API reference#

domainsearch answers one question, is this domain registered?, over a plain JSON API. No account, no API key, no cookies. Base URL:

https://domainsearch24.eu/api/v1

How availability is determined#

Every check runs through layered signals, ordered by cost and freshness, and never guesses. The availability status is one of:

Status Meaning
registered The domain is taken.
free The registry itself answered "not registered" (RDAP 404).
unknown No signal was available: see the reason field.

Each answer names its source:

Source Layer Freshness
czds ICANN zone files: every delegated name per covered gTLD ≤ 24 h
commoncrawl Common Crawl web-graph domain set (~120 M domains) months
dns NS delegation probe: works for every TLD live
rdap The registry's own RDAP answer: the only source that can assert free live

Two important consequences:

GET /check#

GET /api/v1/check?domains=example.com,example.io[&fast=1]

Checks up to 30 comma-separated domains and returns all results in one response (extra domains beyond 30 are dropped). Domains must be registrable names in punycode (IDNs are not auto-encoded). Whole-batch budget: ~9 s; slow registries yield per-domain unknown and retries are cheap (availability results are cached server-side: registered 24 h, free 1 h, unknown 10 min).

fast=1 skips RDAP and answers from the local layers only: milliseconds, but it can assert registered, never free. Use it to pre-filter candidate lists before confirming the survivors with a full check (or use streaming and get both in one request).

curl 'https://domainsearch24.eu/api/v1/check?domains=example.com,zqhx.dev'
{
  "results": [
    {"domain": "example.com", "status": "registered", "source": "czds"},
    {"domain": "zqhx.dev", "status": "free", "source": "rdap"}
  ]
}

GET /check/{domain}#

The curl-friendly single-domain form. Same semantics, bare result object.

curl https://domainsearch24.eu/api/v1/check/example.com
{"domain": "example.com", "status": "registered", "source": "czds"}

GET /check/stream#

GET /api/v1/check/stream?domains=example.com,example.io[&fast=1]

Same input as /check, but the response is NDJSON (application/x-ndjson): one result object per line, written as each domain resolves. Local-layer answers arrive in milliseconds while RDAP confirmations trail in over a few seconds: ideal for progressive UIs. Line order is completion order, not input order; match on domain. The stream ends when every domain has answered (budget ~15 s).

curl -N 'https://domainsearch24.eu/api/v1/check/stream?domains=a.com,b.io,c.dev'

GET /bulk/stream#

GET /api/v1/bulk/stream?label=acme[&confirm=1][&tlds=com,io,dev]

The bulk search behind the landing page: ONE label checked across every delegated TLD (~1,450 domains) on a single NDJSON stream.

By default only the fast local layers run (zone files, Common Crawl, DNS): seconds for the whole TLD space, no registry traffic. A clean local miss classes as free: no zone entry, no crawl entry, NXDOMAIN. Its strict status stays unknown: only a registry can formally assert free: and the registrar checkout is the final word either way.

tlds=com,io,dev restricts the sweep to a comma-separated subset (unknown TLDs are ignored). DNS probe outcomes are cached server-side for 24 hours, so repeated sweeps are effectively instant.

confirm=1 adds a second phase: RDAP for the still-unknown names on RDAP-capable TLDs, popular TLDs first, until the ~90 s budget runs out. Upgrade lines stream with the same domain; a confirm line supersedes the local one (upgrading assumed-free to registry-confirmed free, or catching the rare registered-but-undelegated name).

Each line adds a class refining the raw status for filtering:

class Meaning
taken Registered.
free No registration found (clean local miss), or registry-confirmed when status is free.
premium Registered with registry status reserved: typically premium/registry-held inventory.
aftermarket Registered, but delegated to a known parking/for-sale marketplace nameserver (heuristic).
unknown No signal either way: e.g. the DNS probe failed, or confirmation is pending.

The stream opens with {"label":"acme","total":1438} and closes with {"done":true,"confirm":…,"queued":…,"confirmed":…,"truncated":…}: truncated: true means the confirmation budget ran out before every queued name was verified.

curl -N 'https://domainsearch24.eu/api/v1/bulk/stream?label=acme'

Bulk searches are rate limited per IP as whole searches (they already fan out server-side); API keys lift the limit.

GET /tlds#

Every delegated root-zone TLD (per IANA) with capability flags:

{"tlds": [{"tld": "com", "rdap": true, "zone": true}, ...]}

Cacheable for an hour; the underlying sources change at most daily.

GET /status#

Layer readiness and uptime: also our health check:

{
  "ok": true,
  "uptime_s": 86400,
  "layers": {
    "dns": {"enabled": true, "ready": true},
    "rdap": {"enabled": true, "ready": true},
    "czds": {"enabled": true, "ready": true, "detail": "853 zones indexed"},
    "commoncrawl": {"enabled": true, "ready": true}
  }
}

Errors#

Errors use one envelope, always JSON:

{"error": {"code": "rate_limited", "message": "anonymous rate limit exceeded; retry later or use an API key"}}
HTTP code When
400 invalid_request No domains given.
404 not_found Unknown endpoint.
429 rate_limited Anonymous allowance exhausted: honor Retry-After.
501 unavailable Checking is not configured on this deployment.

Malformed domains are not request errors: they come back as per-domain unknown results with a reason, so one bad name never fails a batch.

Rate limits & keys#

Anonymous use is limited per IP, per domain checked (a 30-domain batch costs 30 units): 120 domains/minute with burst headroom of twice that. That is plenty for interactive use.

Calling the API from a service? An API key lifts the limit: request one at liam@domainsearch24.eu and send it as Authorization: Bearer <key>.

CORS & OpenAPI#

The API sends Access-Control-Allow-Origin: *: call it straight from the browser. A machine-readable spec is at /api/openapi.yaml; this page is also served as plain markdown at /docs.md for LLM agents (see /llms.txt).