GET/api/v2/cname
CNAME lookup API
Follow a name's CNAME chain hop by hop to its addresses, with the platform behind it and dangling or looping targets.
- 20 calls a minute per IP
- Same engine as the CNAME Lookup tool
{
"query": {
"name": "www.wikipedia.org"
},
"unicode": null,
"verdict": "alias",
"cnames": 1,
"chain": [
{
"name": "www.wikipedia.org",
"zone": "wikipedia.org",
"status": "cname",
"cnames": [
{
"target": "dyna.wikimedia.org",
"ttl": 86400
}
],
"otherTypes": [],
"ipv4": [],
"ipv6": [],
"aTtl": null,
"aaaaTtl": null,
"negativeTtl": null,
"apex": false,
"answeredBy": "authoritative",
"server": "ns1.wikimedia.org",
"ip": "208.80.153.231",
"authoritative": true,
"dnsOperators": [
{
"id": "domain:wikimedia.org",
"name": "wikimedia.org"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 542
},
{
"name": "dyna.wikimedia.org",
"zone": "wikimedia.org",
"status": "address",
"cnames": [],
"otherTypes": [],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"aTtl": 180,
"aaaaTtl": 180,
"negativeTtl": null,
"apex": false,
"answeredBy": "authoritative",
"server": "ns1.wikimedia.org",
"ip": "208.80.153.231",
"authoritative": true,
"dnsOperators": [
{
"id": "domain:wikimedia.org",
"name": "wikimedia.org"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 498
}
],
"end": {
"reason": "address",
"name": "dyna.wikimedia.org",
"loopsBackTo": null
},
"target": {
"name": "dyna.wikimedia.org",
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"network": {
"asn": 14907,
"name": "Wikimedia Foundation",
"prefix": "103.102.166.0/24",
"country": "US"
}
},
"platform": null,
"lowestTtl": {
"ttl": 180,
"name": "dyna.wikimedia.org",
"type": "A"
},
"dnssec": [
{
"name": "www.wikipedia.org",
"validated": false
},
{
"name": "dyna.wikimedia.org",
"validated": false
}
],
"zoneAliases": {
"zone": "wikipedia.org",
"mx": [
{
"host": "mx-in1001.wikimedia.org",
"cname": null
},
{
"host": "mx-in2001.wikimedia.org",
"cname": null
}
],
"ns": [
{
"host": "ns2.wikimedia.org",
"cname": null
},
{
"host": "ns0.wikimedia.org",
"cname": null
},
{
"host": "ns1.wikimedia.org",
"cname": null
}
]
},
"copies": [
{
"source": "google",
"status": "ok",
"chain": [
{
"name": "www.wikipedia.org",
"target": "dyna.wikimedia.org",
"ttl": 15282
}
],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2620:0:861:ed1a::1"
],
"dnssecValidated": false,
"tookMs": 278
},
{
"source": "cloudflare",
"status": "ok",
"chain": [
{
"name": "www.wikipedia.org",
"target": "dyna.wikimedia.org",
"ttl": 86390
}
],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"dnssecValidated": false,
"tookMs": 261
}
],
"issues": [],
"tookMs": 2290
}How it works
Follows the chain one name at a time at each zone's own nameservers (recursion off), so every hop shows which zone answered, who runs its DNS, the record's own TTL and whether the server is authoritative; Google's and Cloudflare's cached copies of the whole chain come beside it. The platform behind the target is named from documented CNAME suffixes (CloudFront, Fastly, GitHub Pages, Vercel…).
Findings come back as issues: a dangling target (NXDOMAIN at the end of the chain, a takeover risk), loops, more than 8 aliases in a row (RFC 9460 §10.2), a CNAME at a zone apex or beside other data (RFC 2181 §10.1), MX or NS hosts that are aliases, platforms that answer any name (DNS can't tell a deleted site there), and older targets.
Honest as the CNAME Lookup page: NXDOMAIN at the end of a chain means the target doesn't exist, never the name; a SERVFAIL or a timeout is unresolved, never "doesn't exist"; on Cloudflare's nameservers a proxied or flattened record looks like an A record, so the verdict is hidden (may be proxying), never a claim.
Answers kept: Kept for the chain's lowest TTL, 30 seconds to 5 minutes (30 seconds when a part failed), shared with the CNAME Lookup page. A kept answer carries an `Age` header, and the resolvers' TTLs are counted down.
Query parameters
namestringrequiredA host name, looked up exactly as given (www.stays); a URL or an e-mail address works too, and IDNs in Unicode are sent as Punycode.
Response fields
200 with this JSON object, plus tookMs, and incomplete with warnings when a source failed. Fields marked optional appear only when they apply.
queryobjectalwaysWhat was looked up, normalised (lower case, no trailing dot, IDNs as Punycode).namestringalwaysThe name looked up, lower case, IDNs as Punycode.
unicodestring or nullalwaysThe name in Unicode, when it is an IDN.verdictstringalwaysalias(CNAMEs ending at addresses),no_cname(its own addresses),hidden(no CNAME visible, every address Cloudflare's: may be proxied or flattened),dangling(the target doesn't exist),loop,long_chain(more than 8 aliases),dkim_key(a DKIM selector's chain ending at its TXT key),target_no_address,unresolved(couldn't follow past a hop),nxdomain(the name doesn't exist),nodata(exists, no CNAME and no address) orfailed.one of
"alias","no_cname","hidden","dangling","loop","long_chain","dkim_key","target_no_address","unresolved","nxdomain","nodata","failed"cnamesintegeralwaysCNAME records followed (each once, also in a loop).chainarray of objectsalwaysEvery name of the chain, the one looked up first.Show 19 fields
namestringalwaysThe name asked.zonestring or nullalwaysThe zone that answered (its apex).statusstringalwaysWhat the zone holds there:cname,address,nodata,nxdomain, or a failure (servfail,refused,timeout,error).one of
"cname","address","nodata","nxdomain","servfail","refused","timeout","error"cnamesarray of objectsalwaysThe CNAME records at the name (more than one is a broken zone).Show 2 fields
targetstringalwaysThe target.ttlintegeralwaysThe TTL as the zone serves it, in seconds.
otherTypesarray of stringsalwaysOther types the zone answered beside the CNAME (not allowed, RFC 2181 §10.1).ipv4array of stringsalwaysA records, at the chain's end.ipv6array of stringsalwaysAAAA records, at the chain's end.aTtlinteger or nullalwaysThe A records' TTL, in seconds.aaaaTtlinteger or nullalwaysThe AAAA records' TTL, in seconds.negativeTtlinteger or nullalwaysFor NXDOMAIN or NODATA: how long the miss is cached, in seconds.apexbooleanalwaysThe name is its zone's apex (a CNAME can't sit there).answeredBystringalwaysWho answered:authoritative(the zone's own nameserver, the fresh truth),google(Google Public DNS's cached copy) orcloudflare(Cloudflare 1.1.1.1's).one of
"authoritative","google","cloudflare"serverstringalwaysThe server that answered.ipstring or nullalwaysIts address.authoritativebooleanalwaysThe AA flag.dnsOperatorsarray of objectsalwaysWho runs the zone's DNS, from its nameservers' names.Show 2 fields
idstringalwaysA stable id, e.g.route53, ordomain:<domain>.namestringalwaysIts name.
zoneOnCloudflarebooleanalwaysThe zone is on Cloudflare's nameservers.platformobject or nullalwaysThe platform this hop's target belongs to.Show 2 fields
idstringalwaysA stable id.namestringalwaysIts name.
tookMsinteger or nullalwaysHow long that answer took, in milliseconds; null when it wasn't timed.
endobject or nullalwaysHow the chain ended.reasonstringalwaysaddress,nodata,nxdomain,loop,long(our 16-hop cap),servfail,refused,timeoutorerror.one of
"address","nodata","nxdomain","loop","long","servfail","refused","timeout","error"namestringalwaysThe name it ended at.loopsBackTointeger or nullalwaysFor a loop: the index inchainthe last target returns to.
targetobject or nullalwaysWhere the chain lands, when it reaches addresses.Show 4 fields
namestringalwaysThe last name.ipv4array of stringsalwaysIts A records.ipv6array of stringsalwaysIts AAAA records.networkobject or nullalwaysThe network behind the address (Team Cymru); null when unknown.Show 4 fields
asnintegeralwaysThe AS number that announces the address.namestringalwaysThe network's name, cleaned ("Google", "Amazon.com").prefixstringalwaysThe announced prefix the address is in, e.g.8.8.8.0/24.countrystringalwaysThe network's registration country (ISO 3166-1 alpha-2), as Team Cymru has it.
platformobject or nullalwaysThe platform behind the chain, named from documented CNAME suffixes; null when none matches.Show 6 fields
idstringalwaysA stable id, e.g.cloudfront,github-pages.namestringalwaysIts name.kindstringalwaysWhat it is.one of
"cdn","hosting","static","builder","shop","lb","steering","storage","setup","dkim","help","marketing","verify"suffixstringalwaysThe documented suffix that matched (the evidence).legacybooleanalwaysAn older target the platform has replaced.documentedbooleanalwaysThe suffix is in the platform's documentation.
lowestTtlobject or nullalwaysThe lowest TTL in the chain as the zones serve it: how often that part is fetched again (not the time an edit takes).ttlintegeralwaysThe TTL, in seconds.namestringalwaysWhose record.typestringalwaysIts type.one of
"CNAME","A","AAAA"
dnssecarray of objects or nullalwaysEach hop asked on its own with DNSSEC; null when not checked.namestringalwaysThe name.validatedboolean or nullalwaysGoogle validated it (AD); null when no answer.
zoneAliasesobject or nullalwaysThe name's zone's MX and NS hosts, checked for being aliases (RFC 2181 §10.3).zonestringalwaysThe zone.mxarray of objects or nullalwaysIts MX hosts; null when the question failed.Show 2 fields
hoststringalwaysThe host.cnamestring or nullalwaysIts CNAME target, when it is an alias.
nsarray of objects or nullalwaysIts NS hosts; null when the question failed.Show 2 fields
hoststringalwaysThe host.cnamestring or nullalwaysIts CNAME target, when it is an alias.
copiesarray of objectsalwaysGoogle's and Cloudflare's cached copies of the whole chain (TTLs are the time left).Show 7 fields
sourcestringalwaysgoogleorcloudflare.one of
"google","cloudflare"statusstringalwaysThe answer:ok(records came back),nodata(the name exists without them),nxdomain(no such name),servfail,refused,timeout,errororunreadable(an answer our decoder refuses).one of
"ok","nodata","nxdomain","servfail","refused","timeout","error","unreadable"chainarray of objectsalwaysThe CNAMEs the answer followed, in order.Show 3 fields
namestringalwaysThe alias.targetstringalwaysThe name it points to.ttlintegeralwaysThe record's TTL, in seconds.
ipv4array of stringsalwaysThe addresses it ended at (A).ipv6array of stringsalwaysThe addresses it ended at (AAAA).dnssecValidatedbooleanalwaysThe resolver validated the whole answer.tookMsintegeralwaysHow long that answer took, in milliseconds.
issuesarray of objectsalwaysProblems found in the target's configuration, worst first. Empty when there are none.severitystringalwayserrorbreaks something,warningrisks it,infois worth knowing.one of
"error","warning","info"codestringalwaysStable machine-readable code.messagestringalwaysThe problem and what to do about it, in plain English.
Errors
429rate_limitedAlso when the domain was looked up 30 times in the last minute by all callers together (a lookup that isn't kept asks its nameservers directly).
Plus the errors every endpoint can return: 400 for a missing or unreadable parameter, 429 past the limit, 503 when every source failed.
Code samples
curl "https://dnsrobot.net/api/v2/cname?name=www.wikipedia.org"const params = new URLSearchParams({ name: "www.wikipedia.org" });
const res = await fetch(`https://dnsrobot.net/api/v2/cname?${params}`);
const data = await res.json();
if (!res.ok) throw new Error(data.error.message);
console.log(data.chain);import requests
r = requests.get(
"https://dnsrobot.net/api/v2/cname",
params={"name": "www.wikipedia.org"},
timeout=30,
)
data = r.json()
if not r.ok:
raise RuntimeError(data["error"]["message"])
print(data["chain"])package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
func main() {
q := url.Values{"name": {"www.wikipedia.org"}}
res, err := http.Get("https://dnsrobot.net/api/v2/cname?" + q.Encode())
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]any
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
panic(err)
}
if res.StatusCode != http.StatusOK {
panic(data["error"])
}
fmt.Println(data["chain"])
}<?php
$query = http_build_query(["name" => "www.wikipedia.org"]);
$context = stream_context_create(["http" => ["ignore_errors" => true, "timeout" => 30]]);
$data = json_decode(file_get_contents("https://dnsrobot.net/api/v2/cname?" . $query, false, $context), true);
if (isset($data["error"])) {
throw new RuntimeException($data["error"]["message"]);
}
print_r($data["chain"]);require "net/http"
require "json"
uri = URI("https://dnsrobot.net/api/v2/cname")
uri.query = URI.encode_www_form(name: "www.wikipedia.org")
data = JSON.parse(Net::HTTP.get(uri))
raise data["error"]["message"] if data["error"]
puts data["chain"]// Cargo.toml: reqwest = { version = "0.13", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::get("https://dnsrobot.net/api/v2/cname?name=www.wikipedia.org")?;
let ok = res.status().is_success();
let data: serde_json::Value = res.json()?;
if !ok {
return Err(data["error"]["message"].to_string().into());
}
println!("{}", data["chain"]);
Ok(())
}using System.Text.Json;
using var http = new HttpClient();
var res = await http.GetAsync("https://dnsrobot.net/api/v2/cname?name=www.wikipedia.org");
var data = JsonDocument.Parse(await res.Content.ReadAsStringAsync()).RootElement;
if (!res.IsSuccessStatusCode)
throw new Exception(data.GetProperty("error").GetProperty("message").GetString());
Console.WriteLine(data.GetProperty("chain"));www.wikipedia.org → dyna.wikimedia.org
GET /api/v2/cname?name=www.wikipedia.org{
"query": {
"name": "www.wikipedia.org"
},
"unicode": null,
"verdict": "alias",
"cnames": 1,
"chain": [
{
"name": "www.wikipedia.org",
"zone": "wikipedia.org",
"status": "cname",
"cnames": [
{
"target": "dyna.wikimedia.org",
"ttl": 86400
}
],
"otherTypes": [],
"ipv4": [],
"ipv6": [],
"aTtl": null,
"aaaaTtl": null,
"negativeTtl": null,
"apex": false,
"answeredBy": "authoritative",
"server": "ns1.wikimedia.org",
"ip": "208.80.153.231",
"authoritative": true,
"dnsOperators": [
{
"id": "domain:wikimedia.org",
"name": "wikimedia.org"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 542
},
{
"name": "dyna.wikimedia.org",
"zone": "wikimedia.org",
"status": "address",
"cnames": [],
"otherTypes": [],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"aTtl": 180,
"aaaaTtl": 180,
"negativeTtl": null,
"apex": false,
"answeredBy": "authoritative",
"server": "ns1.wikimedia.org",
"ip": "208.80.153.231",
"authoritative": true,
"dnsOperators": [
{
"id": "domain:wikimedia.org",
"name": "wikimedia.org"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 498
}
],
"end": {
"reason": "address",
"name": "dyna.wikimedia.org",
"loopsBackTo": null
},
"target": {
"name": "dyna.wikimedia.org",
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"network": {
"asn": 14907,
"name": "Wikimedia Foundation",
"prefix": "103.102.166.0/24",
"country": "US"
}
},
"platform": null,
"lowestTtl": {
"ttl": 180,
"name": "dyna.wikimedia.org",
"type": "A"
},
"dnssec": [
{
"name": "www.wikipedia.org",
"validated": false
},
{
"name": "dyna.wikimedia.org",
"validated": false
}
],
"zoneAliases": {
"zone": "wikipedia.org",
"mx": [
{
"host": "mx-in1001.wikimedia.org",
"cname": null
},
{
"host": "mx-in2001.wikimedia.org",
"cname": null
}
],
"ns": [
{
"host": "ns2.wikimedia.org",
"cname": null
},
{
"host": "ns0.wikimedia.org",
"cname": null
},
{
"host": "ns1.wikimedia.org",
"cname": null
}
]
},
"copies": [
{
"source": "google",
"status": "ok",
"chain": [
{
"name": "www.wikipedia.org",
"target": "dyna.wikimedia.org",
"ttl": 15282
}
],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2620:0:861:ed1a::1"
],
"dnssecValidated": false,
"tookMs": 278
},
{
"source": "cloudflare",
"status": "ok",
"chain": [
{
"name": "www.wikipedia.org",
"target": "dyna.wikimedia.org",
"ttl": 86390
}
],
"ipv4": [
"103.102.166.224"
],
"ipv6": [
"2001:df2:e500:ed1a::1"
],
"dnssecValidated": false,
"tookMs": 261
}
],
"issues": [],
"tookMs": 2290
}www.github.com → github.com
GET /api/v2/cname?name=www.github.com{
"query": {
"name": "www.github.com"
},
"unicode": null,
"verdict": "alias",
"cnames": 1,
"chain": [
{
"name": "www.github.com",
"zone": "github.com",
"status": "cname",
"cnames": [
{
"target": "github.com",
"ttl": 3600
}
],
"otherTypes": [],
"ipv4": [],
"ipv6": [],
"aTtl": null,
"aaaaTtl": null,
"negativeTtl": null,
"apex": false,
"answeredBy": "authoritative",
"server": "ns-421.awsdns-52.com",
"ip": "205.251.193.165",
"authoritative": true,
"dnsOperators": [
{
"id": "route53",
"name": "Route 53"
},
{
"id": "ns1",
"name": "NS1"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 39
},
{
"name": "github.com",
"zone": "github.com",
"status": "address",
"cnames": [],
"otherTypes": [],
"ipv4": [
"20.207.73.82"
],
"ipv6": [],
"aTtl": 60,
"aaaaTtl": null,
"negativeTtl": null,
"apex": true,
"answeredBy": "authoritative",
"server": "ns-421.awsdns-52.com",
"ip": "205.251.193.165",
"authoritative": true,
"dnsOperators": [
{
"id": "route53",
"name": "Route 53"
},
{
"id": "ns1",
"name": "NS1"
}
],
"zoneOnCloudflare": false,
"platform": null,
"tookMs": 39
}
],
"end": {
"reason": "address",
"name": "github.com",
"loopsBackTo": null
},
"target": {
"name": "github.com",
"ipv4": [
"20.207.73.82"
],
"ipv6": [],
"network": {
"asn": 8075,
"name": "Microsoft",
"prefix": "20.192.0.0/10",
"country": "US"
}
},
"platform": null,
"lowestTtl": {
"ttl": 60,
"name": "github.com",
"type": "A"
},
"dnssec": [
{
"name": "www.github.com",
"validated": false
},
{
"name": "github.com",
"validated": false
}
],
"zoneAliases": {
"zone": "github.com",
"mx": [
{
"host": "github-com.mail.protection.outlook.com",
"cname": null
}
],
"ns": [
{
"host": "ns-1283.awsdns-32.org",
"cname": null
},
{
"host": "dns4.p08.nsone.net",
"cname": null
},
{
"host": "dns2.p08.nsone.net",
"cname": null
},
// … 5 more items
]
},
"copies": [
{
"source": "google",
"status": "ok",
"chain": [
{
"name": "www.github.com",
"target": "github.com",
"ttl": 1312
}
],
"ipv4": [
"140.82.113.3"
],
"ipv6": [],
"dnssecValidated": false,
"tookMs": 59
},
{
"source": "cloudflare",
"status": "ok",
"chain": [
{
"name": "www.github.com",
"target": "github.com",
"ttl": 3600
}
],
"ipv4": [
"20.207.73.82"
],
"ipv6": [],
"dnssecValidated": false,
"tookMs": 3
}
],
"issues": [],
"tookMs": 416
}Shortened for the page: long lists show their first items.