Tutorials Internet Infrastructure Series Chapter 1

RDAP Explained — The HTTPS + JSON Replacement for WHOIS

InfrastructureChapter 1 of the Internet Infrastructure Series22 minMay 28, 2026Beginner

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 problemWhat it meant in practice
Plaintext TCP/43, no encryptionYour query and the response travel unencrypted across the internet
No standard response formatEvery registry's output looks different — you write a parser per registry
No internationalizationNon-ASCII contact fields fall apart
No structured errors, redirects, rate limitsFailures look like... more plaintext
No structured contactsThe "registrant" is a free-form blob, not parseable name/email/phone
No discoverabilityYou 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 typeForExample value
domainA domain nameexample.com
ipAn IPv4 / IPv6 address or block8.8.8.8
autnumAn Autonomous System Number13335 (Cloudflare)
nameserverA name-server hostns1.example.com
entityA registrar, registrant, or other actoropaque 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:

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:

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:

Loading diagram…

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:

FieldWhat it tells you
ldhNameThe "letters-digits-hyphens" name — the domain itself
statusEPP status codes (locked? pending delete? OK?)
eventsTimeline — registration, expiration, last-changed; the keys for monitoring
entitiesThe people/orgs involved (registrar, registrant, abuse contact) with structured roles
vcardArrayThe entity's contact info — a JSON encoding of vCard (RFC 7095, "jCard")
nameserversThe 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

WHOISRDAP
TransportPlaintext TCP port 43HTTPS
FormatFree-form text, per-registry quirksJSON with a defined schema
Errors"sorry, try later" in proseHTTP status codes + structured JSON
RedirectsNone — you have to know the serverHTTP 301/302 + IANA bootstrap
Rate limitingImplicit, server-by-serverHTTP 429 with Retry-After
ContactsFree-form textStructured jCard (vCard-in-JSON)
i18nLimitedUTF-8 throughout
Privacy / redactionAd-hoc "REDACTED" stringsFormal redacted array explaining what + why
Auth for elevated dataNone standardisedHTTP auth / OAuth for tiered access
ICANN gTLD status (2026)Sunset Jan 2025Required

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:

  1. Domain availability + ownership checks. A 404 on domain/foo.com means unregistered; a 200 with a populated payload means taken. Faster and more reliable than scraping registrar sites.
  2. Abuse contact lookup for an IP. When something attacks your server, you want the network owner's abuse address — RIRs publish abuse-mailbox and abuse entity records right in the IP response. Way more reliable than guessing abuse@<reverse-dns>.
  3. Expiration monitoring. Pull the expiration event 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.
  4. 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:

Mental Model — Three Sentences

  1. 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.
  2. The URL shape is https://<server>/<resource-type>/<value>, the bootstrap (or rdap.org) tells you which server is authoritative, and the response is JSON with a defined schema including redacted for GDPR-hidden fields.
  3. As of January 2025, RDAP is the contractually-required gTLD lookup protocol — WHOIS is officially retired for .com / .org / .net and friends, so build new tools on RDAP and migrate any WHOIS scrapers you still own.

Try It Yourself (10 Minutes)

  1. Run curl -sL https://rdap.org/domain/<your-favourite-domain> | jq . and read the response. Find the expiration event.
  2. 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.
  3. Fetch IANA's bootstrap: curl -s https://data.iana.org/rdap/dns.json | jq '.services[] | select(.[0][] == "com")' — see the actual mapping from .com to its RDAP server URL.
  4. Look up Cloudflare's ASN: curl -sL https://rdap.org/autnum/13335 | jq '.name, .entities[].handle'.
  5. 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.

← Series OverviewComing Soon →
SecurityWeb Security SeriesWeb security lessons for DNS, subdomain takeover, certificate transparency, storage exposure, and OWASP risk.Production WebProduction Web Apps SeriesProduction patterns for web apps: caching, rate limiting, webhooks, queues, cron jobs, and idempotency.CloudflareCloudflare Feature FocusFocused Cloudflare tutorials for Workers, R2, Stream, Durable Objects, and edge deployment.

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
5 free articles remainingSubscribe for unlimited access