RDAP vs WHOIS for Domain-Age and Registration Signals
How to build a structured domain-intelligence pipeline without pretending registration data proves trust
“Use a WHOIS API” is still common advice when an application needs domain age, registrar or expiry data.
For a new integration, the better starting point is RDAP.
The Registration Data Access Protocol uses HTTP and structured JSON. ICANN positions it as the standards-based replacement for WHOIS, and the IETF defines its query and response formats. That does not make domain registration data complete or authoritative for every business decision—but it makes the data contract far easier to reason about.
Why parsing WHOIS is fragile
WHOIS commonly returns free-form text. Field names, date formats, encodings, referral behavior and redaction differ across registries and registrars.
A parser often becomes a collection of special cases:
Creation Date: 2021-03-04T12:00:00Z
created: 2021-03-04
Registered On: 04-Mar-2021
Those values may describe the same event, but downstream code has to discover that fact.
RDAP responses use JSON objects with defined fields for events, status, nameservers, entities, secure DNS and notices. A domain query follows a uniform HTTP path. The result is still subject to registry policy, but it is a much better programmatic interface.
A small RDAP adapter in Node.js
A direct lookup can start like this:
export async function fetchRdap(domain) {
const response = await fetch(
"https://rdap.org/domain/" + encodeURIComponent(domain),
{
headers: {
accept: "application/rdap+json, application/json",
},
signal: AbortSignal.timeout(6_000),
},
);
if (response.status === 404) {
return { status: "not_found", data: null };
}
if (!response.ok) {
return {
status: "unknown",
data: null,
reason: "RDAP returned " + response.status,
};
}
return { status: "ok", data: await response.json() };
}
The adapter deliberately distinguishes “not found” from “unknown.” A timeout or upstream failure is not proof that the domain is unregistered.
Normalize events instead of assuming array order
RDAP events identify their meaning with eventAction. Search for the action you need.
function findEventDate(events = [], action) {
const event = events.find(
(item) => String(item.eventAction).toLowerCase() === action,
);
if (!event?.eventDate) return null;
const date = new Date(event.eventDate);
return Number.isNaN(date.getTime()) ? null : date.toISOString();
}
function normalizeRegistration(rdap) {
return {
domain: rdap.ldhName ?? null,
createdAt: findEventDate(rdap.events, "registration"),
expiresAt: findEventDate(rdap.events, "expiration"),
updatedAt:
findEventDate(rdap.events, "last changed") ??
findEventDate(rdap.events, "last update of rdap database"),
status: Array.isArray(rdap.status) ? rdap.status : [],
nameservers: (rdap.nameservers ?? [])
.map((item) => item.ldhName)
.filter(Boolean),
dnssec: rdap.secureDNS
? {
delegationSigned: Boolean(rdap.secureDNS.delegationSigned),
zoneSigned: Boolean(rdap.secureDNS.zoneSigned),
}
: null,
};
}
Do not assume every field will be present. A null registration date should remain null.
Compute age without turning it into a verdict
function ageInDays(createdAt, now = Date.now()) {
if (!createdAt) return null;
const created = new Date(createdAt).getTime();
if (Number.isNaN(created)) return null;
return Math.max(0, Math.floor((now - created) / 86_400_000));
}
Domain age can be useful in a larger model:
- a very recent registration may trigger enhanced vendor verification;
- a domain close to expiry may indicate an operational risk;
- status codes may reveal holds or transfer restrictions;
- signed delegation can provide a DNSSEC signal.
None of these proves intent. Old domains can be compromised or sold. New domains can be legitimate. Registration evidence belongs in a feature set, not in a moral label.
RDAP is only one layer of domain intelligence
A technical website assessment becomes more useful when it combines independent evidence:
RDAP registration
+ DNS reachability and delegation
+ TLS certificate health
+ HTTPS behavior
+ browser security headers
= explainable technical posture
The independence matters. A healthy certificate cannot compensate for an expired registration. Missing Content Security Policy should not erase years of stable registration history. Each category should expose its own status and point contribution.
If RDAP is unavailable, the overall score should be provisional and show the maximum possible score if the missing check later passes. Silently treating unknown registration evidence as zero creates false negatives; awarding full points creates false confidence.
Model findings as stable data
Human-readable messages are useful, but automation needs stable codes.
{
"code": "DOMAIN_EXPIRING_SOON",
"severity": "high",
"title": "Domain expires within 30 days",
"message": "The registration expires in 18 days.",
"recommendation": "Confirm renewal before relying on the domain."
}
Policy can react to DOMAIN_EXPIRING_SOON even if the title is rewritten later. Store the code, severity, evidence timestamp and the policy version that consumed it.
Privacy and access policy still matter
Structured access does not mean unrestricted access. RFC and ICANN materials describe authentication, differentiated access and policy-controlled fields. Personal contact data may be redacted, and public output differs across registries.
Build the integration around the fields you actually need. For a technical trust model, registration date, expiry, status, registrar and DNSSEC are often enough. Do not collect registrant data merely because it is available.
Use a hosted audit when the broader signals matter
The Domain Intelligence & Website Trust Score API on RapidAPI combines RDAP with DNS, TLS, HTTPS and security-header evidence. It returns per-check points, stable findings and a provisional state. The Basic plan includes 50 requests per month.
The full domain reputation checker guide on StadiaSoft covers score interpretation, bulk checks and an application-level allow/review/block policy.
RDAP is an upgrade over parsing WHOIS, but the most important improvement is conceptual: preserve what the source does not know.
Disclosure: I publish the RapidAPI product referenced above. This article documents both its scope and its limitations.

