Bulk WHOIS & Domain Age Lookup (RDAP) - Expiry, Registrar
Pricing
$3.00 / 1,000 registered domain looked ups
Bulk WHOIS & Domain Age Lookup (RDAP) - Expiry, Registrar
Bulk WHOIS lookup over RDAP, the official successor protocol: domain age checker, domain expiry date, registrar, nameservers, DNSSEC and availability for domains, URLs, emails or Google Maps rows. No personal data. $0.003 per registered domain; available domains and failures are free.
Pricing
$3.00 / 1,000 registered domain looked ups
Rating
0.0
(0)
Developer
Luke Hunter
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
For sales, SEO, security, domain-investing and data teams that need WHOIS data for a whole list of domains. Paste domains, URLs, emails or a Google Maps / lead dataset and get one clean row per domain: the registration date and domain age in days, the domain expiry date and days to expiry, the registrar (name, IANA ID, website), nameservers, DNSSEC, status codes and, where the registry publishes it, the registrant organisation and country. It is a bulk WHOIS lookup and domain age checker built on RDAP, the official IETF replacement for WHOIS (RFC 9082 and 9083), so the answers are structured JSON from the registries themselves, not parsed WHOIS text.
$0.003 per registered domain with data. Available (unregistered) domains, TLDs without RDAP and failed lookups are free. 1,000 domains = $3.
No personal contact data, ever: emails, phone numbers, street addresses and the names of private individuals are dropped before anything is saved. Only the registrant's organisation name and country are kept, and only when the registry or registrar publishes them.
What you get
| Field | Meaning |
|---|---|
domain, input, tld | The registrable domain looked up (www, paths and subdomains removed, IDN as punycode), your original entry, and its TLD. |
status | registered (charged), or free: available, no-rdap, invalid, skipped, blocked, rate-limited, error, not-processed. |
registered | true, false (the registry has no record: available) or null (no answer). |
registrationDate, domainAgeDays | When the domain was first registered, and its age in whole days at the check. |
expirationDate, daysToExpiry | When the registration expires, and days left (negative if already past). |
lastChangedDate | When the record last changed. |
statusCodes | RDAP status values, e.g. client transfer prohibited, server delete prohibited. |
registrar, registrarIanaId, registrarUrl | The sponsoring registrar. |
nameservers, dnssec | Delegated nameservers and whether the delegation is DNSSEC-signed. |
registrantOrganization, registrantCountry | Only when published. Many registries redact them, so expect null for most domains. |
rdapServer, registrarRdapServer | The registry RDAP server that answered, and the registrar's RDAP server when it was also read. |
warnings, retryable, message, checkedAt | Data-quality notes, whether running again later may help, why a row has no data, and the check time. |
Quick start
{"domains": ["apify.com", "wikipedia.org", "github.io"],"maxItems": 5}
Entries can be domains (apify.com), URLs (https://www.apify.com/pricing), emails (sales@apify.com) or non-ASCII names (bücher.de). Subdomains are reduced to the registrable domain (blog.example.co.uk becomes example.co.uk) using the public suffix list, and duplicates are merged. Addresses at free-mail providers (gmail.com and similar) are skipped when they come from an email.
How it works
- The Actor loads the IANA RDAP bootstrap file (
data.iana.org/rdap/dns.json) once per run. It lists the authoritative RDAP server of every TLD that has one. - For each domain it asks that registry:
GET {server}domain/{domain}withAccept: application/rdap+json. - If the registry answer links to the registrar's own RDAP server (the usual case for
.comand.net), it follows that link once to add registrar-level data such as the registrant organisation, when the registrar publishes it. - An RDAP 404 means the registry has no record: the domain is reported as
availableand costs nothing.
It is deliberately gentle: robots.txt of every RDAP host is read and obeyed, requests to one host are spaced at least one second apart (longer if Crawl-delay asks), at most five domains are in flight at a time, and a 429 Too Many Requests is honoured with Retry-After and backoff. It never tries to get around a refusal.
Recipes
Domain age for lead scoring. Brand-new domains are a common sign of throwaway or low-trust companies; old domains correlate with established ones. Run your lead list and filter on domainAgeDays:
{"domains": ["acme.com", "https://www.example-startup.io/about", "jane@example-shop.co.uk"],"maxItems": 500}
Sort or filter the dataset on domainAgeDays (for example under 90 days is "new") and keep registrar and nameservers for context.
Expiring domains watch. Save your domain list as a Task, add a Schedule (weekly is plenty) and send the results to a Google Sheet, Slack or a webhook through the Integrations tab. Alert on daysToExpiry below 30:
{"domains": ["mycompany.com", "mycompany.org", "mycompany-shop.com"],"maxItems": 100}
Use it for your own portfolio, for suppliers and partners, or for competitors. A row with daysToExpiry below 0 means the registration has lapsed but the registry still holds the name (a grace period).
Enrich a Google Maps lead list with domain age. Run a Google Maps scraper first, then pass its default dataset ID. The Actor reads the website (or domain, url, email) field of each row:
{"datasetId": "<DEFAULT_DATASET_ID_OF_THE_GOOGLE_MAPS_RUN>","maxItems": 1000}
Join the result back to your leads on input (the website exactly as it appeared). The same works with datasets from Website Contact Scraper and Google Maps Email Extractor & Lead Enricher. Or pass rows directly: "rows": [{"title": "Acme", "website": "https://acme.com"}].
Find available domains. Check a list of candidate names; rows with status: "available" are unregistered according to the registry and are free.
Input
| Field | Default | What it does |
|---|---|---|
domains | none | Domains, URLs or emails. |
rows | none | Objects with a website, domain, url or email field, merged with domains. |
datasetId | none | An Apify dataset of such rows (up to 50,000 rows are read). |
maxItems | 100 | Hard cap on domains looked up and charged, 1 to 10,000. Domains beyond it are not looked up. |
Example output
{"domain": "acme-widgets.com","input": "https://www.acme-widgets.com/about","tld": "com","status": "registered","registered": true,"statusCodes": ["client delete prohibited", "client transfer prohibited", "client update prohibited", "server delete prohibited"],"registrationDate": "2015-03-12T09:30:00.000Z","expirationDate": "2027-03-12T09:30:00.000Z","lastChangedDate": "2026-02-01T11:00:00.000Z","domainAgeDays": 4232,"daysToExpiry": 150,"registrar": "Example Registrar, Inc.","registrarIanaId": 9999,"registrarUrl": "https://www.registrar.example","nameservers": ["ns1.dns-host.example", "ns2.dns-host.example"],"dnssec": false,"registrantOrganization": "Acme Widgets Ltd","registrantCountry": "GB","rdapServer": "https://rdap.registry.example/com/v1/","registrarRdapServer": "https://rdap.registrar.example/","warnings": [],"retryable": false,"message": null,"checkedAt": "2026-10-12T12:00:00.000Z"}
The sample is illustrative (an invented company on invented servers), shaped like real RDAP answers. An unregistered domain looks like this and is free:
{"domain": "free-name-1234.com","input": "free-name-1234.com","tld": "com","status": "available","registered": false,"statusCodes": [],"registrationDate": null,"expirationDate": null,"domainAgeDays": null,"daysToExpiry": null,"registrar": null,"nameservers": [],"rdapServer": "https://rdap.registry.example/com/v1/","retryable": false,"message": "The .com registry has no record of free-name-1234.com (RDAP 404): it looks unregistered and available. Free."}
(Fields with no data are null or empty in every row; the sample is shortened here.) Status meanings:
registered: RDAP data found. Charged.available: the registry has no record (RDAP 404). Free.no-rdap: the TLD has no RDAP server in the IANA bootstrap file, so there is nothing to ask. Free, with a clear message.invalid/skipped: not a domain, or a free-mail address. Free.blocked: the host'srobots.txtdisallows the request or could not be read, or the server refused it. Free.retryablesays whether trying later may help.rate-limited/error: the server kept saying 429, had an error or could not be reached. Free andretryable.not-processed: not looked up because your spending limit or the run time limit was reached. Free; run those again.
Use with AI agents (MCP)
This Actor works as a tool for Claude, ChatGPT, Cursor and other MCP clients through Apify's MCP server. Every input property description is short and carries an example, so agents fill it in correctly. None is required, but give it domains, rows or a datasetId.
Claude Desktop (claude_desktop_config.json), with your own token from Apify Console > Settings > API & Integrations:
{"mcpServers": {"apify-domain-whois-rdap-lookup": {"command": "npx","args": ["-y", "mcp-remote","https://mcp.apify.com?tools=lukehunter/domain-whois-rdap-lookup","--header", "Authorization: Bearer ${APIFY_TOKEN}"],"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }}}}
Clients that support OAuth (Claude.ai, VS Code) can connect with just the URL https://mcp.apify.com?tools=lukehunter/domain-whois-rdap-lookup and sign in to Apify. Never paste a real token into a shared file or chat.
Example. You ask: "How old is apify.com and when does it expire?" The agent calls lukehunter--domain-whois-rdap-lookup with:
{"domains": ["apify.com"],"maxItems": 1}
It is charged $0.003 for the one registered domain, capped by maxItems.
Pricing
Pay-per-event: $0.003 per registered domain (event domain), meaning one domain whose RDAP data was read. Available domains, TLDs without RDAP, blocked, rate-limited and failed lookups and not-processed rows are free.
| Domains | Cost if all are registered |
|---|---|
| 5 | $0.015 |
| 100 (default cap) | $0.30 |
| 1,000 | $3.00 |
| 10,000 (maximum) | $30.00 |
For comparison, other WHOIS and domain lookup Actors on the Apify Store were listed in October 2026 at roughly $0.0025 to $0.003 per domain, with one outlier at $0.02, and a free availability checker without a paid path. maxItems and your Apify per-run spending limit both stop delivery before the cap is passed: a result is delivered and charged together, and never past your limit. Price changes follow Apify's notice rules; the Pricing tab always shows the rate you are charged.
Limitations
- RDAP availability varies by TLD. Most generic TLDs (
.com,.net,.org,.ioand hundreds of new ones) have RDAP servers, but some country-code registries only offer WHOIS or a web form, and a few publish very little. Those come back asno-rdap(free). The server list comes from the IANA bootstrap file at run time, so it is always current. - Registrant data is often redacted. Since GDPR, most registries and registrars hide registrant details.
registrantOrganizationandregistrantCountryarenullunless they are really published. This Actor does not try to unmask anything. - No personal contact data by design. Emails, phones, street addresses and the names of private individuals are never read into the output, even when a server publishes them. If you need contact data, use the registrar's own channels.
- Registry limits and speed. Registries throttle bulk use, so the Actor sends one request per second per host (two per
.comdomain when the registrar is also read). 1,000.comdomains take roughly 30 to 35 minutes. A run stops after 5 hours and reports what is left. Different TLDs are looked up in parallel. robots.txtis obeyed. If an RDAP host disallows the request, or itsrobots.txtcannot be read (server error, refusal), that host is not requested in the run and its domains come back asblocked(free). A host that answers 404 or another 4xx forrobots.txthas no restrictions, as RFC 9309 says.- It reports the registration, not the owner's intent.
availablemeans the registry has no record right now. Reserved and premium names, and names a registry blocks, can also answer 404. Confirm with a registrar before buying. - Dates are the registry's. Expiry dates move when a domain is renewed; schedule the Actor if you need to track them. A negative
daysToExpirymeans the registration has lapsed but the name is still held by the registry. - Not legal advice. This Actor is independent and not affiliated with ICANN, IANA or any registry or registrar. RDAP data is public registration data; use it in line with each registry's terms and applicable law.
Use it from your code, Make, Zapier or n8n
Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.
One API call that runs the Actor and returns the data (replace $APIFY_TOKEN with your token from Apify Console → Settings → Integrations):
curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~domain-whois-rdap-lookup/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"domains": ["apify.com", "wikipedia.org", "github.io"], "maxItems": 5}'
JavaScript (npm i apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lukehunter~domain-whois-rdap-lookup').call({"domains": ["apify.com","wikipedia.org","github.io"],"maxItems": 5});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python (pip install apify-client):
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('lukehunter~domain-whois-rdap-lookup').call(run_input={"domains": ["apify.com", "wikipedia.org", "github.io"], "maxItems": 5})items = client.dataset(run['defaultDatasetId']).list_items().items
Schedules, webhooks and no-code tools: save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.
Feedback: an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.
FAQ
What is RDAP and why not WHOIS? RDAP (Registration Data Access Protocol) is the IETF standard that replaces the port-43 WHOIS protocol. It returns structured JSON over HTTPS, with standard fields for dates, status and nameservers, and ICANN requires it of generic TLD registries and registrars. That makes the data cleaner and the lookups more reliable than parsing free-text WHOIS.
Why is the registrant empty for most domains? Registries and registrars redact it for privacy. The Actor outputs an organisation and country only when one is genuinely published.
Which domains are charged? Only registered rows, $0.003 each. available, no-rdap, blocked, rate-limited, error, invalid, skipped and not-processed are free.
Does it check subdomains? No. WHOIS is about the registered domain, so blog.example.co.uk is looked up as example.co.uk. For github.io, a public suffix owned by one registrant, the domain itself is looked up.
How is domainAgeDays calculated? Whole days from the RDAP registration event to the moment of the check. It is null when the registry publishes no registration date.
A lookup came back rate-limited. What now? The registry kept asking to slow down. Run those domains again later; they were not charged.
Related Actors
Other data tools from the same developer, built to the same standard: official or public sources, hard cost caps, and honest documentation of limits.
- Domain Email Provider Lookup: the email provider (Google Workspace, Microsoft 365, Zoho and more), MX, SPF and DMARC setup of any domain list, with provider-change alerts.
- French Company Leads: French companies (entreprises) from the official Sirene-based API, filtered by NAF code, department, headcount and creation date, with SIREN/SIRET, officers and new-company alerts.
- Poland KRS Company Lookup: Polish companies from the official KRS API by KRS number: NIP, REGON, address, share capital, PKD and the board as published, with optional VAT status.
- EU VAT Number Validator: bulk EU VAT number checks against the official VIES service: valid or invalid, registered name and address, with optional consultation numbers.
- Website Contact Scraper: emails, phone numbers and social profile links from any list of company domains, with the page each came from and a changed-contacts-only mode for scheduled runs.
- Impressum Scraper: legal entity data from the imprint of any company website in Germany, Austria and Switzerland: legal name and form, managing directors, HRB/HRA or FN register, VAT id and address, with a changed-data-only mode for scheduled runs.
- Website Tech Stack Detector: the technologies a website runs (CMS, ecommerce platform, analytics, ad pixels, chat, payments, CDN, frameworks) from its home page, with the evidence for each match and a changed-technologies-only mode for scheduled runs.
- Google Maps Email Extractor & Lead Enricher: emails, phones, social links, named people and the tech stack of every business in your Google Maps Scraper results, one enriched row per business, with filters such as only Shopify stores with an email.