Looking up a domain’s expiry date sounds like a solved problem and was, for about twenty years, a genuinely miserable one. RDAP fixed most of it, and this post is about using it properly and being honest about the parts it does not cover.
Key takeaways
RDAP returns structured JSON. WHOIS returns free text that differs per registry.
The bootstrap file maps a TLD to its RDAP server, and it is cached rather than fetched.
A lookup returns the expiry, the registrar, the nameservers and the status codes.
Some ccTLDs have no RDAP. Those are tracked from the invoice date and flagged as such.
A failed lookup three weeks running is an alarm, not a gap in a chart.
What a lookup returns
domain example.com
expiry 2027-03-14T09:00:00Z the field everything depends on
registrar the sponsoring registrar, by name and IANA id
nameservers [ns1..., ns2...] a change here is its own signal
status [clientTransferProhibited, ...]
created 2011-06-02
last_changed 2026-03-14 usually the last renewal
source rdap | invoice how confident we are
The source field is the honest one. A date from RDAP is authoritative; a date carried over from an invoice because the registry offers no RDAP is a best estimate, and the register should say which it is holding rather than presenting both as facts.
The lookup
Fig 1. One domain’s weekly check. The change detection is worth as much as the expiry itself: nameservers changing without anybody expecting it is a much more urgent signal than a date six months out.
Database
App integration
Networking
Management
Analytics
Outside AWS
The bootstrap
IANA publishes a JSON file mapping every top-level domain to its RDAP service. Fetching it once a week and caching it is the whole of service discovery, and it removes the need for any per-registry configuration. A TLD that is not in the bootstrap has no RDAP service, which is information rather than an error.
The registries without RDAP
A shrinking number of country-code registries still offer only WHOIS, or only a web form, or nothing machine-readable at all. Parsing free-text WHOIS per registry is a maintenance burden out of all proportion to two domains, so the honest handling is to not try.
Those domains carry a date taken from the renewal invoice, marked source: invoice, and the escalation for them starts earlier — a hundred and twenty days rather than ninety — because the date is less reliable and there is no independent way to confirm it. The register says so on the domain, so nobody mistakes a remembered date for a verified one.
Failure is a signal
Fig 2. Why repeated lookup failures alarm. This is the same trap as any watcher: the dangerous state is not an error, it is quiet.
Machine learning
Management
Analytics
Three consecutive failures on one domain is worth a message, and a domain whose last_checked has not moved in three weeks is worth an alarm from a different function — because if the checker itself has stopped running, it will not be the thing that tells you.