I was researching a suspicious email. The sender's domain was registered 3 days ago. That's a red flag.
I found it using a free WHOIS API — no key, no signup, just a GET request.
The Free WHOIS APIs
Several services offer free WHOIS lookups via API:
1. RDAP (Registration Data Access Protocol)
RDAP is the official replacement for WHOIS, maintained by IANA. It returns structured JSON.
import requests
def rdap_lookup(domain):
# RDAP bootstrap finds the right registry automatically
resp = requests.get(f'https://rdap.org/domain/{domain}')
if resp.status_code != 200:
return {'error': f'Status {resp.status_code}'}
data = resp.json()
# Extract key info
result = {'domain': domain}
# Registration dates
for event in data.get('events', []):
if event['eventAction'] == 'registration':
result['registered'] = event['eventDate'][:10]
elif event['eventAction'] == 'expiration':
result['expires'] = event['eventDate'][:10]
elif event['eventAction'] == 'last changed':
result['updated'] = event['eventDate'][:10]
# Nameservers
result['nameservers'] = [
ns.get('ldhName', '')
for ns in data.get('nameservers', [])
]
# Status
result['status'] = data.get('status', [])
return result
# Example
info = rdap_lookup('google.com')
for k, v in info.items():
print(f" {k}: {v}")
Output:
domain: google.com
registered: 1997-09-15
expires: 2028-09-14
updated: 2019-09-09
nameservers: ['ns1.google.com', 'ns2.google.com', ...]
status: ['client delete prohibited', 'server update prohibited']
2. Check Domain Age (Security Signal)
from datetime import datetime
def check_domain_age(domain):
info = rdap_lookup(domain)
if 'registered' not in info:
return {'domain': domain, 'risk': 'UNKNOWN', 'reason': 'No registration date found'}
reg_date = datetime.strptime(info['registered'], '%Y-%m-%d')
age_days = (datetime.now() - reg_date).days
if age_days < 30:
risk = 'HIGH'
note = f'Domain is only {age_days} days old!'
elif age_days < 365:
risk = 'MEDIUM'
note = f'Domain is {age_days} days old'
else:
risk = 'LOW'
note = f'Domain is {age_days // 365} years old'
return {'domain': domain, 'risk': risk, 'age_days': age_days, 'note': note}
# Check suspicious domains
for d in ['google.com', 'totally-legit-bank.com']:
result = check_domain_age(d)
print(f" {result['domain']}: {result['risk']} — {result['note']}")
3. Bulk Domain Research
import time
def research_domains(domains):
results = []
for domain in domains:
info = rdap_lookup(domain)
info['age'] = check_domain_age(domain)
results.append(info)
time.sleep(1) # Be polite
# Sort by registration date
results.sort(key=lambda r: r.get('registered', '9999'))
for r in results:
age = r['age']
print(f" {r['domain']:<30} reg:{r.get('registered','?'):<12} {age['risk']}")
return results
# Research competitor domains
research_domains(['stripe.com', 'square.com', 'paypal.com'])
4. Find Nameserver Patterns
from collections import Counter
def analyze_nameservers(domains):
ns_counter = Counter()
for domain in domains:
info = rdap_lookup(domain)
for ns in info.get('nameservers', []):
# Extract provider from nameserver
provider = ns.split('.')[-2] if '.' in ns else ns
ns_counter[provider] += 1
time.sleep(1)
print('Nameserver providers:')
for ns, count in ns_counter.most_common(5):
print(f' {ns}: {count} domains')
Use Cases
- Security: Flag newly registered domains in phishing emails
- Due diligence: Verify company claims about their founding date
- SEO: Check domain age before purchasing expired domains
- Competitive intelligence: Track when competitors register new domains
- Brand protection: Monitor for typosquat domain registrations
Rate Limits
- RDAP: No official rate limit, but registries may throttle
- Add 1-second delays between requests
- Cache results — domain data doesn't change often
Building security and research tools with free APIs. More projects: GitHub | Writing: Spinov001@gmail.com
Top comments (0)