Query A, AAAA, CNAME, MX, NS, TXT, SOA, PTR, SRV, CAA, DNSKEY and DS records through any public resolver with one JSON request. It's the same API that powers DNS Robot's DNS Lookup and DNS propagation checker.
No key, no account. Send a POST request and read JSON.
Ask Google, Cloudflare, Quad9 or any public DNS server by IP.
DNSKEY and DS records come from Cloudflare's DNS-over-HTTPS resolver.
Look up the A records of example.com through Cloudflare's resolver:
curl -X POST https://dnsrobot.net/api/dns-query \
-H "Content-Type: application/json" \
-d '{"domain":"example.com","recordType":"A","dnsServer":"1.1.1.1"}'{
"status": "success",
"responseTime": 4,
"resolvedIPs": ["172.66.147.243", "104.20.23.154"],
"dnsServer": "1.1.1.1",
"recordType": "A",
"domain": "example.com",
"method": "dns-node",
"debug": "Found 2 records"
}POST https://dnsrobot.net/api/dns-query
Content-Type: application/jsonRequest body fields:
| Field | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Domain to query (max 253 characters). Underscore names such as _dmarc.example.com and _sip._tcp.example.com are accepted. For PTR, pass an IPv4 or full IPv6 address. |
| recordType | string | Yes | One of A, AAAA, CNAME, MX, NS, TXT, SOA, PTR, SRV, CAA, DNSKEY, DS. |
| dnsServer | string | Yes | IPv4 address of the public resolver to ask, e.g. 8.8.8.8. Private, loopback and reserved addresses are rejected. |
| timeout | number | No | Milliseconds to wait for the resolver, 1000–10000. Default 5000. |
| Field | Meaning |
|---|---|
| status | "success" when the resolver answered (with or without records), "error" when the lookup failed. |
| resolvedIPs | Array of record values as strings (see the formats below). Empty when no records of that type exist. |
| responseTime | Time the lookup took, in milliseconds. |
| errorMessage | Present when status is "error", e.g. NXDOMAIN - Domain does not exist, DNS server timeout, DNS server failure. |
| dnsServer · recordType · domain | Echo of the request, with recordType upper-cased. |
| debug | Short human-readable summary such as "Found 2 records". |
No records of the requested type is a normal answer, not an error: you get status: "success" with an empty array.
{
"status": "success",
"resolvedIPs": [],
"recordType": "DNSKEY",
"domain": "spidyhost.com",
"debug": "No records of this type exist for this domain",
...
}DNS failures also return HTTP 200, with status: "error" and an errorMessage:
{
"status": "error",
"responseTime": 7,
"resolvedIPs": [],
"errorMessage": "NXDOMAIN - Domain does not exist",
"dnsServer": "8.8.8.8",
"recordType": "A",
"domain": "no-such-domain-dnsrobot-test.com",
"method": "dns-node"
}| Type | Each value contains | Example |
|---|---|---|
| A | IPv4 address | 172.66.147.243 |
| AAAA | IPv6 address | 2001:db8::1 |
| CNAME | Target hostname | example.com.cdn.cloudflare.net |
| MX | priority exchange | 10 alt1.gmail-smtp-in.l.google.com |
| NS | Nameserver hostname | ns1.example.net |
| TXT | Full text (long records joined) | v=spf1 include:_spf.google.com ~all |
| SOA | Seven labelled strings | Primary NS: …, Hostmaster: …, Serial: …, Refresh/Retry/Expire/Min TTL |
| PTR | Hostname for an IP | dns.google |
| SRV | priority weight port target | 10 60 5060 sip.example.com |
| CAA | flags tag "value" | 0 issue "letsencrypt.org" |
| DNSKEY | flags protocol algorithm key | 256 3 13 oJMRESz5E4gYzS/q6XDrvU1q… |
| DS | key-tag algorithm digest-type digest | 2371 13 2 32996839a6d8… |
DNSKEY and DS are always fetched through Cloudflare's DNS-over-HTTPS service, so the dnsServerfield doesn't change their answer. A domain without DNSSEC returns an empty array for both.
| Status | When |
|---|---|
| 200 | The lookup ran. Check status: "success" (records or none) or "error" (NXDOMAIN, timeout, SERVFAIL…). |
| 400 | Invalid input: bad domain, unknown record type, malformed or non-public dnsServer, timeout out of range. |
| 429 | Rate limit reached. Wait for the number of seconds in the Retry-After header. |
HTTP/1.1 400 Bad Request
{ "error": "Invalid input parameters", "details": "Invalid domain, SRV record, or IP address format" }
HTTP/1.1 429 Too Many Requests
Retry-After: 120
{ "error": "Rate limit exceeded", "details": "Max 600 requests per 10 minutes per IP. Retry after 120s." }Per client IP, sliding window. Plenty for scripts, CI checks and dashboards.
Set per request with timeout. The default is 5 seconds.
dnsServer must be a public IPv4 address. Private and reserved ranges are rejected.
The API is free and provided as is, without an uptime guarantee. Cache results where you can, back off when you receive a 429, and if you use it in a public project, a link to dnsrobot.net is appreciated. Use is subject to the terms of service.
const res = await fetch("https://dnsrobot.net/api/dns-query", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ domain: "gmail.com", recordType: "MX", dnsServer: "8.8.8.8" }),
})
const data = await res.json()
if (res.ok && data.status === "success") {
console.log(data.resolvedIPs) // ["5 gmail-smtp-in.l.google.com", ...]
} else {
console.error(data.errorMessage ?? data.details)
}import requests
r = requests.post(
"https://dnsrobot.net/api/dns-query",
json={"domain": "example.com", "recordType": "TXT", "dnsServer": "9.9.9.9"},
timeout=15,
)
data = r.json()
if r.ok and data["status"] == "success":
for record in data["resolvedIPs"]:
print(record)
else:
print("Error:", data.get("errorMessage") or data.get("details"))# Compare one record across several public resolvers (a mini propagation check)
for ns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
curl -s -X POST https://dnsrobot.net/api/dns-query -H "Content-Type: application/json" \
-d "{\"domain\":\"example.com\",\"recordType\":\"A\",\"dnsServer\":\"$ns\"}" \
| jq -c '{dnsServer, resolvedIPs}'
done| dnsServer | Provider |
|---|---|
| 8.8.8.8 | Google Public DNS |
| 1.1.1.1 | Cloudflare |
| 9.9.9.9 | Quad9 |
| 208.67.222.222 | OpenDNS (Cisco) |
| 94.140.14.14 | AdGuard DNS |
Not sure which one to pick? The DNS Speed Test measures which resolver is fastest from your location, and the MX Lookup and SPF Checker tools build on the same lookups with extra analysis.