RDAP vs WHOIS: looking up domain registration data
· 6 min read · Email validation
RDAP is the replacement for WHOIS: both return domain registration data (registrar, creation and expiry dates, status, nameservers), but RDAP does it over HTTPS with a standard JSON format and a standard way to find the right server. For generic TLDs like .com, .org and .app, ICANN made RDAP the definitive source on 28 January 2025. For new code, query RDAP first and fall back to WHOIS only for the country-code TLDs that don't support it yet.
That fallback isn't rare. As of 2026, most two-letter country-code TLDs still have no RDAP server in IANA's registry, including .de, .io and .co.
RDAP vs WHOIS at a glance
| WHOIS | RDAP | |
|---|---|---|
| Specification | RFC 3912 (2004) | RFC 7480, 7481, 9082, 9083, 9224 |
| Transport | Plain text over TCP port 43 | HTTPS |
| Response format | Free text, differs by registry | JSON with a standard schema |
| Finding the right server | Per-TLD conventions, hardcoded in clients | IANA bootstrap file |
| Internationalized names | No standard handling | Supported |
| Differentiated access (e.g. authenticated users see more) | No | Supported by the protocol |
| Status for generic TLDs | Obligation sunset on 28 January 2025 (except .com, .name, .post) | Required, definitive source |
| Country-code TLDs | Widely available | Depends on the registry |
The data is largely the same. ICANN's own FAQ says RDAP gives you the same registration data as WHOIS, with a different response structure. What changed is that you can now parse it without a pile of regexes.
Why WHOIS was hard to use from code
WHOIS is a simple protocol: open a TCP connection to port 43, send the domain name, read text until the server closes the connection. RFC 3912 says almost nothing about what the text contains. Each registry chose its own field names, date formats and line layout.
Compare two registries. Verisign's server for .com returns lines like these:
Domain Name: STRIPE.COM
Registrar: SafeNames Ltd.
Creation Date: 1995-09-12T04:00:00Z
Registry Expiry Date: 2027-09-11T04:00:00Z
DENIC's server for .de returns a different layout and, for the domain we tried, no creation date at all:
Domain: stripe.de
Nserver: ns1.sedoparking.com
Status: connect
Changed: 2021-06-20T13:03:03+02:00
A WHOIS client that extracts creation dates across TLDs ends up as a collection of per-registry parsers, and breaks quietly when a registry changes its format. Finding the server is its own problem: clients ship a hardcoded TLD-to-server map or follow referrals. WHOIS also has a security footnote: in January 2025 ICANN warned about rogue WHOIS servers set up on expired domains that had once hosted real WHOIS services, and encouraged everyone to use RDAP instead.
How RDAP lookups work
An RDAP lookup is two steps.
- Find the server. IANA publishes a bootstrap file at
data.iana.org/rdap/dns.json, defined in RFC 9224. It maps TLDs to RDAP base URLs. For .com, that'shttps://rdap.verisign.com/com/v1/. - Ask it. Send
GET <base>domain/<name>. The response is JSON following RFC 9083: aneventsarray with registration, expiration and last-changed dates, anentitiesarray with the registrar (and a registrant entry, usually redacted),statuscodes andnameservers.
Registry responses often link to the registrar's own RDAP record for the same domain, which can hold extra detail. For quick manual checks, rdap.org redirects to the right server for you, and ICANN Lookup does the same in a browser.
Here's a lookup in TypeScript that handles the bootstrap, the missing-TLD case and unregistered domains. It runs on Node 18+, Bun, Deno and Cloudflare Workers:
type RegistrationInfo = {
source: 'rdap' | 'none';
createdAt: string | null;
registrar: string | null;
notFound?: boolean;
};
const BOOTSTRAP_URL = 'https://data.iana.org/rdap/dns.json';
let servers: Map<string, string> | null = null;
async function rdapBaseFor(domain: string): Promise<string | null> {
if (!servers) {
// Cache this: IANA updates the file occasionally, not per request.
const data = await (await fetch(BOOTSTRAP_URL)).json();
servers = new Map();
for (const [tlds, urls] of data.services as [string[], string[]][]) {
const url = urls.find((u) => u.startsWith('https://')) ?? urls[0];
for (const tld of tlds) servers.set(tld.toLowerCase(), url);
}
}
const tld = domain.split('.').pop()!.toLowerCase();
return servers.get(tld) ?? null;
}
export async function registrationInfo(domain: string): Promise<RegistrationInfo> {
const base = await rdapBaseFor(domain);
if (!base) return { source: 'none', createdAt: null, registrar: null }; // no RDAP: try WHOIS
const url = new URL(`domain/${domain}`, base.endsWith('/') ? base : `${base}/`);
const res = await fetch(url, {
headers: { accept: 'application/rdap+json' },
signal: AbortSignal.timeout(3000),
});
if (res.status === 404) return { source: 'rdap', createdAt: null, registrar: null, notFound: true };
if (!res.ok) throw new Error(`RDAP ${res.status} for ${domain}`);
const data = await res.json();
const created = data.events?.find((e: any) => e.eventAction === 'registration');
const registrar = data.entities?.find((e: any) => e.roles?.includes('registrar'));
const fn = registrar?.vcardArray?.[1]?.find((f: any[]) => f[0] === 'fn');
return { source: 'rdap', createdAt: created?.eventDate ?? null, registrar: fn?.[3] ?? null };
}
Run against a few domains, it returns 1995-09-12T04:00:00Z and SafeNames Ltd. for stripe.com, a 2019 creation date for github.dev, a result for bbc.co.uk from Nominet's server, source: 'none' for stripe.io, and notFound: true for an unregistered .com.
Pass the registrable domain, not a subdomain. mail.stripe.com isn't registered on its own; stripe.com is. If you're starting from an email address, reduce it to eTLD+1 with the Public Suffix List first. Internationalized names should be converted to punycode before the lookup.
Where RDAP still falls short
Country-code coverage
IANA's bootstrap file covers nearly every generic TLD. Country codes are a different story: as of 2026 it lists RDAP servers for 72 of the 248 two-letter TLDs. .uk, .fr, .nl, .br, .ca, .au and .in are covered. .de, .io, .co, .cn, .jp, .ru, .us and .eu are not. For those, WHOIS is still the only public source, with all the parsing work above, and some registries don't expose creation dates at all.
Redaction
RDAP doesn't bring back registrant details. The registrar's RDAP record for stripe.com lists a registrant entity with no name or address, which is typical. If your goal is "who owns this domain", registration data rarely answers it; the domain's website and public company data are better sources.
Rate limits and availability
Registries operate their own RDAP servers, and they don't all publish limits. Cache results (creation dates don't change; a TTL of days or weeks is fine), set a short timeout, and treat a failed lookup as unknown. Never block a user because a registry was slow.
What registration data is useful for
The most common practical use in signup and lead flows is domain age. A company domain registered three days ago is more suspicious than one registered in 1995, though plenty of real startups have new domains. We cover how to weigh it in domain age as a signup risk signal. Expiry dates and status codes such as clientHold or pendingDelete are occasionally useful too: a domain on hold won't resolve, which DNS will tell you more directly.
For everything else, DNS and classification usually answer the question faster. Free domain lookup tools maps each question to the right free tool, and what is domain intelligence explains how the layers fit together.
Where pingutil fits
pingutil doesn't do WHOIS or RDAP lookups, and doesn't report domain age. It covers the layers next to registration data: category (disposable, free, ISP, educational, government, company), local-part signals, DNS facts with check_dns: true, and a company profile for company domains. If domain age matters to your risk model, run the RDAP lookup above alongside it and combine the two, as in building a simple email risk score from free signals. The response fields are in the API reference.
Checklist for adding registration lookups
- Reduce input to the registrable domain and punycode before querying.
- Load IANA's bootstrap file once and cache it.
- Query RDAP first. Fall back to WHOIS only for TLDs with no RDAP entry.
- Read
eventsfor dates and theregistrarentity for the registrar name. Don't expect registrant data. - Cache by domain for days, time out in a few seconds, and treat failures as unknown.
Questions people ask
- Is WHOIS still available?
- Partly. ICANN made RDAP the definitive source for generic TLD registration data on 28 January 2025, and most gTLD registries and registrars are no longer required to run WHOIS. Many still do, and many country-code registries rely on WHOIS because they don't offer RDAP.
- Does RDAP show who owns a domain?
- Usually not. RDAP returns the same registration data WHOIS did, and registrant contact details are redacted or omitted for most domains. You can reliably get the registrar, creation and expiry dates, status codes and nameservers.
- How do I find the RDAP server for a domain?
- Use IANA's bootstrap file at data.iana.org/rdap/dns.json, which maps each top-level domain to its RDAP base URL, as specified in RFC 9224. If the TLD isn't listed, that registry has no RDAP service registered and you'll need WHOIS.