Dev.to Security 🔐 Cybersecurity 👁 0 📖 2 min read

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/news was reduced to the registrable domain bbc.co.uk automatically.
  • .io-style and .de domains 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 null rather than guessed. Check for None before doing arithmetic.
  • Registrant names and emails are usually redacted because of GDPR. Don't build on them.

Ideas to build on it

  1. Expiry watchlist: run weekly on your portfolio and alert when daysUntilExpiry < 60.
  2. Lead scoring: low ageDays plus no MX can flag throwaway domains.
  3. 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].

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.