If you've ever opened a terminal and run whois example.com, you know the feeling: a wall of plaintext, formatted differently by every registry, half of it now replaced with REDACTED FOR PRIVACY. Useful if you squint, awful if you want to build anything on top of it.
There is a successor, and as of January 2025 ICANN made it the official protocol for gTLD registration lookups: RDAP — the Registration Data Access Protocol. It speaks HTTPS, returns clean JSON, has a real schema, supports redirects and rate limits like a normal API, and was built specifically so that machines (not humans squinting at a terminal) can ask "who owns this domain / who owns this IP / who runs this ASN?" and get a reliable answer.
This chapter is the from-zero introduction. By the end you'll know what RDAP is, why it had to replace WHOIS, the exact URL shape and JSON it returns, how to query it with one curl line, and four real things to build with it.
What RDAP Is, in One Paragraph
RDAP is a small, IETF-standardized HTTPS+JSON protocol for asking authoritative registries about internet resources — domains (registrar, registrant, dates, status, nameservers), IP address blocks (which RIR allocated it, abuse contact), autonomous system numbers (network operator behind a BGP route), and a few related objects. It's defined in RFCs 7480–7484 (2015), updated by 9082 (query format) and 9083 (JSON response format) in 2021. Every modern registry — Verisign for .com, ARIN for North American IPs, RIPE for European IPs, and so on — runs an RDAP server.
That's it. RDAP is just "WHOIS, but as a normal modern API." The novelty is entirely in the engineering quality, not the idea.
Why It Exists — The Problems With WHOIS
WHOIS is from 1982. It worked, but it was a protocol of its time, and by the 2010s every one of these had become a real pain:
| WHOIS problem | What it meant in practice |
|---|---|
| Plaintext TCP/43, no encryption | Your query and the response travel unencrypted across the internet |
| No standard response format | Every registry's output looks different — you write a parser per registry |
| No internationalization | Non-ASCII contact fields fall apart |
| No structured errors, redirects, rate limits | Failures look like... more plaintext |
| No structured contacts | The "registrant" is a free-form blob, not parseable name/email/phone |
| No discoverability | You have to know which WHOIS server is authoritative for a TLD |
| Clash with GDPR (2018) | Registries started bulk-redacting fields with ad-hoc "REDACTED" strings |
RDAP was designed to fix every one of these. The big one — the reason it actually shipped instead of being yet another nice IETF idea — is GDPR. Once registrars had to redact personal data, they needed a protocol that could say what was redacted and why, in a structured way, instead of mashing "REDACTED FOR PRIVACY" into a plaintext blob. RDAP has a formal redacted array for exactly that.
How RDAP Actually Works
It's a REST API. That's almost the entire description. The URL has a tiny grammar:
https://<server>/<resource-type>/<value>Resource types are a short closed list:
| Resource type | For | Example value |
|---|---|---|
domain | A domain name | example.com |
ip | An IPv4 / IPv6 address or block | 8.8.8.8 |
autnum | An Autonomous System Number | 13335 (Cloudflare) |
nameserver | A name-server host | ns1.example.com |
entity | A registrar, registrant, or other actor | opaque registry handle |
Send a GET to one of those URLs and you get back JSON. There's no auth for normal queries; just hit the URL.
The Bootstrap: Finding the Right Server
The one tricky bit. Different TLDs and IP ranges are administered by different organizations:
.com/.net→ Verisign.org→ Public Interest Registry- IPv4 / IPv6 in North America → ARIN
- in Europe → RIPE NCC
- in Asia/Pacific → APNIC
- ...and so on
So which RDAP server do you query for example.com? IANA publishes a "bootstrap" file — a small JSON document mapping TLDs (and IP ranges and ASN ranges) to their authoritative RDAP base URL:
https://data.iana.org/rdap/dns.json— TLD → RDAP serverhttps://data.iana.org/rdap/ipv4.json— IPv4 range → RDAP serverhttps://data.iana.org/rdap/ipv6.json— IPv6 range → RDAP serverhttps://data.iana.org/rdap/asn.json— ASN range → RDAP server
You can fetch those yourself and route accordingly. Or, easier, hit the free public aggregator rdap.org, which reads the bootstrap for you and HTTP-redirects your query to the right authoritative server:
Figure 1 — How a query gets routed. You hit rdap.org, it looks up the TLD in the IANA bootstrap, redirects you to the authoritative registry's RDAP server, and that server returns the JSON. Curl with -L (follow redirects) and you never have to know any of this.
Try It Right Now — Three curl Lines
You can test all this with one command and jq (a JSON pretty-printer; brew install jq).
# Who owns a domain?
curl -sL https://rdap.org/domain/example.com | jq .
# Who owns an IP address?
curl -sL https://rdap.arin.net/registry/ip/8.8.8.8 | jq .
# Who runs an autonomous system?
curl -sL https://rdap.arin.net/registry/autnum/13335 | jq .You'll get back something like this (trimmed for readability):
{
"rdapConformance": ["rdap_level_0"],
"objectClassName": "domain",
"handle": "2336799_DOMAIN_COM-VRSN",
"ldhName": "EXAMPLE.COM",
"status": ["client delete prohibited", "client transfer prohibited"],
"events": [
{ "eventAction": "registration", "eventDate": "1995-08-14T04:00:00Z" },
{ "eventAction": "expiration", "eventDate": "2026-08-13T04:00:00Z" },
{ "eventAction": "last changed", "eventDate": "2024-08-14T07:01:34Z" }
],
"entities": [
{
"objectClassName": "entity",
"roles": ["registrar"],
"vcardArray": ["vcard", [
["version", {}, "text", "4.0"],
["fn", {}, "text", "RESERVED-Internet Assigned Numbers Authority"]
]]
}
],
"nameservers": [
{ "objectClassName": "nameserver", "ldhName": "A.IANA-SERVERS.NET" },
{ "objectClassName": "nameserver", "ldhName": "B.IANA-SERVERS.NET" }
]
}Read it like this:
| Field | What it tells you |
|---|---|
ldhName | The "letters-digits-hyphens" name — the domain itself |
status | EPP status codes (locked? pending delete? OK?) |
events | Timeline — registration, expiration, last-changed; the keys for monitoring |
entities | The people/orgs involved (registrar, registrant, abuse contact) with structured roles |
vcardArray | The entity's contact info — a JSON encoding of vCard (RFC 7095, "jCard") |
nameservers | The authoritative DNS hosts |
Every RDAP response has the same shape. Write the parser once; reuse it for every TLD and every RIR. That alone is the value proposition over WHOIS.
RDAP vs WHOIS, Side by Side
| WHOIS | RDAP | |
|---|---|---|
| Transport | Plaintext TCP port 43 | HTTPS |
| Format | Free-form text, per-registry quirks | JSON with a defined schema |
| Errors | "sorry, try later" in prose | HTTP status codes + structured JSON |
| Redirects | None — you have to know the server | HTTP 301/302 + IANA bootstrap |
| Rate limiting | Implicit, server-by-server | HTTP 429 with Retry-After |
| Contacts | Free-form text | Structured jCard (vCard-in-JSON) |
| i18n | Limited | UTF-8 throughout |
| Privacy / redaction | Ad-hoc "REDACTED" strings | Formal redacted array explaining what + why |
| Auth for elevated data | None standardised | HTTP auth / OAuth for tiered access |
| ICANN gTLD status (2026) | Sunset Jan 2025 | Required |
Same job, one is a 1980s protocol, the other is a 2010s API. The migration was forty years in the making.
Privacy: Reading the redacted Array
Under GDPR, registrars must hide personal data from public RDAP responses. WHOIS dealt with this by overwriting fields with literal REDACTED FOR PRIVACY. RDAP does it properly: a top-level redacted array lists exactly which JSON paths were hidden and the reason. A trimmed example:
{
"redacted": [
{
"name": { "type": "Registrant Name" },
"prePath": "$.entities[?(@.roles[0]=='registrant')].vcardArray[1][?(@[0]=='fn')]",
"reason": { "type": "Server policy" },
"method": "removal"
}
]
}That tells a client: "the registrant's name was removed, here is the JSONPath where it would have been, and it's hidden because of server policy." Machine-readable. No more guessing which "REDACTED" string means what.
For accredited use (law enforcement, certain registrars), some RDAP servers accept authentication (HTTP auth or OAuth) and return the unredacted fields. The protocol leaves room for that without forcing it on everyone.
Four Things Devs Actually Build on RDAP
You're unlikely to query RDAP interactively beyond the first time. The real uses are programmatic:
- Domain availability + ownership checks. A 404 on
domain/foo.commeans unregistered; a 200 with a populated payload means taken. Faster and more reliable than scraping registrar sites. - Abuse contact lookup for an IP. When something attacks your server, you want the network owner's abuse address — RIRs publish
abuse-mailboxand abuseentityrecords right in the IP response. Way more reliable than guessingabuse@<reverse-dns>. - Expiration monitoring. Pull the
expirationevent from a domain's RDAP record on a schedule, alert N days before. A 30-line cron job protects you from the classic "we forgot to renew" outage. - Threat intel / fraud signals. Cheap signals: very-recently-registered domains, domains that just changed nameservers, IPs whose RDAP entity matches known bad networks. RDAP makes all of that structured enough to score.
Gotchas
A few real-world things to know before you ship:
- Not every TLD has RDAP yet. Most ccTLDs are catching up; a few still only offer WHOIS. Always handle "no RDAP server found" gracefully.
- Always follow redirects.
curl -L,fetchwithredirect: "follow"— the bootstrap path goes through 1–2 hops. - Rate limits are real. Expect HTTP 429 with a
Retry-Afterheader under heavy use. Don't hammer a registry from a tight loop; cache responses. - Implementations vary. Required fields are required, but optional fields differ. Code defensively (
response.events?.find(e => e.eventAction === "expiration")). - Some Cloudflare-fronted RDAP endpoints aggressively block server-side fetches — if you're hitting RDAP from a Worker, route through
rdap.orgrather than registry-specific URLs and you'll have fewer surprises.
Mental Model — Three Sentences
- RDAP is "WHOIS as a normal HTTPS+JSON REST API" — defined in IETF RFCs, used to look up domains, IPs, and ASNs in a structured way every registry returns the same shape.
- The URL shape is
https://<server>/<resource-type>/<value>, the bootstrap (orrdap.org) tells you which server is authoritative, and the response is JSON with a defined schema includingredactedfor GDPR-hidden fields. - As of January 2025, RDAP is the contractually-required gTLD lookup protocol — WHOIS is officially retired for
.com/.org/.netand friends, so build new tools on RDAP and migrate any WHOIS scrapers you still own.
Try It Yourself (10 Minutes)
- Run
curl -sL https://rdap.org/domain/<your-favourite-domain> | jq .and read the response. Find theexpirationevent. - Look up your own IP:
curl -sL https://rdap.org/ip/$(curl -s https://api.ipify.org) | jq '.entities[]?.roles, .name'— see which network operator owns the block you're sitting in. - Fetch IANA's bootstrap:
curl -s https://data.iana.org/rdap/dns.json | jq '.services[] | select(.[0][] == "com")'— see the actual mapping from.comto its RDAP server URL. - Look up Cloudflare's ASN:
curl -sL https://rdap.org/autnum/13335 | jq '.name, .entities[].handle'. - Pick one of the four "real uses" above and prototype it as a 30-line script. Domain expiration monitoring is the easiest first one.
Where This Lands in the Series
This is Chapter 1 of the Internet Infrastructure series — the protocols and registries every developer relies on but rarely sees explained directly. RDAP makes a good opening because it's an immediately useful tool you can curl in the next sixty seconds, and because understanding it forces you to meet the cast (IANA, the RIRs, gTLD registries, registrars) that the rest of the series will revisit.
Coming next: DNS — how example.com actually becomes an IP, root servers, authoritative vs recursive resolvers, the record types you'll meet (A, AAAA, CNAME, MX, TXT, CAA), and how to read a dig +trace output. Then BGP, certificates, and the rest of the plumbing.
Ship your apps faster
When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.
Try Simple App Shipper