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

  1. Expect and tolerate failure: this source should degrade gracefully while certSpotter/crt.sh still answer
  2. Reduce request frequency or cache subdomain results per domain
  3. 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

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.