lissy93/web-check · warning · Error
hackerTarget unavailable
Error message
hackerTarget unavailable
What it means
hackerTarget's hostsearch endpoint returns plain text; on failure it returns text containing 'error', 'api count', or 'quota'. If the body is empty or matches that pattern, this error is thrown. It is effectively a quota/availability detector for hackertarget.com's free tier.
Source
Thrown at api/subdomains.js:40
};
const crtSh = async (domain) => {
const res = await httpGet('https://crt.sh/', {
params: { q: `%.${domain}`, output: 'json' },
headers: { Accept: 'application/json' },
timeout: SOURCE_TIMEOUT,
});
if (!Array.isArray(res.data)) throw new Error('crt.sh returned an unexpected response');
return res.data.flatMap((row) => String(row?.name_value ?? '').split('\n'));
};
const hackerTarget = async (domain) => {
const res = await httpGet('https://api.hackertarget.com/hostsearch/', {
params: { q: domain },
timeout: SOURCE_TIMEOUT,
});
const body = typeof res.data === 'string' ? res.data : '';
if (!body || /error|api count|quota/i.test(body)) throw new Error('hackerTarget unavailable');
return body.split('\n').map((line) => line.split(',')[0]);
};
const SOURCES = [
{ name: 'certSpotter', lookup: certSpotter },
{ name: 'crt.sh', lookup: crtSh },
{ name: 'hackerTarget', lookup: hackerTarget },
];
const isTransient = (error) => {
const status = error.response?.status;
if (status && status < 500) return false;
return true;
};
const subdomainsHandler = async (url) => {
const { hostname } = parseTarget(url);
if (isIpAddress(hostname)) {View on GitHub (pinned to af1a97759f)
Solutions
- Expect and tolerate failure: this source should degrade gracefully while certSpotter/crt.sh still answer
- Reduce request frequency or cache subdomain results per domain
- Purchase hackertarget API access or run from a different egress if the quota is the bottleneck
Example fix
// before
const hosts = await hackerTarget(domain); // throws 'hackerTarget unavailable' after quota
// after
let hosts = [];
try { hosts = await hackerTarget(domain); }
catch (e) { if (/quota|api count/i.test(e.message)) console.warn('hackerTarget quota hit; skipping'); else throw e; } Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
const isUsableBody = (s) => typeof s === 'string' && s.length > 0 && !/error|api count|quota/i.test(s);
Try / catch
try { return await hackerTarget(domain); }
catch (e) {
if (e.message === 'hackerTarget unavailable') { console.warn('skipping hackertarget'); return []; }
throw e;
} Prevention
- Assume the free quota will run out; design for source absence
- Cache hostsearch results per domain
- Consider paid hackertarget access or alternate sources for high-volume pipelines
When it happens
Trigger: Exceeding hackertarget's free daily API count for your IP, receiving their literal error text, or an empty response body.
Common situations: Repeated subdomain enumeration from one IP or CI runner exhausting the free quota; shared NAT egress (office/VPN) pooling many users into one quota.
Related errors
AI-assisted analysis of lissy93/web-check@af1a97759f (2026-08-27).
Data as JSON: /api/errors/bbfab4ae17c0fa12.
Report an issue: GitHub.