Manual WHOIS checks work for one-off lookups. For competitor monitoring, lead verification, or brand protection you need automation through a WHOIS API.
Popular WHOIS API Services
| Service | Free tier | Price | Features |
|---|---|---|---|
| WhoisXML API | 500 requests/mo | from $19/mo | Normalized JSON, history |
| Whoxy.com | 100/mo | from $10/mo | Reverse WHOIS, bulk |
| ip-api.com | 45/min (IP) | Free | IP geolocation only |
| domain-coupler.io | 10/mo | from $5/mo | Simple, fast |
PHP Example
// WHOIS lookup via the WhoisXML API
$apiKey = 'YOUR_API_KEY';
$domain = 'example.com';
$url = "https://www.whoisxmlapi.com/whoisserver/WhoisService"
. "?apiKey={$apiKey}&domainName={$domain}&outputFormat=JSON";
$response = file_get_contents($url);
$data = json_decode($response, true);
echo "Registrar: " . $data['WhoisRecord']['registrarName'] . "
";
echo "Expires: " . $data['WhoisRecord']['expiresDate'] . "
";
echo "NS: " . implode(', ', $data['WhoisRecord']['nameServers']['hostNames']) . "
";
Python Example
import requests
API_KEY = 'YOUR_API_KEY'
domains = ['example.com', 'competitor.com', 'anotherdomain.net']
for domain in domains:
url = f"https://www.whoisxmlapi.com/whoisserver/WhoisService"
params = {
'apiKey': API_KEY,
'domainName': domain,
'outputFormat': 'JSON'
}
resp = requests.get(url, params=params).json()
record = resp.get('WhoisRecord', {})
print(f"{domain}: expires {record.get('expiresDate', 'N/A')}")
Using the whois Python Library
pip install python-whois
import whois
w = whois.whois('example.com')
print(w.expiration_date) # Expiration date
print(w.registrar) # Registrar
print(w.name_servers) # NS servers
💡 Competitor monitoring: Run a WHOIS check on competitor domains every week. If a domain has moved to a new owner or its NS servers changed, that signals a hosting move or a business sale.
⚠️ Rate limiting: Public WHOIS servers throttle requests (usually 1–5/sec). Run bulk checks only through paid APIs with official rate limits.
Common Errors When Working with a WHOIS API
| Error | Cause |
|---|---|
| HTTP 401 Unauthorized | An invalid or expired API key, or the key was passed in the wrong parameter — different services expect apiKey, api_key, or a dedicated header |
| HTTP 429 Too Many Requests | The plan's request limit was exceeded: checking a list of domains in bulk with no pause between requests quickly hits the rate limit |
| WhoisRecord.registrarName: null in the response | The domain uses "thin" WHOIS (common for some ccTLDs) — the registrar does not publish this data in the shared protocol, only through the zone registry's RDAP |
| SSL certificate problem: unable to get local issuer certificate | An outdated CA bundle on the server, or the openssl extension is not enabled in PHP — curl cannot verify the API's certificate chain |
| WhoisCommandFailed: No match for domain | The domain is available, or the registry's whois server is temporarily down; python-whois does not retry automatically |
| Quota exceeded / HTTP 402 Payment Required | The free tier's monthly quota ran out before the renewal date — the service's counter resets on the first of the month, not 30 days after signup |
When a WHOIS API Is Not the Right Tool
- You need a real-time check right inside a site's signup form — public WHOIS servers are too slow and too rate-limited for a synchronous request on every keystroke; RDAP with your own cache fits better
- There is no budget for a paid tier, but the volume of checks is large — free limits run out quickly, and bulk requests to public WHOIS servers end in an IP ban
- You need historical WHOIS data from past years — a regular lookup only returns the current state; history requires a separate paid service such as WhoisXML Historical WHOIS
- The domain is in a zone with WHOIS closed by default (most .eu, many .de) — the owner's personal data will not come back through any API, since the restriction sits at the registry level, not the service
Verifying the Result
Before wiring the API into a production script, confirm the key actually works and the limit is not already exhausted — it saves time debugging the whole pipeline later. The basics of WHOIS and manual lookups are covered in the articles on what WHOIS is and on checking a domain online.
# Confirm the key works with a single curl request
curl -s "https://www.whoisxmlapi.com/whoisserver/WhoisService?apiKey=YOUR_KEY&domainName=example.com&outputFormat=JSON" | head -c 200
# Count how many domains from the list actually got a response
grep -c '"expiresDate"' results.json