dns-doctor
regfish ↗

For developers

API

Every dns-doctor.com check and tool is also available as a JSON API: free, CORS-enabled (Access-Control-Allow-Origin: *, including POST and the Authorization header) and usable without signup. Check results are cached server-side for 5 minutes.

Domain check

GET/api/v1/check/{domain}?lang=en|de

Complete health report for a domain: a score from 0 to 100 and findings in the categories dns, email, web and security, each with a severity (ok, info, warn, problem), an explanation and, where possible, a concrete fix including the DNS record. The lang parameter selects the language of all texts (default: en). Errors: 400 invalid_domain, 429 rate_limited.

Example
curl 'https://dns-doctor.com/api/v1/check/example.com?lang=en'
Response (abridged)
{
  "api": "v1",
  "domain": "example.com",
  "displayDomain": "example.com",
  "resolvable": true,
  "score": 92,
  "findings": [
    {
      "id": "email-spf-missing",
      "category": "email",
      "severity": "problem",
      "title": "No SPF record found",
      "detail": "Without SPF, any server may send mail as example.com.",
      "fix": {
        "steps": ["Create this TXT record for your domain."],
        "record": {"host": "@", "type": "TXT", "value": "v=spf1 mx ~all"}
      }
    }
  ],
  "summary": {"ok": 12, "info": 2, "warn": 1, "problem": 1},
  "checkedAt": "2026-07-15T09:30:00.000Z",
  "locale": "en"
}

DNS lookup

GET/api/v1/lookup/{name}/{type}

Raw records via DNSSEC-validating resolvers. Supported types: A, NS, CNAME, SOA, PTR, MX, TXT, AAAA, SRV, DS, DNSKEY and CAA. For PTR, name may also be an IP address; the arpa mapping happens automatically. status is the DNS RCODE (0 = NOERROR, 3 = NXDOMAIN), ad tells you whether the answer is DNSSEC-validated. Errors: 400, 429, 502.

Example
curl https://dns-doctor.com/api/v1/lookup/example.com/MX
Response (abridged)
{
  "api": "v1",
  "name": "example.com",
  "type": "MX",
  "typeCode": 15,
  "status": 0,
  "ad": true,
  "answers": [
    {"name": "example.com", "type": 15, "ttl": 3600, "data": "10 mail.example.com."}
  ]
}

Propagation

GET/api/v1/propagation/{name}/{type}

Queries the same name and type on five public resolvers (cloudflare, google, alidns, dnssb, adguard) and compares the answers. consistency shows how many reachable resolvers agree; consistent is true once all reachable resolvers return the same answer set. Handy after record changes to watch propagation. Errors: 400, 429.

Example
curl https://dns-doctor.com/api/v1/propagation/regfish.de/A
Response (abridged)
{
  "api": "v1",
  "name": "regfish.de",
  "type": "A",
  "resolvers": [
    {
      "id": "cloudflare",
      "label": "Cloudflare (1.1.1.1)",
      "reachable": true,
      "status": 0,
      "ad": true,
      "answers": [{"ttl": 300, "data": "203.0.113.10"}]
    },
    {
      "id": "google",
      "label": "Google (8.8.8.8)",
      "reachable": true,
      "status": 0,
      "ad": true,
      "answers": [{"ttl": 287, "data": "203.0.113.10"}]
    }
  ],
  "consistency": {"reachable": 5, "total": 5, "agreeing": 5, "consistent": true}
}

Domain availability

GET/api/v1/availability/{domain}

Non-binding availability check via public RDAP; for registered domains it includes the registrar plus creation and expiry dates. Important: TLDs without public RDAP (e.g. .de) return state "unknown" with noRdapForTld=true; only the responsible registry decides at registration time. Errors: 400, 429.

Example
curl https://dns-doctor.com/api/v1/availability/regfish.com
Response (abridged)
{
  "api": "v1",
  "domain": "regfish.com",
  "state": "registered",
  "noRdapForTld": false,
  "registrar": "regfish GmbH",
  "created": "2004-09-13T10:22:41Z",
  "expires": "2027-09-13T10:22:41Z",
  "disclaimer": "Non-binding. Only the responsible registry decides at registration time."
}

DKIM check

GET/api/v1/dkim/{domain}/{selector}

Fetches selector._domainkey.domain as TXT and inspects the DKIM key: key type (rsa or ed25519), key length in bits, revoked (empty p=) and testing (t=y). Without a DKIM record you get found=false with no further fields except status (the DNS RCODE). Errors: 400, 429, 502.

Example
curl https://dns-doctor.com/api/v1/dkim/regfish.de/k1
Response (abridged)
{
  "api": "v1",
  "domain": "regfish.de",
  "selector": "k1",
  "name": "k1._domainkey.regfish.de",
  "found": true,
  "valid": true,
  "revoked": false,
  "testing": false,
  "keyType": "rsa",
  "keyBits": 2048,
  "record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
}

DNSSEC check

GET/api/v1/dnssec/{domain}

Reads DS and DNSKEY records, computes key tags and shows in links which DS entries match a published DNSKEY. status is unsigned (no DS), valid (resolver-validated and at least one DS matches) or broken. Errors: 400, 429, 502.

Example
curl https://dns-doctor.com/api/v1/dnssec/denic.de
Response (abridged)
{
  "api": "v1",
  "domain": "denic.de",
  "status": "valid",
  "adValidated": true,
  "ds": [
    {"keyTag": 26902, "algorithm": "ECDSAP256SHA256", "digestType": "SHA-256", "digest": "4a7c..."}
  ],
  "dnskeys": [
    {"keyTag": 26902, "flags": 257, "algorithm": "ECDSAP256SHA256", "role": "ksk"},
    {"keyTag": 43547, "flags": 256, "algorithm": "ECDSAP256SHA256", "role": "zsk"}
  ],
  "links": [{"keyTag": 26902, "matched": true}]
}

IDN/Punycode

GET/api/v1/idn/{name}

Converts domain names between Unicode and Punycode (ASCII), in both directions. Pure conversion without network access, therefore not rate-limited. Errors: 400.

Example
curl https://dns-doctor.com/api/v1/idn/xn--mller-kva.de
Response (abridged)
{
  "api": "v1",
  "input": "xn--mller-kva.de",
  "ascii": "xn--mller-kva.de",
  "unicode": "müller.de"
}

Record generators

POST/api/v1/generate/{kind}

Record generators as an API, no DNS queries. kind is spf, dmarc, caa or mta-sts; the JSON body mirrors the fields of the corresponding web tools: spf (allowA, allowMx, ip4, ip6, includes, all), dmarc (policy, subdomainPolicy, rua, ruf, pct, adkim, aspf, fo, domain), caa (issue, issuewild, iodef, critical; the value ";" in the issue array forbids all certificate issuance) and mta-sts (domain, mode, mx, maxAgeDays, id, tlsRptEmail). Warnings and errors are deliberately structured codes (e.g. too-many-lookups) instead of prose so integrations can localize them. Errors: 400, 405, 429.

Example
curl -X POST 'https://dns-doctor.com/api/v1/generate/spf' \
  -H 'Content-Type: application/json' \
  -d '{"allowMx": true, "ip4": ["203.0.113.10"], "all": "softfail"}'
Response (abridged)
{
  "api": "v1",
  "kind": "spf",
  "host": "@",
  "type": "TXT",
  "record": "v=spf1 mx ip4:203.0.113.10 ~all",
  "lookupCount": 1,
  "warnings": [],
  "errors": []
}
Example
curl -X POST 'https://dns-doctor.com/api/v1/generate/mta-sts' \
  -H 'Content-Type: application/json' \
  -d '{"domain": "regfish.de", "mode": "testing", "mx": ["mx1.regfish.de", "mx2.regfish.de"]}'
Response (abridged)
{
  "api": "v1",
  "kind": "mta-sts",
  "dnsRecord": {"host": "_mta-sts.regfish.de", "type": "TXT", "value": "v=STSv1; id=202607150930"},
  "policyFile": "version: STSv1\nmode: testing\nmx: mx1.regfish.de\nmx: mx2.regfish.de\nmax_age: 604800\n",
  "policyUrl": "https://mta-sts.regfish.de/.well-known/mta-sts.txt",
  "warnings": []
}

Email header analysis

POST/api/v1/header-analysis

Parses a raw email header: Received hops with time deltas, Authentication-Results (SPF, DKIM, DMARC), the key sender fields and an alignment hint. Body as text/plain (raw header) or JSON {"raw": "..."}, at most 64 KiB. Privacy: processing is ephemeral, nothing is stored or passed on; the response is sent with Cache-Control: no-store. Errors: 400, 413, 429.

Example
curl -X POST 'https://dns-doctor.com/api/v1/header-analysis' \
  -H 'Content-Type: text/plain' \
  --data-binary @header.txt
Response (abridged)
{
  "api": "v1",
  "hops": [
    {"index": 1, "from": "client.example.net", "by": "mail.example.net", "with": "ESMTPSA"},
    {"index": 2, "from": "mail.example.net", "by": "mx.regfish.de", "with": "ESMTPS", "deltaSec": 1}
  ],
  "auth": {"spf": "pass", "dkim": "pass", "dmarc": "pass"},
  "fields": {"from": "Alice <alice@example.net>", "returnPath": "<alice@example.net>"},
  "alignment": {"fromDomain": "example.net", "returnPathDomain": "example.net", "aligned": true}
}

Rate limits & API keys

AnonymousWith API key
Requests per day50 per IP5000
AuthenticationnoneX-Api-Key (HTTP header)

Higher limits are available with an API key via your regfish account: sign up for free →

Example
curl -H 'X-Api-Key: rf_xxxxxxxx' \
  'https://dns-doctor.com/api/v1/check/example.com'

Already have a regfish API key (api.regfish.de/.com)? Use it directly: as Authorization: Bearer or X-Api-Key. It is verified server-side with regfish and counts like a dns-doctor key, i.e. 5000 requests per day.

Example
curl -H 'Authorization: Bearer <regfish-token>' \
  'https://dns-doctor.com/api/v1/check/regfish.de'

Exception: /api/v1/idn is a pure conversion and is not rate-limited.

Badge

GET/badge/{domain}.svg

Embeddable SVG badge showing the current DNS health score of your domain. The color depends on the score and the badge is cached for 1 hour. Live example:

DNS health badge

Markdown (e.g. for your README)
[![DNS health](https://dns-doctor.com/badge/YOUR-DOMAIN.svg)](https://dns-doctor.com/?domain=YOUR-DOMAIN)
HTML (for your website)
<a href="https://dns-doctor.com/?domain=YOUR-DOMAIN">
  <img src="https://dns-doctor.com/badge/YOUR-DOMAIN.svg" alt="DNS health" />
</a>

Replace YOUR-DOMAIN with your domain, e.g. example.com.

OpenAPI & fair use

A machine-readable description of the API is available as an OpenAPI 3.1 spec: /api/v1/openapi.json

Fair use: the API is meant for integrations, monitoring and occasional automated checks, not for mass scraping of entire domain lists. Abuse will lead to blocking.