# Bulk WHOIS & RDAP Domain Lookup - Age, Expiry, DNS (`kadi_bence/domain-whois-lookup`) Actor

Look up domains via official RDAP (WHOIS). Input: list of domains; optional DNS records. Returns per domain: registered, registrar, creation and expiry dates, domain age, nameservers, status, DNSSEC, plus DNS/MX/SPF/DMARC. 1,100+ TLDs, no personal data, no API key.

- **URL**: https://apify.com/kadi_bence/domain-whois-lookup.md
- **Developed by:** [Bence Kadi](https://apify.com/kadi_bence) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 domains

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bulk WHOIS & RDAP Domain Lookup: age, expiry, registrar, DNS

Look up **registrar, creation and expiry dates, domain age, EPP status, nameservers and DNSSEC** for any list of domains from each registry's official **RDAP** service (the modern WHOIS), plus **DNS, SPF, DMARC and e-mail provider**. **$1.50 per 1,000 domains**.

### 🔎 What is Bulk WHOIS & RDAP Domain Lookup?

A bulk WHOIS tool that asks each domain's own registry for its public data over RDAP, the ICANN-mandated successor of WHOIS. Paste domains, URLs or e-mail addresses; get one clean row per domain, ready for a spreadsheet, CRM or API.

- 🌍 **1,100+ TLDs from the official source:** generic TLDs (.com, .org, .io, .ai, .app...) and 90+ country TLDs via IANA's RDAP bootstrap, plus verified registry servers IANA doesn't list yet (.de, .io, .ch, .us, .me). RDAP only, never port-43 WHOIS.
- 🛡️ **GDPR-safe:** no names, e-mails, phones or addresses of people, ever. Registrant organisation only when clearly a legal entity (GitHub, Inc.). No raw WHOIS text.
- 📬 **DNS & e-mail included:** A/AAAA/MX/NS/TXT, SPF, DMARC and the e-mail provider, at no extra cost. Competitors charge $3+ per 1,000 for WHOIS + DNS.
- 🧮 **Ready-to-filter:** `domainAgeDays` and `daysUntilExpiry` computed; ISO 8601 UTC dates; standard EPP status names.
- 💸 **Failures are free:** not-registered, unsupported, timed-out and rate-limited domains are listed with the reason, not charged.
- 🤝 **Polite by design:** per-registry rate limits, automatic slow-down on HTTP 429, `Retry-After` honoured, robots.txt opt-outs respected. No proxies, no IP rotation.
- 🔁 **Messy input OK:** URLs and e-mail addresses become the registrable domain; IDNs (münchen.de) work.

#### 🎯 Use cases

- **Expiry monitoring (agencies, IT teams):** filter `daysUntilExpiry < 30` to catch renewals before they lapse.
- **Fraud, phishing and KYB checks:** new domains (`domainAgeDays < 90`) and missing DMARC are classic risk signals for vendors and sign-ups.
- **Lead enrichment (sales teams):** add domain age, e-mail provider and registrar to CRM accounts.
- **Brand protection & security audits:** who registered look-alike domains, where they are hosted, whether SPF/DMARC/DNSSEC are set.
- **Developers and AI agents:** call it from code or via MCP inside a workflow.

#### 📋 Output fields

| Field | Description | Example |
|---|---|---|
| `input` | Your line | `https://www.bbc.co.uk/news` |
| `domain` / `domainUnicode` / `tld` | Registrable domain, Unicode form, TLD | `bbc.co.uk` |
| `registered` | `true`, `false` or `null` (failed) | `true` |
| `availability` | `registered`, `possibly_available`, `unknown` | `registered` |
| `lookupSource` | `rdap` if the registry answered | `rdap` |
| `registrar` / `registrarIanaId` | Registrar and IANA ID | `MarkMonitor Inc.` / `292` |
| `registrarUrl` | Registrar website | `http://www.markmonitor.com` |
| `registrarAbuseEmail` / `registrarAbusePhone` | Abuse contact (role addresses only) | `abusecomplaints@markmonitor.com` |
| `registrantOrganization` / `registrantCountry` | Only for a legal entity | `GitHub, Inc.` / `US` |
| `createdDate` / `updatedDate` / `expiresDate` | UTC dates | `1997-09-15T04:00:00Z` |
| `domainAgeDays` | Days since registration | `10611` |
| `daysUntilExpiry` | Days left (negative if expired) | `710` |
| `status` | EPP status codes | `["clientTransferProhibited"]` |
| `nameservers` / `dnssec` | Registry nameservers, delegation signed | `["ns1.google.com"]` / `false` |
| `registryDomainId` | Registry handle | `2138514_DOMAIN_COM-VRSN` |
| `dnsResolved` | DNS answered | `true` |
| `aRecords` / `aaaaRecords` | IPv4 / IPv6 | `["185.199.108.153"]` |
| `mxRecords` / `nsRecords` | MX (with priority), NS | `["10 smtp.google.com"]` |
| `txtRecords` | TXT (e-mails masked) | `["v=spf1 a -all"]` |
| `hasSpf` / `hasDmarc` / `dmarcPolicy` | SPF, DMARC, policy | `true` / `true` / `reject` |
| `emailProvider` | From MX (Google Workspace, Microsoft 365, Self-hosted, Other...) | `Microsoft 365` |
| `registryServer` / `registryTermsUrl` | Registry that answered, its terms | `https://rdap.verisign.com/com/v1/` |
| `error` / `errorType` | Why a lookup failed | `unsupported_tld` |
| `lookedUpAt` | Lookup time (UTC) | `2026-10-05T02:16:10Z` |

The DNS fields only appear when **Include DNS records** is on.

**Use cases:** Analyze SEO & marketing (analyze domain authority & metrics, extract website metadata & tech stacks) · Generate leads (lead enrichment & validation) · Research markets & competitors (profile companies & due diligence).

### 🚀 How to use

1. Open the Actor's Store page and click **Try for free**.
2. Paste your **domains**, URLs or e-mail addresses, one per line (a whole CSV column works).
3. Keep **Include DNS records** on, or turn it off for a registry-only lookup.
4. Click **Start**. The prefilled 8 domains finish in about 2-5 seconds.
5. Download CSV, Excel or JSON, or fetch results via API, Make, Zapier or n8n.

#### 🔧 Input guide

**Domains** (`domains`, required). One per line; commas and semicolons also split entries. Each is reduced to the registrable domain (Public Suffix List); duplicates are skipped, so `news.bbc.co.uk` and `www.bbc.co.uk` count once as `bbc.co.uk`.

- ✅ Good: `example.com`, `https://shop.example.co.uk/cart`, `info@example.de`, `münchen.de`.
- ❌ Bad: `192.168.1.1` (IP address), `gov.uk` (public suffix), `localhost` (no TLD), `example.notatld` (unknown TLD).
- Invalid lines are skipped and listed in `RUN_SUMMARY` → `invalidInputs`. If no line is valid, the run fails with a clear message.

**Include DNS records** (`includeDns`, default `true`). A, AAAA, MX, NS, TXT, SPF, DMARC and e-mail provider via DNS-over-HTTPS, free of extra charge. Turn it off if you only need dates and registrar.

**Max domains** (`maxResults`, default `0` = all). Hard limit: **100,000 domains per run**; longer lists are cut with a log warning. Use 10-20 to test a big list first.

**Parallel lookups** (`maxConcurrency`, 1-50, default `10`). Each registry keeps its own limit (e.g. PIR, DENIC, Nominet: 2 parallel, 0.5 s gaps), so higher values mostly help lists that mix many TLDs.

**Request timeout** (`requestTimeoutSecs`, 5-60, default `20`). Busy answers (HTTP 408, 429, 5xx) and dropped connections are retried up to 3 times with backoff; a domain that still fails becomes a free row with `error` set.

Full example input:

```json
{
  "domains": [
    "apify.com",
    "wikipedia.org",
    "https://www.bbc.co.uk/news",
    "www.spiegel.de",
    "github.io",
    "afnic.fr",
    "sidn.nl",
    "cbc.ca"
  ],
  "includeDns": true,
  "maxResults": 0,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20
}
```

### 📦 Output

One row per domain. Real row from a run on 2026-10-05 (arrays shortened):

```json
{
  "input": "google.com",
  "domain": "google.com",
  "domainUnicode": "google.com",
  "tld": "com",
  "registered": true,
  "availability": "registered",
  "lookupSource": "rdap",
  "registrar": "MarkMonitor Inc.",
  "registrarIanaId": "292",
  "registrarUrl": "http://www.markmonitor.com",
  "registrarAbuseEmail": "abusecomplaints@markmonitor.com",
  "registrarAbusePhone": "+1.2086851750",
  "registrantOrganization": null,
  "registrantCountry": null,
  "createdDate": "1997-09-15T04:00:00Z",
  "updatedDate": "2019-09-09T15:39:04Z",
  "expiresDate": "2028-09-14T04:00:00Z",
  "domainAgeDays": 10611,
  "daysUntilExpiry": 710,
  "status": ["clientDeleteProhibited", "clientTransferProhibited", "serverUpdateProhibited"],
  "nameservers": ["ns1.google.com", "ns2.google.com", "ns3.google.com", "ns4.google.com"],
  "dnssec": false,
  "registryDomainId": "2138514_DOMAIN_COM-VRSN",
  "dnsResolved": true,
  "aRecords": ["192.178.194.100", "192.178.194.101"],
  "aaaaRecords": ["2a00:1450:4025:1807::64"],
  "mxRecords": ["10 smtp.google.com"],
  "nsRecords": ["ns1.google.com", "ns2.google.com", "ns3.google.com", "ns4.google.com"],
  "txtRecords": ["v=spf1 include:_spf.google.com ~all", "MS=E4A68B9AB2BB9670BCE15412F62916164C0B20BB"],
  "hasSpf": true,
  "hasDmarc": true,
  "dmarcPolicy": "reject",
  "emailProvider": "Google Workspace",
  "registryServer": "https://rdap.verisign.com/com/v1/",
  "registryTermsUrl": "https://www.verisign.com/domain-names/registration-data-access-protocol/terms-service/index.xhtml",
  "error": null,
  "errorType": null,
  "lookedUpAt": "2026-10-05T02:16:10Z"
}
```

- `availability`: `possibly_available` = registry "not found" and no DNS; `unknown` = lookup failed, or "not found" but the name resolves. A hint, not a purchase guarantee (reserved and premium names exist).
- Unsupported TLDs give `registered: null`, `errorType: "unsupported_tld"` and a reason (`.it is not supported: the registry offers no public RDAP service (WHOIS is not used)`), plus DNS data.

**Dataset views** (Output tab): **Registration overview** (registrar, dates, age, nameservers), **Expiry & status** (expiry, days left, EPP status, DNSSEC, availability), **DNS & e-mail** (A, MX, provider, SPF, DMARC, NS) and **Lookup source & errors** (input, registry server, error, error type).

**Key-value store:** each run writes a **RUN_SUMMARY** record with counts (`domainsLookedUp`, `domainsNotRegistered`, `domainsFailed`...), `errors` by type, results per TLD (`byTld`), `invalidInputs`, `duplicatesSkipped`, `chargeLimitReached`, `domainsNotProcessed`, the RDAP bootstrap version, `requests`, `robotsBlockedHosts` and `durationSecs`.

**Export:** JSON, CSV, Excel, XML, RSS or HTML table from the Output tab, or via the API (e.g. `/v2/datasets/{id}/items?format=csv&view=expiry`).

### 🌐 Supported TLDs

| Status | TLDs |
|---|---|
| Supported (registry RDAP) | Generic TLDs whose registry allows automated RDAP access (.com, .net, .org, .info, .biz, .io, .ai, .app, .dev, .me, .tv, .cc...) and 90+ country TLDs including .uk, .de, .fr, .nl, .ch, .li, .ca, .au, .pl, .in, .us, .cz, .fi, .no, .si, .tw, .kr |
| **Not supported** (free rows that say why) | TLDs whose registry's robots.txt disallows automated access to its RDAP server: **.co**, **.xyz** and other CentralNic TLDs, GMO Registry TLDs, **.br**, **.so**. Country TLDs with no RDAP service (~150), e.g. **.it, .eu, .be, .es, .at, .se, .dk, .jp, .ru, .cn, .pt, .ie, .nz, .hu, .mx, .hk** |

The run summary (`RUN_SUMMARY` → `robotsBlockedHosts`) lists the registry servers that opted out during your run.

### 💵 Pricing: $1.50 per 1,000 domains

You pay **once per domain for which registration data was returned** (event `domain`), DNS included. Platform compute is included; the only other charge is Apify's tiny $0.00005 per-run start fee. **Not registered, unsupported, failed and rate-limited domains are free.**

| Typical run | Domains charged | Cost |
|---|---|---|
| Client's sites | 100 | $0.15 |
| Agency portfolio | 1,000 | $1.50 |
| CRM batch | 10,000 | $15.00 |
| Maximum run | 100,000 | $150.00 |

(Plus the start fee.) In our 223-domain test, only the 147 domains with data were charged ($0.22).

Cap spending with **Max charge per run**: the run stops cleanly at your limit (`RUN_SUMMARY` → `chargeLimitReached`).

### 🔌 Use it via API

Get your token from **Apify Console → Settings → API & Integrations** and replace `YOUR_API_TOKEN`.

**JavaScript** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('kadi_bence/domain-whois-lookup').call({
  domains: ['apify.com', 'https://www.bbc.co.uk/news', 'info@example.de'],
  includeDns: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((d) => console.log(d.domain, d.expiresDate, d.daysUntilExpiry));
```

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("kadi_bence/domain-whois-lookup").call(run_input={
    "domains": ["apify.com", "wikipedia.org", "github.io"],
    "includeDns": False,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["domain"], item["registrar"], item["domainAgeDays"])
```

**cURL** (runs the Actor and returns the rows in one call):

```bash
curl -X POST "https://api.apify.com/v2/acts/kadi_bence~domain-whois-lookup/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["apify.com", "sidn.nl"], "includeDns": true}'
```

**Apify CLI**:

```bash
apify call kadi_bence/domain-whois-lookup --input '{"domains": ["apify.com", "cbc.ca"]}'
apify call kadi_bence/domain-whois-lookup -f input.json
```

**MCP for AI agents.** Add the Actor as a tool in Claude, Cursor, VS Code or any other MCP client:

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com/?actors=kadi_bence/domain-whois-lookup"}}}
```

### 🔄 Integrations & scheduling

- **Schedules:** run a saved task on a cron expression.
- **Webhooks:** POST to your URL when a run succeeds (`ACTOR.RUN.SUCCEEDED`).
- **Zapier, Make, n8n:** start runs and read dataset items.
- **Google Sheets, Slack, e-mail:** via Apify integrations or Zapier/Make.

**Recipe 1: monthly expiry monitoring of a domain portfolio.** Save a task with your portfolio in `domains` and `includeDns: false`, and schedule it monthly (cron `0 6 1 * *`). On run success, a Make/Zapier scenario reads the **Expiry & status** view, keeps rows with `daysUntilExpiry < 60` and posts them to Slack or e-mail. A 500-domain portfolio costs about $0.75 per month.

**Recipe 2: sign-up risk check.** Call the run-sync endpoint with the new user's e-mail address; flag accounts with `domainAgeDays < 90` or `hasDmarc: false`.

**Recipe 3: CRM enrichment.** Run company websites weekly and write `emailProvider`, `domainAgeDays` and `registrar` back via Make or n8n.

### 🧰 Related tools by the same developer

Website due diligence:

- [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector): CMS, ecommerce, analytics and frameworks from 7,600+ fingerprints; $1.50 / 1,000 websites.
- [SEO Site Audit Crawler](https://apify.com/kadi_bence/seo-site-audit): broken links, redirects, titles/meta, canonical and hreflang on every page; $1.50 / 1,000 pages.
- [Website Screenshot & PDF API](https://apify.com/kadi_bence/website-screenshot): full-page/mobile PNG, JPEG, WebP and PDF captures; $2.50 / 1,000 screenshots.

Content pipelines:

- [Document to Markdown](https://apify.com/kadi_bence/document-to-markdown): PDF/Word/PowerPoint/Excel/OCR to Markdown and RAG chunks; $2 / 1,000 documents.
- [Bulk Image Downloader](https://apify.com/kadi_bence/bulk-image-downloader): all images/files from pages into a ZIP; $0.80 / 1,000 files.

### ❓ FAQ

**How does it work?**
It finds each domain's registry in IANA's RDAP bootstrap (downloaded every run) or its verified extra list, checks robots.txt, sends one RDAP request and flattens the answer. DNS runs in parallel.

**Why is the registrant name or e-mail missing or "REDACTED"? (GDPR)**
Since GDPR, most registries redact personal registrant data. On top of that, this Actor **never outputs personal data**, even when a registry publishes it: no names, e-mails, phones or addresses of any contact, and no raw WHOIS/RDAP text. `registrantOrganization` is filled only for a legal entity (Inc, LLC, GmbH, S.p.A., Sp. z o.o., Ltd, Foundation, University...), never for a redaction placeholder or privacy/proxy service; in our test that was 13% of registered domains. Abuse e-mails are kept only when they are role addresses (abuse@, compliance@...), and e-mail addresses in TXT records become `[e-mail removed]`.

**Why are some other fields empty?**
Some registries never publish them: **.de** has no dates or registrar, **.ch/.li** and **.au** no creation or expiry dates, **.nl** no expiry date. In a 223-domain test across 37 TLDs, every registered domain in a supported TLD came back: 100% with nameservers, 88% registrar, 83% creation date, 78% expiry date.

**Why is my TLD not supported?**
If a registry's RDAP robots.txt disallows bots (CentralNic for .co/.xyz, GMO Registry, registro.br) or a country TLD has no RDAP at all (.it, .eu, .be, .es, .dk, .jp...), the row says so and is free. We don't fall back to port-43 WHOIS: most WHOIS terms forbid automated queries and none explicitly allow them. New RDAP registries are picked up automatically from IANA's list.

**Is it legal?**
RDAP is the official, ICANN-mandated protocol for public registration data. The Actor queries only domains you supply, respects each registry's limits, robots.txt and terms, and outputs no personal data. Registry terms forbid using the data for spam, mass marketing or rebuilding their database (DENIC and nic.ch also exclude advertising). You are responsible for your use of the results; this is not legal advice.

**How fast is it?**
The prefilled 8 domains take 2-5 s. In our test, 223 domains across 37 TLDs took 23-33 s with 20 in parallel. .com/.net (Verisign) is the fastest.

**Do I need proxies?**
No, and it deliberately doesn't rotate IPs. If a registry still answers 429, the row says `rate_limited` (free); re-run those domains later. Big single-registry lists (e.g. 10,000 .org) hit this most.

**Where does the DNS data come from?**
Cloudflare's public DNS-over-HTTPS (1.1.1.1), with Google Public DNS as fallback.

**Can I use it from Python, Zapier or an AI agent?**
Yes: see [Use it via API](#-use-it-via-api) and [Integrations & scheduling](#-integrations--scheduling).

**What does a big job cost?**
100,000 domains (the per-run maximum) cost at most $150 plus the start fee; free rows lower that. Use **Max charge per run** as a hard cap.

**What if a lookup fails?**
The row stays in the dataset, free, with `error` and `errorType` (`unsupported_tld`, `rate_limited`, `timeout`, `dns`, `refused`, `tls`, `network`, `http`, `invalid_response`, `internal`). If something looks wrong or a TLD is missing, open an issue on the **Issues** tab with the domain. Fixes usually land within 24-48 hours. Recent changes are in the changelog below.

### 📝 Changelog

- **2026-10-05:** Store page rewritten (README and input descriptions); no change to the code or output.
- **1.0 (2026-10-05):** First release. RDAP via the IANA bootstrap plus verified non-bootstrap registry servers, RDAP only (no port-43 WHOIS), robots.txt opt-outs honoured with no workaround, DNS/SPF/DMARC/e-mail provider, GDPR guard, per-registry rate limits, failed, unsupported and not-registered domains not charged.

### 🤝 Need a custom version?

I build custom scrapers, scheduled data feeds and integrations (CSV, Excel, Google Sheets, API, MCP for AI agents). Tell me the sites and fields you need:

- Email: bence.kadi@gmail.com
- Apify profile: https://apify.com/kadi_bence

### Credits

Registry data: each TLD's registry via RDAP (RFC 9082/9083) and the IANA RDAP bootstrap (RFC 9224). Public Suffix List © Mozilla Foundation and contributors, MPL-2.0. DNS: Cloudflare 1.1.1.1 and Google Public DNS. This Actor is not affiliated with ICANN, IANA or any registry.

### Related Actors

More low-cost Actors by the same developer, built on official APIs and public data:

- [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector) — CMS, ecommerce, analytics and frameworks of any website
- [SEO Site Audit](https://apify.com/kadi_bence/seo-site-audit) — 0-100 SEO score per page, broken links and fix hints
- [New Business Filings USA](https://apify.com/kadi_bence/us-new-business-filings) — newly registered LLCs and companies
- [Website Screenshot & PDF API](https://apify.com/kadi_bence/website-screenshot) — full-page screenshots and PDFs of any URL
- [PageSpeed Insights Bulk Checker](https://apify.com/kadi_bence/pagespeed-checker) — Core Web Vitals and Lighthouse scores in bulk
- [SEC Form D Scraper](https://apify.com/kadi_bence/sec-form-d-funding) — new startup funding rounds from SEC EDGAR
- [AI Visibility Tracker](https://apify.com/kadi_bence/ai-visibility-tracker) — how ChatGPT, Perplexity, Gemini and Claude mention your brand

All my Actors: [apify.com/kadi_bence](https://apify.com/kadi_bence)

# Actor input Schema

## `domains` (type: `array`):

One per line (commas and semicolons also split). Domains, URLs and e-mail addresses are reduced to the registrable domain, e.g. https://news.example.co.uk/page -> example.co.uk, info@example.de -> example.de. Duplicates are skipped; IP addresses and public suffixes (gov.uk) are rejected. You can paste thousands of lines from a CSV column.

## `includeDns` (type: `boolean`):

Add A, AAAA, MX, NS and TXT records, SPF and DMARC checks and the e-mail provider (Google Workspace, Microsoft 365...) via DNS-over-HTTPS. Included in the price. Turn off if you only need dates and registrar, e.g. for an expiry check.

## `maxResults` (type: `integer`):

Stop after this many domains (0 = all, up to 100,000 per run). Tip: use 10-20 to test a big list first.

## `maxConcurrency` (type: `integer`):

How many domains are looked up at the same time (1-50). Each registry still gets its own polite rate limit, so a higher value mostly helps lists that mix many TLDs; a list of only .org domains won't get much faster.

## `requestTimeoutSecs` (type: `integer`):

Give up on a slow registry server after this many seconds (5-60). Busy servers and dropped connections are retried up to 3 times; domains that still fail are listed with an error and not charged.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "wikipedia.org",
    "https://www.bbc.co.uk/news",
    "www.spiegel.de",
    "github.io",
    "afnic.fr",
    "sidn.nl",
    "cbc.ca"
  ],
  "includeDns": true,
  "maxResults": 0,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Registrar, creation and expiry dates, age and nameservers per domain.

## `expiry` (type: `string`):

Expiry date, days to expiry, EPP status codes and DNSSEC.

## `dns` (type: `string`):

A/MX/NS records, e-mail provider, SPF and DMARC.

## `full` (type: `string`):

Every field for every domain.

## `summary` (type: `string`):

Counts, errors, results per TLD and registry data versions.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "apify.com",
        "wikipedia.org",
        "https://www.bbc.co.uk/news",
        "www.spiegel.de",
        "github.io",
        "afnic.fr",
        "sidn.nl",
        "cbc.ca"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kadi_bence/domain-whois-lookup").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "apify.com",
        "wikipedia.org",
        "https://www.bbc.co.uk/news",
        "www.spiegel.de",
        "github.io",
        "afnic.fr",
        "sidn.nl",
        "cbc.ca",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("kadi_bence/domain-whois-lookup").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "apify.com",
    "wikipedia.org",
    "https://www.bbc.co.uk/news",
    "www.spiegel.de",
    "github.io",
    "afnic.fr",
    "sidn.nl",
    "cbc.ca"
  ]
}' |
apify call kadi_bence/domain-whois-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kadi_bence/domain-whois-lookup"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3LKoLuuc1Uixmsqve/builds/GBpuyEImVgIgItalq/openapi.json
