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}]
}

Mail server check

GET/api/v1/mail-check/{domain}

Resolves the MX hosts (forward), checks their reverse DNS (PTR) with FCrDNS match and the TCP availability of the common mail ports (SMTP, IMAP, POP3) and web ports. Connects only to public target IPs (SSRF-safe). Extra burst limit because of the port probes. Errors: 400, 429.

Example
curl https://dns-doctor.com/api/v1/mail-check/example.com
Response (abridged)
{
  "api": "v1",
  "domain": "example.com",
  "acceptsMail": true,
  "nullMx": false,
  "mail": [
    {
      "host": "mail.example.com",
      "priority": 10,
      "ipv4": ["203.0.113.10"],
      "ipv6": [],
      "ptr": [{"ip": "203.0.113.10", "names": ["mail.example.com"], "matchesForward": true}],
      "ports": [
        {"port": 25, "service": "SMTP", "state": "open"},
        {"port": 587, "service": "Submission", "state": "open"},
        {"port": 993, "service": "IMAPS", "state": "open"}
      ]
    }
  ],
  "web": null,
  "checkedAt": "2026-07-18T09:30:00.000Z"
}

SEO & AI visibility

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

Fetches the page (soft-404-guarded), robots.txt and the metadata and scores how well the domain is visible to search engines and AI assistants. Findings in four categories: indexing, content, technical and ai (AI-crawler access). Localized via ?lang=de. Each run makes several outbound requests, so there is an extra burst limit. Errors: 400, 429.

Example
curl 'https://dns-doctor.com/api/v1/seo-check/example.com?lang=en'
Response (abridged)
{
  "api": "v1",
  "domain": "example.com",
  "finalUrl": "https://example.com/",
  "fetchedAt": "2026-07-18T09:30:00.000Z",
  "ttfbMs": 142,
  "score": 94,
  "pageTitle": "Example Domain",
  "error": null,
  "findings": [
    {
      "id": "https",
      "category": "technical",
      "severity": "ok",
      "title": "HTTPS active",
      "detail": "The page is served over HTTPS."
    },
    {
      "id": "ai-crawlers",
      "category": "ai",
      "severity": "warn",
      "title": "Some AI crawlers are blocked",
      "detail": "robots.txt disallows GPTBot."
    }
  ]
}

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}
}

MCP server (for AI assistants)

POST/mcp

Every check is also available as an MCP server (Model Context Protocol) for AI assistants like Claude: stateless over JSON-RPC 2.0 at https://dns-doctor.com/mcp, with the same engine, auth and rate limits as this REST API.

MCP docs: tools, connector URL and examples →

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.