dug

The dug API

Every command is a GET. There’s no key, no signup and no request body to build, and every response publishes the quota. The same URL answers in three representations, and the browser app at / is one of them, not a separate product.

[ calling it ]

$ curl https://dug.sh/tls/github.com

$ curl https://dug.sh/dig/example.com/MX

$ curl -H 'Accept: application/json' https://dug.sh/mail/github.com

The query form is equivalent and is what the browser app uses: /api/tls?command=TLS&target=github.com

[ representations ]
text/plain
the default for curl and other terminal clients
application/json
Accept: application/json, or ?format=json
text/markdown
Accept: text/markdown, on the pages
text/html
the browser app; a command url opened in a browser lands there with the command run
Vary
Accept, User-Agent, so negotiation is cache safe
Cache-Control
derived from the answer’s own TTL, floored at 30s
[ auth ]

None. Reads are open and there’s no key to obtain, so there’s nothing here to sandbox. The guard validates every destination before connect, which is what makes open reads safe. The quota below applies per address, since there’s no key.

[ errors ]

An upstream that fails mid-answer is 200: the failure is named in degraded and the rest of the answer is real. Arguments that are wrong are 400, because nothing was looked up. Only a 4xx carries error, so its presence and the status always agree.

error.code
missing_argument, invalid_argument
error.message
the refusal in one sentence
error.hint
what a corrected call looks like

Branch on the code, never on the message. The text representation carries the same code on a line reading "error <code>".

[ rate limits ]
RateLimit-Limit
60 requests per window
RateLimit-Remaining
what is left in this window
RateLimit-Reset
seconds until it resets
RateLimit-Policy
"fixed";q=60;w=60, per RFC 9331
over the quota
429, error.code rate_limited, Retry-After

Every response carries these, including a 200, so a caller can pace itself instead of discovering the ceiling by hitting it. The count lives in the memory of one proxy instance, and a serverless deployment runs more than one, so a client spread across instances gets more than 60. It’s a real backstop and a truthful number to pace against. It isn’t a security control.

[ versioning and deprecation ]

The paths are unversioned and additive. New commands, blocks and fields may appear at any time, so parse defensively and ignore what you don’t recognise. A change that would break an existing caller ships under a /v2/ prefix instead of changing these.

X-API-Version
on every response, naming the contract it ran under
Deprecation
an http-date, the day it became deprecated
Sunset
an http-date, the day it stops answering
notice
at least 180 days between the two dates

Nothing is deprecated today, and the absence of a Deprecation header is how you can tell. The full timeline is at /deprecation.

Endpoints

[ resolution ]
  • GET /dig/{target}every record type, or a single one
  • GET /prop/{target}agreement across the fixed resolver list
  • GET /ttl/{target}remaining lifetime per record
[ delegation ]
  • GET /ns/{target}root to tld to authoritative walk
  • GET /dnssec/{target}chain of trust, ds and dnskey
[ registration ]
  • GET /rdap/{target}registration data with status codes decoded
  • GET /watch/{target}domain and certificate expiry, computed now
[ transport ]
  • GET /tls/{target}chain, validity spans, protocols
  • GET /http/{target}headers, redirect chain, security headers
  • GET /trace/{target}dns, tcp, tls and ttfb timing
[ mail ]
  • GET /mail/{target}mx, spf, dkim, dmarc and alignment policy
  • GET /spf/{target}include tree, against the ten lookup limit
[ addressing ]
  • GET /ip/{target}reverse dns, asn, prefix, neighbours
  • GET /asn/{target}prefixes and address space
  • GET /net/{target}address space grid, a /24 or smaller
  • GET /methe address this request came from
[ reachability ]
  • GET /ping/{target}icmp echo, round trip time and packet loss
  • GET /route/{target}the hops between here and there, with reverse dns
  • GET /ports/{target}which tcp ports are open, closed or filtered
[ meta ]
  • GET /vs/{target}two domains side by side
  • GET /srcresolver list, cache ceilings, upstream health
[ readability ]
  • GET /seo/{target}what a crawler reads: title, canonical, robots, structured data
  • GET /aeo/{target}what an answer engine reads: llms.txt, markdown, content without js
  • GET /og/{target}the share card, with the image fetched and measured
  • GET /webmcp/{target}tools for an agent in the page, and the mcp surface for one that isn’t
[ machine readable ]