# Domain WHOIS & RDAP Lookup (`devilscrapes/domain-whois-rdap-scraper`) Actor

Bulk domain WHOIS lookup over the IETF RDAP network — no API key required. Feed a list of domains and get registrar, registration/expiration dates, name servers, and status codes as structured rows. We resolve each domain to the correct registry via the IANA RDAP bootstrap file, paced and retried.

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

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Domain WHOIS & RDAP Lookup

**💰 $5.05 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Bulk domain WHOIS lookup over the IETF RDAP network — no API key required. Feed a list of domains and get registrar, registration/expiration dates, name servers, and status codes as structured rows. We resolve each domain to the correct registry via the IANA RDAP bootstrap file, paced and retried.

</div>

***

### 🎯 What this scrapes

RDAP (Registration Data Access Protocol, RFC 7482+) is the structured, machine-readable successor to legacy WHOIS text — and every gTLD registry (plus a growing set of ccTLDs) is required to expose it publicly, with no key or login. The catch: there's no single RDAP endpoint. Every TLD points at a different registry server, and you have to resolve that mapping yourself via IANA's bootstrap file before you can ask a single question. This Actor does that resolution for you, walks your domain list at a pace you control, and writes one structured row per domain — registrar, registration and expiration dates, name servers, DNSSEC status, and domain status codes — ready for a portfolio monitor, a lead list, or a brand-protection sweep.

### 🔥 What we handle for you

- 🌐 **Correct-registry routing** — resolves the right RDAP server per TLD via the IANA bootstrap file, so one input list can span domains across dozens of registries.
- 🔁 **Polite pacing + retries** — configurable delay between requests, exponential backoff on `429`/`503`, `Retry-After` honoured.
- 🌐 **Optional proxy rotation** via Apify Proxy for higher-volume runs against registries that throttle by source IP.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated registrar, dates, name servers, and status codes, ready for CSV/JSON export.
- 💰 **Pay-Per-Event pricing** — you only pay for domains that resolve. No data, no charge beyond the warm-up fee.

### 💡 Use cases

- **Domain portfolio monitoring** — schedule daily runs across your portfolio and catch expiration dates before they lapse.
- **Prospecting / lead gen** — bulk-check registrar and creation date to spot newly registered domains in a niche.
- **Brand protection** — batch-check lookalike domain registrations for enforcement leads.
- **Due diligence** — verify domain ownership, age, and registration history for a target company's web assets.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Fill in the input form — most fields have sensible defaults.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `domains` | `array` | **yes** | \['stripe.com'] | Domain names to look up via IETF RDAP, e.g. <code>example.com</code>. One RDAP query per domain, each routed to the… |
| `maxDomains` | `integer` | no | 100 | Safety cap on how many domains from the list are processed in one run. |
| `requestDelaySeconds` | `number` | no | 1.0 | Pause between RDAP requests so we stay polite to registry servers. Raise this if a registry starts rate-limiting. |
| `proxyConfiguration` | `object` | no | {'useApifyProxy': True} | Apify Proxy configuration. RDAP is a public protocol, but some registries throttle by source IP at higher volumes —… |

#### Example input

```json
{
  "domains": [
    "stripe.com",
    "example.com"
  ],
  "maxDomains": 5,
  "requestDelaySeconds": 1.0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one dataset item.

| Field | Type | Notes |
|---|---|---|
| `domain` | `string` | The domain that was looked up, normalized to lowercase. |
| `status` | `string` | `registered` on an RDAP 200, `available` on an RDAP 404 (a legitimate answer, not a failure), `error` only when the lookup could not be completed after retries. |
| `registrar` | `string` | Sponsoring registrar name, if published by the registry. |
| `created_date` | `string` | Domain registration date (ISO-8601), when published. |
| `expiration_date` | `string` | Domain expiration date (ISO-8601), when published. |
| `last_changed_date` | `string` | Last registry change date (ISO-8601), when published. |
| `nameservers` | `array` | Authoritative name servers on record for the domain. |
| `epp_status_codes` | `array` | RDAP/EPP domain status codes, e.g. `client transfer prohibited`. |
| `dnssec_enabled` | `boolean` | Whether DNSSEC is signed for this domain, per the RDAP `secureDNS` block. |
| `registrant_country` | `string` | Registrant country. `null` when GDPR-redacted or absent — the common case since 2018. |
| `registrant_org` | `string` | Registrant organization. `null` when GDPR-redacted or absent — the common case since 2018. |
| `rdap_server` | `string` | Resolved authoritative RDAP host after the rdap.org bootstrap redirect. |
| `scraped_at` | `string` | When this row was recorded (ISO-8601 UTC). |

#### Example output

```json
{
  "domain": "stripe.com",
  "status": "registered",
  "registrar": "SafeNames Ltd.",
  "created_date": "1995-09-12T04:00:00Z",
  "expiration_date": "2027-09-11T04:00:00Z",
  "last_changed_date": "2025-10-01T01:39:51Z",
  "nameservers": [
    "NS-1087.AWSDNS-07.ORG",
    "NS-1882.AWSDNS-43.CO.UK",
    "NS-423.AWSDNS-52.COM",
    "NS-705.AWSDNS-24.NET"
  ],
  "epp_status_codes": [
    "client delete prohibited",
    "client transfer prohibited",
    "client update prohibited",
    "server delete prohibited",
    "server transfer prohibited",
    "server update prohibited"
  ],
  "dnssec_enabled": false,
  "registrant_country": null,
  "registrant_org": null,
  "rdap_server": "rdap.verisign.com",
  "scraped_at": "2026-09-01T09:31:19+00:00"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.05 | One-off warm-up charge per run |
| `domain-scraped` | $0.005 | Per domain RDAP row written to the dataset |

Example: 1 000 results at the rates above ≈ **$5.05**. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

- RDAP coverage depends on the registry — most gTLDs (.com, .net, .org, etc.) support it; some ccTLDs still only offer legacy WHOIS, which this Actor does not fall back to.
- Registrant contact fields (name, email, phone) are frequently redacted by the registrar under GDPR/privacy-proxy policy — this is a registry-side restriction, not a limitation of the lookup.
- We query only the public RDAP surface each registry exposes — no bulk-zone-file access, no historical/expired WHOIS records.

### ❓ FAQ

**Is this legal?**

Yes — RDAP is a public IETF standard (RFC 7482 and successors) that ICANN requires every gTLD registry to expose for public, unauthenticated lookups. We only query the public RDAP endpoint each registry already publishes.

**Why are registrant name/email/phone often empty?**

Most registrars redact registrant contact fields by default since GDPR (2018) and ICANN's Temporary Specification. Registrar, dates, name servers, and status codes remain public and are populated whenever the registry publishes them.

**What happens if a domain isn't registered?**

The row comes back with `status: "available"` and a successful run — a clean not-found from the registry is a real answer, not an error.

**Does every TLD support RDAP?**

Most gTLDs do; ccTLD coverage is growing but not universal. We resolve the registry via IANA's official bootstrap file, so a TLD without an RDAP server is reported clearly rather than silently skipped.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

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

Domain names to look up via IETF RDAP, e.g. <code>example.com</code>. One RDAP query per domain, each routed to the correct registry via the IANA bootstrap file.

## `maxDomains` (type: `integer`):

Safety cap on how many domains from the list are processed in one run.

## `requestDelaySeconds` (type: `number`):

Pause between RDAP requests so we stay polite to registry servers. Raise this if a registry starts rate-limiting.

## `proxyConfiguration` (type: `object`):

Apify Proxy configuration. RDAP is a public protocol, but some registries throttle by source IP at higher volumes — proxy rotation helps there.

## Actor input object example

```json
{
  "domains": [
    "stripe.com"
  ],
  "maxDomains": 100,
  "requestDelaySeconds": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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": [
        "stripe.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/domain-whois-rdap-scraper").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": ["stripe.com"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/domain-whois-rdap-scraper").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": [
    "stripe.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/domain-whois-rdap-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/ZLhc6hak4Ep6qQb2t/builds/SlyK12jeSZPxQDIkG/openapi.json
