Whois Migration To RDAP service
I have been using whois in the terminal to avoid giving my domain ideas to the squatters who inhabit some of the search sites. Now the whois is being replaced; we need some way to do the same, i.e., to avoid third-party services altogether.
Why
The WHOIS server prints, “This WHOIS server is being retired. Please use our RDAP service instead.” RDAP is the replacement: plain HTTPS + JSON, queried against the registry itself.
Avoid third-party lookup sites (including the rdap.org redirector). They see every domain you search, and some use that to squat domains. Querying the registry directly means only the registry sees the lookup, the same as whois. IANA only sees that the bootstrap file was fetched.
How it works
- IANA publishes a bootstrap file mapping each TLD to its registry’s RDAP server: https://data.iana.org/rdap/dns.json
- Download it once, cache it locally, and refresh it weekly.
- Look up the TLD in the cache, then query
<registry-base>/domain/<domain>directly.
Requirements
curl and jq
Install
Paste into ~/.bashrc or ~/.zshrc then reload the shell (source ~/.bashrc).
rdap() {
local domain tld cache base code body
domain=$(printf '%s' "$1" | tr 'A-Z' 'a-z')
[ -z "$domain" ] && { echo "usage: rdap domain.tld" >&2; return 1; }
tld="${domain##*.}"
cache="${XDG_CACHE_HOME:-$HOME/.cache}/rdap-dns.json"
mkdir -p "$(dirname "$cache")"
# refresh the IANA bootstrap file if missing or older than 7 days
if [ ! -s "$cache" ] || [ -n "$(find "$cache" -mtime +7 2>/dev/null)" ]; then
curl -sf https://data.iana.org/rdap/dns.json -o "$cache" \
|| { echo "couldn't fetch IANA bootstrap file" >&2; return 1; }
fi
# find the registry's RDAP base URL for this TLD (prefer https)
base=$(jq -r --arg t "$tld" '
[.services[] | select(.[0] | index($t)) | .[1][]]
| (map(select(startswith("https"))) + .) | first // empty' "$cache")
[ -z "$base" ] && { echo "no RDAP server listed for .$tld" >&2; return 1; }
# query the registry directly; split body and HTTP status code
body=$(curl -s -w '\n%{http_code}' "${base%/}/domain/$domain")
code="${body##*$'\n'}"
body="${body%$'\n'*}"
case "$code" in
200) printf '%s' "$body" | jq '{
name: .ldhName,
status: .status,
registrar: ([.entities[]? | select(.roles | index("registrar"))
| .vcardArray[1][] | select(.[0]=="fn") | .[3]] | first),
events: [.events[]? | {(.eventAction): .eventDate}],
nameservers: [.nameservers[]?.ldhName]
}' ;;
404) echo "$domain: not found (likely unregistered)" ;;
429) echo "rate limited by registry, try again shortly" >&2; return 1 ;;
*) echo "registry returned HTTP $code" >&2; return 1 ;;
esac
}
Usage
rdap example.com
Output: name, status, registrar, events (registration/expiry/last changed), nameservers.
For the full raw record, replace the jq '{ ... }' block in the 200 case with plain jq.
Manual one-off (no function)
# .com / .net
curl -s https://rdap.verisign.com/com/v1/domain/example.com | jq
# any other TLD: find its server in the bootstrap file
curl -s https://data.iana.org/rdap/dns.json | jq '.services[] | select(.[0] | index("org"))'
Notes
- 404 = unregistered, so it works as an availability check.
- Some ccTLDs have no RDAP server yet. The function says so; fall back to plain
whoisfor those. - Registrant details are redacted (GDPR), so expect registrar, status, dates, and nameservers only.
- Rate limiting: registries return HTTP 429 if you hammer them. Space out bulk lookups.
- Cache location:
~/.cache/rdap-dns.json. Delete it to force a refresh. - Other lookups: RDAP also handles IPs and ASNs at
<rir-server>/ip/<addr>and/autnum/<n>, using the bootstrap filesipv4.json,ipv6.jsonandasn.jsonin the same IANA directory.