API documentation
Everything you need to use the NetTrace API in your own tools.
Introduction
The NetTrace API gives you the same checks as this website. No account or API key is needed. Base URL:
https://api.nettrace.eu/v1.0
The check endpoints accept POST; /resolvers is GET. CORS is open (Access-Control-Allow-Origin: *), so you can also call the API directly from a browser.
Requests and responses
Send parameters as form data (application/x-www-form-urlencoded or multipart/form-data) or as JSON. Responses are JSON, compressed with brotli or gzip when your client asks for it.
curl -X POST https://api.nettrace.eu/v1.0/dns-check -d "domain=nettrace.eu" -d "recordType=A"
curl -X POST https://api.nettrace.eu/v1.0/dns-check \
-H "Content-Type: application/json" \
-d '{"domain":"nettrace.eu","recordType":"A"}'
Responses include X-Cache: HIT or MISS and a Cache-Control header with the remaining cache lifetime.
Rate limits and errors
Each IP address gets on average 1 request per second, with bursts up to 30. Above that you get 429 with a Retry-After header. Under exceptional load the API may return 503, also with Retry-After. Cached answers keep working.
400{"error":"Missing domain"}405{"error":"Method not allowed"}429{"error":"Too many requests, please slow down"}503{"error":"Server busy, please retry"}
POST /dns-check
Queries a record at all 84 resolvers at once. Each resolver has its own 2-second timeout, so the answer arrives within about 2 seconds even if a resolver does not respond. A complete check is cached for at least 30 seconds.
| Parameter | Required | Description |
|---|---|---|
domain | yes | Domain name (IDN allowed). For PTR an IP address is also accepted. |
recordType | yes | A AAAA MX NS TXT CNAME SOA PTR SRV CAA NAPTR DS DNSKEY |
stream | no | 1 = live results as NDJSON (see below). May also be a query string. |
Response: an array with one object per resolver. status is ok, nodata, nxdomain, timeout, servfail, refused, formerr, notimp, error or down (skipped because the resolver failed its health check). formerr and notimp mean the resolver does not support the query, e.g. PTR at some filtering resolvers. location_nl holds the location in Dutch. rtt_ms is that resolver's response time, or null on a cache hit.
[
{
"location": "Anycast – nearest PoP (Cisco OpenDNS)",
"location_nl": "Anycast – dichtstbijzijnde PoP (Cisco OpenDNS)",
"ip": "208.67.222.220",
"provider": "OpenDNS",
"dns_results": [
{
"host": "nettrace.eu",
"priority": 10,
"target": "mx1.mijn.host",
"type": "MX"
},
{
"host": "nettrace.eu",
"priority": 20,
"target": "mx2.mijn.host",
"type": "MX"
}
],
"resolved": true,
"status": "ok",
"rtt_ms": 100,
"cached": false
},
{
"location": "Anycast – nearest PoP (Google Public DNS)",
"location_nl": "Anycast – dichtstbijzijnde PoP (Google Public DNS)",
"ip": "8.8.8.8",
"provider": "Google",
"dns_results": [
{
"host": "nettrace.eu",
"priority": 20,
"target": "mx2.mijn.host",
"type": "MX"
},
{
"host": "nettrace.eu",
"priority": 10,
"target": "mx1.mijn.host",
"type": "MX"
}
],
"resolved": true,
"status": "ok",
"rtt_ms": 10,
"cached": false
}
]
400{"error":"Missing domain"}400{"error":"Missing record type"}400{"error":"Invalid record type"}400{"error":"Invalid domain"}
Live streaming
With ?stream=1 (or Accept: application/x-ndjson) you receive each resolver as a separate JSON line as soon as it answers, with the extra fields index (fixed order) and total (number of resolvers).
curl -N -X POST "https://api.nettrace.eu/v1.0/dns-check?stream=1" -d "domain=nettrace.eu" -d "recordType=A"
{"index":37,"total":84,"location":"Anycast – nearest PoP (Cloudflare, secondary)","location_nl":"Anycast – dichtstbijzijnde PoP (Cloudflare, secundair)","ip":"1.0.0.1","provider":"Cloudflare Inc","dns_results":[{"host":"nettrace.eu","ip":"37.1.226.221","type":"A"}],"resolved":true,"status":"ok","rtt_ms":0,"cached":false}
{"index":15,"total":84,"location":"Anycast – nearest PoP (Cloudflare)","location_nl":"Anycast – dichtstbijzijnde PoP (Cloudflare)","ip":"1.1.1.1","provider":"Cloudflare Inc","dns_results":[{"host":"nettrace.eu","ip":"37.1.226.221","type":"A"}],"resolved":true,"status":"ok","rtt_ms":0,"cached":false}
POST /email-check
Checks a domain's email setup. If the given DKIM selector finds nothing, common selectors are tried automatically.
| Parameter | Required | Description |
|---|---|---|
domain | yes | Domain or email address. |
dkimSelector | no | DKIM selector, default default. |
{
"success": true,
"mxValid": true,
"disposable": false,
"deliverable": true,
"spf": "v=spf1 include:spf.mijn.host ~all",
"dmarc": "v=DMARC1; p=quarantine; sp=none;",
"dkim": "Valid DKIM record found for selector x: v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArQIV04gVwTijuLE2uIDyv1z5Jaf5cYyP2zyNXCeqgmQbGSQhaAUHCtFflAgjskALvWF2RpPHaEKs8f9c4sz6IG/cPqIGCzL+19eLLVP0VgBBwtOQwzE7cIFGrIsmucRKfYNtPOnf3sW2HtM4KMZt2hGQ51dxtLva4s8E0cv1nz6nuFZsVTtppr7BTWsTbCSMcGigG4NRKnWvk5pvSGbm+7HulODV6QHMBGG3bNbRFXE/yQxnFDjqTxvwJK7ubK2ouyHERnTy5OaR3hhvqZ2zK8KfQDfjnQ2UToO6zMWnJW7O80chb43JEKjIaUPqua/shhjgEUUuRqERiZ2o7kGVyQIDAQAB",
"mx": "mx1.mijn.host (priority 10), mx2.mijn.host (priority 20)",
"ptr": "hosted-by.cablehosting.net",
"bimi": "BIMI record missing or invalid",
"google_verification": "Domain is not verified by Google",
"null_mx": false,
"dkim_selector": "x"
}
POST /security-check
Returns a 0–100 score with issues, warnings and improvements, plus details per area: MX, SPF, DMARC, DKIM, BIMI, SSL, HSTS, DNSSEC, CAA, MTA_STS and TLS_RPT. For subdomains it falls back to the registered domain.
| Parameter | Required | Description |
|---|---|---|
domain | yes | Domain; https:// and paths are ignored. |
dkim_selector | no | Optional DKIM selector that is tried first. |
{
"percentage": 75,
"level": "Medium",
"issues": [],
"warnings": [
"BIMI is not configured.",
"No CAA records found.",
"MTA-STS is not configured.",
"TLS-RPT is not configured."
],
"improvements": [
"Tighten SPF policy to use \"-all\" after confirming all legitimate senders are included.",
"Add a \"rua\" tag to DMARC so you receive aggregate reports (e.g. rua=mailto:dmarc@yourdomain.com)."
],
"details": {
"input_domain": "nettrace.eu",
"parent_domain": "nettrace.eu",
"using_parent_fallback": false,
"SPF": {
"fallback_used": false,
"found_on": "nettrace.eu",
"mode": "softfail (~all)",
"value": "v=spf1 include:spf.mijn.host ~all"
},
"DMARC": {
"fallback_used": false,
"found_on": "nettrace.eu",
"policy": "quarantine",
"subdomain_policy": "none",
"value": "v=DMARC1; p=quarantine; sp=none;"
},
"HSTS": "Preload-ready"
}
}
400{"error":"Missing domain"}400{"error":"Invalid domain format"}
POST /spam-check
Checks an IP address (IPv4 or IPv6) or domain against DNS blacklists. status per list is ok, listed, unavailable (list no longer public) or error.
| Parameter | Required | Description |
|---|---|---|
target | yes | IP address or domain. |
mode | no | auto (default), ip, domain |
{
"checked_value": "127.0.0.2",
"type": "ip",
"ip": "127.0.0.2",
"domain": "127.0.0.2",
"total_lists": 9,
"listed_count": 9,
"results": [
{
"name": "Spamhaus ZEN",
"host": "zen.spamhaus.org",
"listed": true,
"response": "127.0.0.2",
"reason": "Listed by XBL, see https://check.spamhaus.org/query/ip/127.0.0.2",
"list_url": "https://www.spamhaus.org/blocklists/zen-blocklist/",
"status": "listed"
},
{
"name": "SpamCop",
"host": "bl.spamcop.net",
"listed": true,
"response": "127.0.0.2",
"reason": "Blocked - see https://www.spamcop.net/bl.shtml?127.0.0.2",
"list_url": "https://www.spamcop.net/",
"status": "listed"
},
{
"name": "Barracuda",
"host": "b.barracudacentral.org",
"listed": true,
"response": "127.0.0.2",
"reason": "http://www.barracudanetworks.com/reputation/?pr=1&ip=127.0.0.2",
"list_url": "https://www.barracudacentral.org/rbl",
"status": "listed"
}
]
}
400{"error":"Missing IP address or domain"}400{"error":"Invalid IP address"}400{"error":"Invalid domain"}400{"error":"Input is neither a valid IP nor a valid domain"}
POST /ip-info
Returns, for an IP address or for each IP address of a domain (up to 8), the hostname (reverse DNS), whether that hostname points back to the IP (fcrdns), the ASN and network owner, IP block, registry and approximate location. Use target=self to get your own IP address. Private and reserved addresses only get a scope.
| Parameter | Required | Description |
|---|---|---|
target | yes | IP address (IPv4/IPv6), domain or self. |
{
"query": "8.8.8.8",
"type": "ip",
"results": [
{
"ip": "8.8.8.8",
"version": 4,
"scope": "public",
"hostname": "dns.google",
"fcrdns": true,
"network": {
"asn": 15169,
"as_name": "Google LLC",
"prefix": "8.8.8.0/24",
"registry": "ARIN",
"allocated": "2023-12-28"
},
"location": {
"country_code": "US",
"country": "United States",
"region": "California",
"city": "Mountain View",
"continent": "NA",
"latitude": 37.422,
"longitude": -122.085,
"accuracy": "city (approximate)"
},
"sources": {
"geo": [
{
"source": "DB-IP Lite",
"city": "Mountain View",
"region": "California",
"country_code": "US",
"latitude": 37.422,
"longitude": -122.085
},
{
"source": "MaxMind GeoLite2 (via RIPEstat)",
"country_code": "US",
"latitude": 37.751,
"longitude": -97.822
}
],
"rir_country": "US",
"rdap": {
"name": "GOGL",
"handle": "NET-8-8-8-0-2",
"range": "8.8.8.0 – 8.8.8.255",
"org": "Google LLC",
"abuse_email": "network-abuse@google.com"
},
"bgp": {
"prefix": "8.8.8.0/24",
"origin_asns": [
"15169"
]
}
}
}
],
"source": "Location: DB-IP (db-ip.com, CC BY 4.0) and MaxMind GeoLite2 via RIPEstat. ASN: DB-IP. Prefix/registry: Team Cymru. Registration: RDAP. Routing and RIR country: RIPEstat."
}
Sources: DB-IP (CC BY 4.0), MaxMind GeoLite2 via RIPEstat, RDAP, RIPE NCC (BGP/RIR) and Team Cymru. The sources field holds the raw result per source.
GET /resolvers
List of all active resolvers with their current status, as on the status page.
curl https://api.nettrace.eu/v1.0/resolvers
{
"count": 84,
"standby": 17,
"recent_replacements": [],
"resolvers": [
{
"ip": "208.67.222.220",
"provider": "OpenDNS",
"location": "Anycast – nearest PoP (Cisco OpenDNS)",
"location_nl": "Anycast – dichtstbijzijnde PoP (Cisco OpenDNS)",
"legacy_location": "San Francisco CA, United States",
"enabled": true,
"up": true
},
{
"ip": "8.8.8.8",
"provider": "Google",
"location": "Anycast – nearest PoP (Google Public DNS)",
"location_nl": "Anycast – dichtstbijzijnde PoP (Google Public DNS)",
"legacy_location": "Mountain View CA, United States",
"enabled": true,
"up": true
}
]
}
OpenAPI
The full specification is available at /openapi.json (OpenAPI 3.0). You can use it to generate a client in most languages.