Bulk domain age, expiry and DNS audit in Python: RDAP with WHOIS fallback
A domain list is a surprisingly useful dataset. Which of your 500 customer domains expire this quarter? Which lead domains were registered last month (often a trust signal)? Which of your own domains have no DMARC record
A domain list is a surprisingly useful dataset. Which of your 500 customer domains expire this quarter? Which lead domains were registered last month (often a trust signal)? Which of your own domains have no DMARC record? All of it is public data, but getting it for a whole list means juggling RDAP, legacy WHOIS servers and DNS lookups.
This tutorial uses one Apify Actor, Domain WHOIS & DNS Lookup, to turn a list of domains into clean JSON rows: registrar, creation and expiry dates, age, nameservers, plus MX, SPF and DMARC. I'm the maker, so the pricing is stated up front: $1 per 1,000 domains, and invalid inputs, duplicates and failed lookups are free.
The code
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("siftwright/domain-whois-dns-lookup").call(run_input={
"domains": ["stripe.com", "github.io", "https://www.bbc.co.uk/news", "spiegel.de", "this-name-should-not-exist-siftwright-test.com"],
})
for d in client.dataset(run.default_dataset_id).iterate_items():
if not d["registered"]:
print(f'{d["domain"]:<14} not registered (likelyAvailable={d["likelyAvailable"]})'); continue
dns = d.get("dns") or {}
soon = d["daysUntilExpiry"] is not None and d["daysUntilExpiry"] < 90
print(f'{d["domain"]:<14} {d["registrar"] or "?":<30} age {d["ageDays"]} days src={d["source"]}'
f'{" EXPIRES<90d" if soon else ""}{" NO-DMARC" if not dns.get("dmarc") else ""}{" NO-SPF" if not dns.get("spf") else ""}')
Install with pip install apify-client (3.x; on 2.x use run["defaultDatasetId"]) and set APIFY_TOKEN.
Real output
This is the output of that exact script, run on 2026-10-05 (the last row is a made-up name, so it comes back unregistered):
this-name-should-not-exist-siftwright-test.com not registered (likelyAvailable=True)
stripe.com SafeNames Ltd. age 11346 days src=rdap
github.io MarkMonitor Inc. age 4958 days src=whois NO-DMARC
spiegel.de ? age None days src=whois
bbc.co.uk British Broadcasting Corporation age 11619 days src=rdap
Things worth noticing:
-
https://www.bbc.co.uk/newswas reduced to the registrable domainbbc.co.ukautomatically. -
.io-style and.dedomains have no usable RDAP, so the Actor falls back to classic WHOIS (src=whois). -
.de registries publish very little. spiegel.de has no registrar or creation date in public data, so those fields are
nullrather than guessed. Check forNonebefore doing arithmetic. - Registrant names and emails are usually redacted because of GDPR. Don't build on them.
Ideas to build on it
-
Expiry watchlist: run weekly on your portfolio and alert when
daysUntilExpiry < 60. -
Lead scoring: low
ageDaysplus no MX can flag throwaway domains. - Email deliverability audit: list every domain missing SPF or DMARC.
Pricing and limits
Pay-per-event at $0.001 per domain looked up (registered or not). Apify's free plan includes monthly credits, so you can try it at no cost. AI agents can also call it through Apify's MCP server: https://mcp.apify.com?tools=siftwright/domain-whois-dns-lookup.
Full details and the product page: siftwright.com/domain-whois-lookup/. Questions: [email protected].
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.