Domain Expiry Monitor: Bulk WHOIS/RDAP & DNS Changes
Pricing
$2.00 / 1,000 domain checkeds
Domain Expiry Monitor: Bulk WHOIS/RDAP & DNS Changes
Check up to 5,000 domains per run for expiry date, registrar, nameservers, status and DNS records from official RDAP, flagged with what changed since your last run: expiring soon, registrar moved, became available. $2 per 1,000 domains; failed lookups free.
Pricing
$2.00 / 1,000 domain checkeds
Rating
0.0
(0)
Developer
Changefeeds Tools
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
- What you get: one row per domain with expiry date, days to expiry, registrar, nameservers, EPP status flags, DNSSEC and A/AAAA/MX/NS/TXT records, read from the registry's official RDAP server (the JSON successor to WHOIS).
- Compared with your last run: each row lists what changed:
expiry_changed,registrar_changed,nameservers_changed,status_changed,became_available,became_registered,dns_changed:<type>, plus anexpiring_soonflag. Up to 5,000 domains per run. - Price: $2 per 1,000 domains checked, DNS included. Failed lookups and unsupported TLDs are free.
Sample output
The prefilled list (example.com, apify.com) run on 2026-10-23, compared
with our previous run of the same list:
| domain | registrar | expires | days_to_expiry | nameservers | changes |
|---|---|---|---|---|---|
| example.com | RESERVED-Internet Assigned Numbers Authority | 2027-08-13 | 295 | elliott / hera.ns.cloudflare.com | none |
| apify.com | Amazon Registrar, Inc. | 2035-06-02 | 3,145 | 4 × awsdns | dns_changed:aaaa, dns_changed:txt |
The example.com row in full:
{"domain": "example.com","status": "registered","registrar": "RESERVED-Internet Assigned Numbers Authority","registrar_iana_id": "376","created": "1995-08-14T04:00:00Z","expires": "2027-08-13T04:00:00Z","updated": "2026-08-14T08:01:43Z","days_to_expiry": 295,"expiring_soon": false,"rdap_status": "200","status_flags": ["client delete prohibited", "client transfer prohibited", "client update prohibited"],"nameservers": ["elliott.ns.cloudflare.com", "hera.ns.cloudflare.com"],"dnssec": true,"dns": {"a": ["104.20.23.154", "172.66.147.243"],"aaaa": ["2606:4700:10::6814:179a", "2606:4700:10::ac42:93f3"],"mx": ["0 "],"ns": ["elliott.ns.cloudflare.com", "hera.ns.cloudflare.com"],"txt": ["_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9", "v=spf1 -all"],"dns_error": []},"changes": ["none"],"checked_at": "2026-10-23T03:50:06.018Z","error": null}
mx: ["0 "] is a null MX record (priority 0, no mail host): the domain
accepts no email.
Your first run is a baseline. Every domain it reads gets
changes: ["baseline"] and its snapshot is saved; change flags start from the
second run of the same list. expiring_soon works from the first run.
How to run in 30 seconds
- Click Try for free. The input already holds
example.comandapify.com. - Click Start. Our first run of that input took 16 seconds and cost $0.004 (2 domains).
- Paste your own domains (one per line;
https://, paths andwww.are stripped), set Expiring within (days), then save it as a task and add a daily schedule.
Pricing
- $0.002 per domain looked up successfully ($2 per 1,000). DNS resolution and change detection are included.
- Free: domains whose lookup fails (
error), TLDs without an RDAP server (unsupported_tld), and snapshot read failures. - Every run checks every domain on the list, so you pay per domain per run:
- first run, 500 domains: $1.00;
- the same 500 domains daily: $1.00 a run, about $30 a month;
- 5,000 domains weekly: $10.00 a run, about $43 a month.
- Set a maximum total charge and the actor stops starting new domains when it
is reached (
charge_limit_reached: truein the summary); domains already checked are still counted.
FAQ
How do I get expiry alerts in Slack? Save your list as a task, add a daily
schedule, and set Webhook URL to a Slack incoming webhook (or a Zapier/Make
"Catch Hook"). After each run it POSTs { summary, rows } with the changed and
expiring rows (up to 500). Or attach an
Apify integration (Slack, Google
Sheets, Zapier, Make) to the task's "run succeeded" event.
Is this WHOIS? It uses RDAP, the registries' official JSON replacement for
WHOIS, found through the IANA bootstrap file
(https://data.iana.org/rdap/dns.json) with rdap.org as the fallback. You get
the same registration facts in a stable format.
Does became_available mean I can buy the domain? No. It means the
registry's own RDAP server no longer finds a registration. Premium, reserved
or locked names can still be unavailable.
Why does a domain show dns_changed:aaaa on every run? Domains behind a CDN
rotate their A/AAAA addresses: apify.com (CloudFront) returned a different
set of eight AAAA records 7 minutes apart on 2026-10-23. Ignore those types for
CDN-hosted domains, or turn Include DNS records off.
What happens when a lookup fails? The row gets lookup_failed, it is not
charged, and the saved snapshot is not overwritten, so a registry outage never
looks like a change.
Limits
- RDAP coverage varies by TLD. All gTLDs (.com, .net, .org, .app, ...) are
covered; some ccTLDs have no RDAP service at all. Those fall back to
rdap.org, and when it knows no authoritative server the result isunsupported_tld(free, never reported as "available"). - No registrant contacts. Registrant data is usually redacted under GDPR and registry policy, and this actor does not collect it.
- Some registries return sparse data (no expiry date, no registrar ID); those
fields are
null. - A failed DNS lookup is not a change. A record type whose lookup fails
transiently (for example a timeout) keeps the last observed value, is not
compared this run, and the other record types are still compared. A DNS
record type that was never observed before is baselined silently: its first
successful observation produces no
dns_changedflag. - Not compared: creation date, last-changed date, registrar IANA ID and DNSSEC are reported in the row but never flagged.
- Polite by design: at most one request in flight per host, at least 500 ms
apart (1,100 ms for
rdap.org, which allows 10 requests per 10 seconds), HTTP 429Retry-Afterhonoured, 15-second timeout. 5,000 domains on one registry take a while.
Change flags
baseline (first run), none, became_registered, became_available,
registrar_changed, expiry_changed, status_changed (EPP flags),
nameservers_changed, dns_changed:<a|aaaa|mx|ns|txt>, lookup_failed
(RDAP lookup failure; nothing is compared), snapshot_read_failed, and
snapshot_write_failed (the row was delivered and charged, but its history
snapshot could not be stored after retries).
Input reference
{"domains": ["example.com", "https://www.example.io/about"],"expiringWithinDays": 30,"includeDns": true,"snapshotKey": "my-monitor-set","webhookUrl": "https://example.com/hook"}
domains(required, max 5,000): schemes, paths andwww.are stripped; internationalized names are punycoded.expiringWithinDays(default 30): setexpiring_soonon domains expiring within this window.includeDns(default true): resolve and compare DNS records. Whenfalse, the previous run's DNS records stay in the snapshot unchanged, so no DNS history is lost.snapshotKey(optional): which saved snapshot to compare against. Default is a hash of the sorted domain list. Set a fixed name to keep history when you edit the list.webhookUrl(optional): receives{ summary, rows }with changed and expiring rows (max 500) after the run.
Output reference
status is one of:
registered: the registry's RDAP server returned the domain.not_registered: the registry's own RDAP server (found via the IANA bootstrap) answered 404.unsupported_tld: no authoritative RDAP server is known for the TLD. Not charged; the snapshot is not overwritten.error: lookup or infrastructure failure. Not charged; the snapshot is not overwritten.
The summary is saved to the default key-value store as OUTPUT. From the
2026-10-23 run above:
{"domains": 2, "registered": 2, "not_registered": 0, "unsupported_tld": 0,"errors": 0, "expiring_soon": 0, "changed": 1, "first_run": false,"charged": 2, "charge_limit_reached": false,"skipped_after_charge_limit": 0, "snapshot_write_failed": 0,"snapshot_key": "0f7391b3d73db6ec"}
On a first run every successfully looked-up row counts toward changed.
Failure rows (status error, or changes that are only lookup_failed,
snapshot_read_failed, invalid_response or snapshot_write_failed) are
excluded from changed and from the webhook.