Domain Expiry, WHOIS & DNS Lookup: Failed Runs Cost Nothing
Pricing
from $0.42 / 1,000 domain looked ups
Domain Expiry, WHOIS & DNS Lookup: Failed Runs Cost Nothing
Domain expiry dates, days left, registrar, EPP status, nameservers and DNSSEC from the registries over RDAP (not WHOIS), plus live DNS records, for up to 2,000 domains. Says whether registry and live nameservers agree. A failed or empty run costs nothing. Free dry run, spend cap, no start fee.
Pricing
from $0.42 / 1,000 domain looked ups
Rating
0.0
(0)
Developer
Monty Burrows
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Domain Registration, Expiry & DNS Lookup
Give it a list of domains. Every run returns one row per domain: the registrar, the EPP status codes, the registration and expiry dates, how many days are left, the nameservers and whether it is DNSSEC-signed. The same row carries what the domain actually resolves to right now, and a column that says whether those two agree.
Read straight from the registries over RDAP, the protocol ICANN requires them to publish, and from live DNS over DNS-over-HTTPS. No login, no API key, no screen scraping.
Paste a hostname and it is reduced to the domain its registry actually holds: www.example.com
is looked up as example.com, because a registry has no record of the first and would return the
same 404 it returns for a name nobody has registered.
No per-run fee, and no contact details, ever. See below, because that second one is a deliberate limitation as much as it is a promise.
What it is for
Set it on a daily schedule over your domain portfolio and sort by Days left. That is the whole product, and 200 domains checked every day costs about $3.60 a month.
It also answers, as a by-product:
- Is this name available? A registry with no record returns exactly that.
- Who is it registered with, and when does it move?
registrar, and the EPP status codes that say whether a transfer or a delete is locked. - Where does it point, and is that where it should?
dnsA,dnsMx,dnsNsand the rest, anddelegationStatus(see the next section). - Has anything changed?
nameservers,dnssecSignedandlastChangedAt, on every run.
Two readings of the same domain, on one row
RDAP tells you what the registry holds. DNS tells you what the world actually sees. Most of the time they say the same thing, and the interesting moments are the ones where they do not.
delegationStatus is the column that says so, and it is the one thing on this row that neither
half could produce on its own. It is graded rather than a yes/no, because the registry's
delegation and your zone's own NS records are allowed to differ and routinely do:
| It says | What it means | Worth acting on |
|---|---|---|
| match | The same set of nameservers on both sides | No |
| extra | Your zone publishes the registry's servers, and more besides | Rarely |
| partial | They overlap, but each has one the other lacks | Usually (see below) |
| mismatch | Nothing in common. The domain now answers from somewhere else | Yes |
| empty | One side had nothing to compare. Not a disagreement | No |
Why graded and not a tick box: of nine established domains checked on 2026-09-23, eight matched
exactly and github.io did not. Identity Digital holds five nameservers for it and the zone
publishes eight, those five among them. Both are correct, and a boolean would have reported
GitHub's own domain as suspicious. partial is the quieter one worth looking at: it means the
registry still delegates to a nameserver your zone no longer lists, which is how a lame delegation
starts.
You also get the records themselves: A, MX and NS by default, and AAAA, TXT, CAA and
SOA if you tick them. They are included in the price. Each extra record type is one more
request per domain, so asking for all seven makes a run slower, not dearer.
There is no CNAME, and that is deliberate. Every name here is looked up as a registrable domain,
and a domain that resolves is a zone apex, which cannot carry a CNAME at all. It came back empty
on all 36 domains tried, including every apex-aliasing platform. A column that can never be filled
is not worth the space in your spreadsheet.
Clear the field entirely and you get a pure registry lookup, with the DNS columns left empty.
No registrant contact data. Ever.
This is worth a section because it cuts both ways.
For .com, .net, .org and the other gTLDs it costs you nothing: post-GDPR the registries
redact the registrant entirely, so there is nothing to collect. Every domain in a sample of
eight returned the registrar and no one else.
Some country-code registries are different. .fr publishes, with nothing redacted:
a name, an organisation, a postal address, an email address and a telephone number
for the registrant, the administrative contact and the technical contact. For a company those are corporate details. For a domain registered by an individual they are that person's home address and phone number.
This Actor reads none of it. The only entity it touches is the registrar, because a
registrar is a company by definition. If you need registrant contact details, this is not the
Actor. That is a decision, not an oversight.
There is one switch that changes this and it is off by default: Include the raw RDAP document adds the registry's whole response to each row, contacts and all. The listing tells you what is in it; what you do with it is yours.
Coverage, which is the real limitation
RDAP is discovered from IANA's own bootstrap file, fetched live on every run rather than pinned to a stale copy. On 2026-09-16 it listed 1,202 TLDs.
Every gTLD (.com, .net, .org, .app, .dev and 1,100 more) | Covered |
| Country-code TLDs in IANA's bootstrap | 71 of roughly 250 |
| Added by hand, each verified by a live lookup | .io .de .us .ch |
| Not covered | .co .eu .jp .cn .ru .me .se .it .es and most of Europe |
Bootstrapping is voluntary for country-code registries and most have not done it. A domain on an uncovered TLD gets a row saying exactly that, with the reason. It also gets its live DNS records, which for those domains are the only reading anyone can give you.
Run a free dry run first. It tells you how many of your domains are on a covered TLD and how
many are not, before you are charged for any of them. If half your portfolio is .co, you will
know in one free run rather than after a bill.
What you get


| Group | Fields |
|---|---|
| Expiry | expiresAt, daysUntilExpiry, registeredAt, lastChangedAt |
| Registration | registrar, registrarIanaId, statuses, isRegistered, outcome |
| Delegation | nameservers (registry), dnsNs (live), delegationStatus |
| Live DNS | dnsA, dnsAaaa, dnsMx, dnsTxt, dnsCaa, dnsSoa |
| DNS status | dnsStatus (ok, nxdomain, failed), dnsTruncated, dnssecSigned |
| Identity | domain, tld, ldhName, unicodeName |
| Provenance | rdapServer, rawRecord, detail, scrapedAt, sourceUrl, runId, id |
Read dnsStatus before believing an empty DNS column. An empty dnsMx on a row whose
dnsStatus is ok means the domain takes no mail. An empty dnsMx on a row whose dnsStatus is
empty means nobody asked.
Not every registry publishes an expiry date
This is the one caveat on the headline use case and it is a real one, not a theoretical one:
- auDA (
.au) publishes only a last-changed date. - DENIC (
.de) publishes a single event.
expiresAt and daysUntilExpiry are empty on those, and the run report counts how many rows are
in that position. An expiry monitor cannot promise this column for every TLD, and this one does
not pretend to.
Pricing
From $0.42 per 1,000 domains, and nothing else. No per-run fee, no charge for compute or retries, and no separate charge for the DNS half: one price covers both readings.
| Your Apify plan | Per domain | Per 1,000 domains |
|---|---|---|
| Free | $0.0006 | $0.60 |
| Bronze | $0.00054 | $0.54 |
| Silver | $0.00048 | $0.48 |
| Gold | $0.00042 | $0.42 |
| Platinum | $0.00042 | $0.42 |
| Diamond | $0.00042 | $0.42 |

The status line is the estimate. A dry run writes no rows, so its results table stays empty, and it charges nothing.


The start fee is the part worth comparing
A domain portfolio is checked on a schedule (that is what an expiry monitor is), so a per-run fee is levied every day, forever. Measured 2026-09-23:
| Actor | Per run | Per domain |
|---|---|---|
automation-lab/domain-availability-checker | $0.035 | $0.001 |
perryay/domain-age-history-checker | $0.025 | per domain |
ntriqpro/whois-domain-lookup | run-start | $0.02 |
visita/domain-inspector | start | $0.004 |
santamaria-automations/domain-whois-dns | $0.001 | $0.002 |
| this Actor | none | $0.0006 to $0.00042 |
At $0.035 a start, a daily check costs $12.78 a year before a single domain is looked up.
What it costs in practice
| What you are doing | Rows | Cost |
|---|---|---|
| 200 domains, once | 200 | $0.12 |
| 200 domains, daily | 200 a run | about $3.60 a month |
| 2,000 domains, weekly | 2,000 a run | about $5.20 a month |
Every domain is charged, including the ones on TLDs with no RDAP service. That rule needs
stating plainly because it is the one you might reasonably object to. The reason it is right: "no
RDAP service is published for .co" is a fact about the TLD, read from IANA's own registry, and
any RDAP client would return the same answer. It is what tells you to stop trying to monitor
those domains this way. The free dry run is where you find out how many of yours those are.
What is never charged is a domain we could not get an answer about: a registry that refused us, throttled us, was down, or replied with something that is not RDAP. Those produce no row at all. And charges settle only after the run succeeds and its health checks pass.
What happens when something changes
Every run is checked against what a healthy run looks like, and a run that fails a check is not billed:
- Every domain ended in exactly one bucket. On an expiry monitor a domain that silently produced nothing is indistinguishable from one that is not expiring.
- IANA's bootstrap was read. Without it this Actor would know four TLDs instead of 1,202 and report almost everything as uncovered: nearly free, and completely wrong.
- No undeclared field reached a row. On this Actor that is not routine schema hygiene: the declared columns are how "no contact data" is enforced.
- Most answerable domains got an answer, and we are not being refused at scale.
- The registries still answered in RDAP.
- The pacing was honoured. One request per second per registry, and note per registry: one server answers for 451 TLDs. The resolver has its own, separate gap.
- The DNS half actually ran. A run that asked for DNS records and resolved nothing fails. A resolver that was merely unreachable for most of the list warns instead. Your registry columns are unaffected, and a correct registry reading should not be refunded because a second, supplementary one was unavailable.
Limits
- 2,000 domains per run, one request each to its registry, plus one per DNS record type, plus one for IANA's bootstrap.
- One row per registrable domain. A hostname is reduced to it, so
example.comandwww.example.comin one list are one lookup and one charge. The DNS columns describe the registrable name, not the hostname you pasted. - The DNS reading is a public resolver's view, not yours. It is what Cloudflare's
1.1.1.1resolves, which is the right answer for "is this domain delegated where I think it is" and the wrong one for anything depending on split-horizon DNS or your own network's resolver. - A dry run resolves nothing. Its count is exact and does not depend on DNS, so it does not spend anyone's resolver to produce a number it already knows.
.co,.euand most of Europe are not covered. See above. Check with a free dry run.- No expiry date from some registries, including
.auand.de. - No registrant, administrative, technical or billing contact, by design.
- RDAP only, no WHOIS. The old port-43 protocol covers more TLDs and is an unparseable mess of per-registry text formats. This Actor reads the structured one and tells you where it cannot.
- It keeps no state between runs. Every run returns the current reading; you decide what
changed.
GROUP BY domain ORDER BY scrapedAtis a better diff than any this Actor could impose.
Run it on a schedule
Save your input as a task and add an Apify Schedule to run it daily, weekly or hourly. When a run finishes, Apify's integrations can pass its rows to Google Sheets, Zapier, Make or n8n, and a webhook can call your own endpoint. A run that fails costs nothing and does not fire an integration or webhook set to run on success.
This is what it is for. Every run reads every domain on the list again, so a daily schedule sorted
by Days left is an expiry monitor, and 200 domains checked daily costs about $3.60 a month.
nameservers, dnssecSigned and lastChangedAt come back on every run, for spotting what
changed.
Use it from an AI agent
Apify's MCP server loads this Actor as a single tool:
https://mcp.apify.com/?tools=montyburrows/domain-rdap
An agent with it can run the Actor with the same inputs as the form, dry run and spend cap included, and read the registry and DNS answers it returns, billed to your Apify account at the prices above.
FAQ
How much does it cost to check domain expiry dates?
$0.60 per 1,000 domains on Apify's free plan, and $0.42 per 1,000 on Gold and above, with no start fee and the DNS records included. Apify's free plan gives $5 of usage a month, which at $0.0006 a domain is about 8,333 domains. Every domain answered is charged, including one on a TLD with no RDAP service. A domain no registry would answer about produces no row and no charge, a failed run and an empty run cost nothing, and the dry run is free and tells you how many of your domains are covered before you pay for any.
Is it legal to look up domains this way?
This Actor reads RDAP, the protocol ICANN requires registries to publish, and live DNS over DNS-over-HTTPS, with no login and no API key. It reads no registrant contact data: the only entity it touches is the registrar. The one exception is Include the raw RDAP document, off by default, which adds the registry's whole response, contacts and all. Whether a particular use is lawful depends on what you do with the data and where you are, and nothing here is legal advice.
Is this a WHOIS lookup?
It answers the questions people use WHOIS for (registrar, dates, status and nameservers), read over RDAP rather than WHOIS. WHOIS covers more TLDs in a different text format for each registry; RDAP is structured, and this Actor says where it cannot reach.
Which TLDs does it cover?
Every gTLD, the 71 country-code TLDs in IANA's bootstrap, and .io, .de, .us and .ch added by
hand. .co, .eu, .jp and most of Europe are not covered; those domains still get a row saying
so, with their live DNS.
Why is the expiry date empty for some domains?
Some registries do not publish one: .au publishes only a last-changed date and .de a single
event. The run report counts how many rows are in that position.
Can it tell me whether a domain is available?
A registry with no record of a name returns exactly that, and isRegistered says so on the row.
Other Actors from this developer
Every one has the same free dry run and spend cap, and none charges for a failed run.
- Google Flights Scraper: live Google Flights fares for any route and date
- Shopify Product Scraper: every product and variant from a list of Shopify stores
- Shopify Price & Stock Tracker: price and stock on the Shopify product pages you choose
- Shopify Store Checker: which of a list of domains are readable Shopify stores
- RSS Feed Reader: RSS, Atom and RDF feeds in one table
Support and feature requests
Need a TLD adding, or another field? Email actors@montyburrows.com. Feature requests are welcome: a ccTLD whose registry runs RDAP is usually a one-line change.