WHOIS Is Broken
If you've ever tried to parse WHOIS data programmatically, you know the pain:
- Every registrar returns a different format
- The output is plain text with no standard structure
- Rate limits are aggressive
- Some registrars just... don't respond
Enter RDAP
RDAP (Registration Data Access Protocol) is the official replacement for WHOIS, standardized by IETF (RFC 7480-7484).
The key difference: it returns structured JSON.
curl https://rdap.org/domain/github.com
You get:
{
"objectClassName": "domain",
"handle": "D1GITHUB-COM",
"ldhName": "github.com",
"status": ["client delete prohibited", "client transfer prohibited"],
"events": [
{"eventAction": "registration", "eventDate": "2007-10-09T18:20:50Z"},
{"eventAction": "expiration", "eventDate": "2026-10-09T07:00:00Z"}
],
"nameservers": [...]
}
No auth. No API key. Structured JSON.
Real Example: Domain Intelligence Script
import requests
from datetime import datetime
def domain_intel(domain):
"""Get structured domain intelligence via RDAP."""
resp = requests.get(f"https://rdap.org/domain/{domain}")
if resp.status_code != 200:
return {"error": f"Not found: {domain}"}
data = resp.json()
events = {e["eventAction"]: e["eventDate"][:10]
for e in data.get("events", [])}
# Calculate domain age
reg_date = events.get("registration", "unknown")
if reg_date != "unknown":
age_days = (datetime.now() - datetime.strptime(reg_date, "%Y-%m-%d")).days
age_years = round(age_days / 365.25, 1)
else:
age_years = "unknown"
return {
"domain": domain,
"status": data.get("status", []),
"registered": reg_date,
"expires": events.get("expiration", "unknown"),
"age_years": age_years,
"nameservers": [ns.get("ldhName", "")
for ns in data.get("nameservers", [])]
}
# Test with popular domains
for domain in ["github.com", "google.com", "dev.to"]:
info = domain_intel(domain)
print(f"\n{info['domain']}:")
print(f" Age: {info['age_years']} years")
print(f" Expires: {info['expires']}")
print(f" NS: {info['nameservers'][:2]}")
Bulk Domain Analysis
import csv
import time
def bulk_analyze(domains):
"""Analyze multiple domains, output CSV."""
results = []
for domain in domains:
info = domain_intel(domain)
results.append(info)
time.sleep(0.5) # Be polite
with open("domain_report.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=results[0].keys())
writer.writeheader()
writer.writerows(results)
print(f"Analyzed {len(results)} domains → domain_report.csv")
# Example: check competitor domains
bulk_analyze(["competitor1.com", "competitor2.io", "competitor3.dev"])
WHOIS vs RDAP
| Feature | WHOIS | RDAP |
|---|---|---|
| Format | Plain text, varies | Structured JSON |
| Standard | De facto | IETF RFC 7480-7484 |
| Auth | None | None |
| Rate limits | Aggressive | More generous |
| Parsing | Custom regex per registrar | json.loads() |
| GDPR compliant | Partial | Yes |
Use Cases
- Competitive intelligence: Track when competitor domains expire
- Brand protection: Monitor similar domain registrations
- Security: Verify domain age (new domains = higher risk)
- Due diligence: Check company domain history before partnerships
Full toolkit: whois-lookup-tools
More free APIs: awesome-free-apis-2026
Still using raw WHOIS? What's your domain lookup workflow? 👇
Top comments (0)