# Domain WHOIS RDAP Lookup - DNS, MX & Expiry (`datagrit/domain-whois-rdap-lookup`) Actor

Bulk domain lookup: official RDAP (WHOIS) registration, expiry and availability plus DNS, mail provider, SPF/DMARC and hosting ASN, with expiry and registrar filters.

- **URL**: https://apify.com/datagrit/domain-whois-rdap-lookup.md
- **Developed by:** [datagrit](https://apify.com/datagrit) (community)
- **Categories:** SEO tools, Developer tools, Lead generation
- **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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What does Domain WHOIS RDAP Lookup do?

Domain WHOIS RDAP Lookup takes a list of domains and returns one flat row per domain: official registration data from the registry's RDAP server (the structured successor of WHOIS) plus the domain's DNS, mail provider, SPF and DMARC policy, and hosting network. It is built for bulk work: SEO and domain investors checking age and expiry, sales teams enriching lead lists with mail stack data, and security teams auditing email authentication.

### Who is it for?

- **Domain investors and expiry hunters** - find domains that expire within N days, are in redemption or pending deletion, or are not registered at all.
- **SEO and link building** - domain age, registrar and hosting network for every prospect site in one CSV.
- **B2B sales and lead enrichment** - which companies run Google Workspace or Microsoft 365, and which sit behind Mimecast or Proofpoint.
- **Email security and deliverability audits** - SPF all-mechanism, DMARC policy (none, quarantine, reject) and DKIM keys on common selectors for a whole portfolio.
- **Brand protection and due diligence** - registrar, IANA id, abuse contact, transfer lock and DNSSEC for lookalike or acquired domains.

### Example output

| domain | found | registered | registrar | createdAt | expiresAt | daysToExpiry | mailProvider | dmarcPolicy | reason |
|---|---|---|---|---|---|---|---|---|---|
| wikipedia.org | true | true | MarkMonitor Inc. | 2001-01-13 | 2027-01-13 | 104 | Other | reject | |
| lemonde.fr | true | true | NAMESHIELD | 2005-08-02 | 2027-06-09 | 252 | Google Workspace | quarantine | |
| zzqx-nonexist-8841.com | true | false | | | | | | | |
| google.de | false | | | | | | | | noRdapService (free) |

```json
{
  "input": "https://www.lemonde.fr/",
  "domain": "lemonde.fr",
  "tld": "fr",
  "found": true,
  "registered": true,
  "reason": null,
  "registrar": "NAMESHIELD",
  "registrarIanaId": 1251,
  "createdAt": "2005-08-02T14:16:36.000Z",
  "updatedAt": "2026-06-12T22:48:47.579Z",
  "expiresAt": "2027-06-09T22:08:09.000Z",
  "domainAgeDays": 7729,
  "daysToExpiry": 252,
  "status": ["serverUpdateProhibited", "serverTransferProhibited", "serverDeleteProhibited", "serverRecoverProhibited"],
  "transferLocked": true,
  "deletionPending": false,
  "registrantOrganization": "SOCIETE EDITRICE DU MONDE",
  "registrantCountry": "FR",
  "dnsStatus": "ok",
  "mxRecords": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"],
  "mailProvider": "Google Workspace",
  "mailGateway": null,
  "dnsProvider": "Google Cloud DNS",
  "spfPolicy": "-all",
  "dmarcPolicy": "quarantine",
  "dkimSelectors": ["google", "k1", "s1", "s2", "mail"],
  "hostingAsn": 54113,
  "hostingAsnName": "FASTLY - Fastly, Inc., US",
  "rdapSource": "iana-bootstrap",
  "sourceUrl": "https://rdap.nic.fr/domain/lemonde.fr"
}
```

The full row has 44 columns; the dataset has Overview, Registration and Mail and DNS views.

### What data do you get?

#### Registration (RDAP)

Registrar name, IANA registrar id and abuse e-mail, creation, last change and expiry dates, domain age and days to expiry, EPP status codes with `transferLocked` and `deletionPending` flags, registry nameservers and DNSSEC. Registrant organization and country only when the registry or registrar publishes them; redacted values become null with `registrantRedacted: true`. When the registrant card is a privacy or proxy service (Domains By Proxy, Withheld for Privacy and similar), the country is null too, because the address on the card is the service's. Personal names, addresses, e-mails and phone numbers are never returned.

#### Availability

`registered: false` means the registry's RDAP server answered "not found" and the name is not delegated in DNS. When RDAP says not found but DNS still delegates the name, the row is `found: false` with reason `notFoundButDelegated` instead of a false "available"; when the delegation check itself fails, the row is `found: false` with reason `dnsUnavailable`. Both are free.

#### DNS, mail and hosting

A, AAAA, MX, NS and TXT records, mail provider (Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, Amazon SES and 25 more), security gateway (Mimecast, Proofpoint, Broadcom, Barracuda, Cisco and others, with the mailbox provider behind it taken from the SPF include), DNS provider, SPF record and its all-mechanism, DMARC record and policy, DKIM keys on 9 common selectors, and the hosting ASN, network name and country of the first IPv4 address.

### How much does it cost?

You pay per domain with a definitive answer (registered or available). Pricing depends on your Apify plan: a small fee when a run starts, then a price per domain that is lower on paid plans. The Apify free plan includes monthly credit you can use to try it. Domains that cannot be looked up (TLDs without RDAP, registry errors, rate limits), duplicates, domains dropped by your filters and the "no match" row are never charged. You can set a maximum spend on the run and the Actor stops when it is reached.

### Input

- **Domains** - one per line. URLs, `www.` hostnames, subdomains and e-mail addresses are reduced to the registered domain; duplicates are merged. An empty list runs a small free example lookup.
- **Include DNS, mail provider, SPF and DMARC** (on) and **Include hosting ASN** (on).
- **Registrant from registrar RDAP** (off) - a second request to the registrar for registries without registrant data (.com, .net, .org).
- **Filters** - Only available domains, Expiring within days, Registered on or after / before, Registrar contains. Filters are checked on the returned fields.
- **Maximum results** - stop after N returned domains.

### How it works

The RDAP server for each TLD comes from the IANA RDAP bootstrap file. Seven registries run official RDAP servers that are not in that file yet (.io, .sh, .ac, .me, .us, .ch, .li); they are used directly. If the IANA file cannot be read, lookups go through rdap.org. TLDs with no RDAP server in the IANA file or in that verified list (for example .de, .co, .it, .eu, .jp) are returned as `found: false` with reason `noRdapService`, free, and listed in the run status.

Requests are paced per server. Measured on 2026-10-01: Verisign (.com) answered 30 requests at up to 15 per second without a limit response; the Actor sends at most 10 per second and 4 in parallel to one registry. GoDaddy's registrar RDAP allows 6 requests per minute and answers 429 with Retry-After; the Actor waits as asked (up to 3 minutes). When a server reports `x-ratelimit-remaining: 0`, the Actor pauses that server until `x-ratelimit-reset`, or for 60 seconds when no reset time is sent.

### FAQ

#### Is it legal to use this data?

The Actor reads public RDAP and DNS services without logging in. RDAP is the protocol ICANN requires registries and registrars to run for public registration data. It returns only organization-level registrant data that the registry or registrar publishes. How you use the data is your decision and your responsibility, including any rules that apply to contacting organizations.

#### How fast is it?

Measured on 2026-10-01: 12 domains from 8 registries with DNS and hosting took 8 seconds including start-up. Up to 8 domains are looked up in parallel and each registry is paced separately (at most 10 requests per second), so a mixed list runs faster than a list of only .com domains. Registrant from registrar RDAP slows runs down on registrars with strict limits such as GoDaddy.

#### Why is a domain found:false?

No RDAP server is known for its TLD, the registry refused the name, the server kept failing or rate-limited the request beyond 3 minutes, or RDAP and DNS disagreed. The reason is in the `reason` column and in the run status; these rows are free.

#### How often can I run it?

As often as you like. For expiry monitoring, a daily or weekly schedule with **Expiring within days** returns only domains close to expiry.

#### Does it follow WHOIS on port 43?

No. It uses RDAP only, which returns structured JSON with the same registry data.

### Related Actors

This is the first datagrit Actor for domain data. Search the Apify Store for "datagrit" to find our other public-data Actors as the catalog grows.

# Changelog

This Actor's version history is a separate document: https://apify.com/datagrit/domain-whois-rdap-lookup/changelog.md

# Actor input Schema

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

Domain names, one per line. URLs, www. hostnames, subdomains and e-mail addresses are accepted and reduced to the registered domain (https://blog.example.co.uk/x -> example.co.uk). Duplicates are merged. Entries that are not a domain are skipped and listed in the run status; if none is valid the run fails. With an empty list the Actor runs a small free example lookup (stripe.com, wikipedia.org, bbc.co.uk, lemonde.fr, google.io, google.de) and says so in the status message.

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

Query A, AAAA, MX, NS and TXT records, the DMARC record and common DKIM selectors for every registered domain, and detect the mail provider, mail security gateway and DNS provider. Turn off for registration data only.

## `includeHosting` (type: `boolean`):

Map the first IPv4 address of the domain to its network (ASN number, network name and country) through the public Team Cymru IP-to-ASN DNS service. Needs DNS to be included.

## `registrantFromRegistrar` (type: `boolean`):

For registries that publish no registrant (for example .com, .net, .org), make a second request to the registrar's own RDAP server to read the registrant organization and country. Registrar servers are rate-limited (GoDaddy allows about 6 requests per minute), so large lists run slower; domains skipped because of a registrar limit are marked registrarRdap = rateLimited.

## `onlyAvailable` (type: `boolean`):

Return only domains with no registration at the registry (RDAP answers not found and the name is not delegated in DNS). Cannot be combined with the expiry, registration date or registrar filters.

## `expiringWithinDays` (type: `integer`):

Keep only registered domains whose registry expiry date is at most this many days away (daysToExpiry <= N), including domains already past expiry that the registry still holds. Domains whose registry publishes no expiry date (for example .ch) are dropped by this filter. 0 disables the filter.

## `registeredAfter` (type: `string`):

Keep only registered domains created on or after this date (YYYY-MM-DD, compared with createdAt in UTC). Domains without a creation date are dropped.

## `registeredBefore` (type: `string`):

Keep only registered domains created before this date (YYYY-MM-DD, the date itself excluded). Domains without a creation date are dropped.

## `registrarContains` (type: `array`):

Keep only registered domains whose registrar name contains one of these words (case-insensitive), for example GoDaddy or Namecheap.

## `maxItems` (type: `integer`):

Stop after this many returned domains. Domains not looked up because of this limit are listed in the run status.

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

Optional proxy for the RDAP requests. Leave disabled: RDAP servers are public. DNS queries never go through the proxy.

## Actor input object example

```json
{
  "domains": [
    "stripe.com",
    "wikipedia.org",
    "bbc.co.uk",
    "lemonde.fr",
    "google.io",
    "google.de"
  ],
  "includeDns": true,
  "includeHosting": true,
  "registrantFromRegistrar": false,
  "onlyAvailable": false,
  "expiringWithinDays": 0,
  "registrarContains": [],
  "maxItems": 10000,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per domain in the default dataset.

# 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",
        "wikipedia.org",
        "bbc.co.uk",
        "lemonde.fr",
        "google.io",
        "google.de"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagrit/domain-whois-rdap-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": [
        "stripe.com",
        "wikipedia.org",
        "bbc.co.uk",
        "lemonde.fr",
        "google.io",
        "google.de",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("datagrit/domain-whois-rdap-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": [
    "stripe.com",
    "wikipedia.org",
    "bbc.co.uk",
    "lemonde.fr",
    "google.io",
    "google.de"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call datagrit/domain-whois-rdap-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datagrit/domain-whois-rdap-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/mui0ngP11lBNORwdm/builds/ONptUbeZ2C2EObdV4/openapi.json
