# Domain WHOIS, DNS & Email Provider Lookup - Bulk RDAP & SSL (`wakachobi/domain-intelligence`) Actor

Enrich any list of domains, URLs or emails: registrar, creation and expiry dates (RDAP/WHOIS), DNS records, email provider (Google Workspace, Microsoft 365...), SPF/DMARC, SSL certificate, hosting/CDN and site title.

- **URL**: https://apify.com/wakachobi/domain-intelligence.md
- **Developed by:** [Cobi Hilliard](https://apify.com/wakachobi) (community)
- **Categories:** Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 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

## Domain Intelligence: bulk WHOIS/RDAP, DNS, email provider, SPF/DMARC and SSL lookup

Paste a list of **domains, website URLs or email addresses** and get one clean record per domain:

- **who it's registered with, when it was created and when it expires** (RDAP, the official successor to WHOIS)
- **DNS records**
- **which email provider the company uses** (Google Workspace, Microsoft 365, Zoho…) and its SPF and DMARC setup
- **the SaaS tools** revealed by DNS verification records
- **the SSL certificate** and its expiry
- **the website's hosting/CDN**, title and description

No API keys, no login, and nothing to install. Built for lead enrichment, Clay/n8n/Make workflows, security audits and domain portfolio checks.

### What data you get

- **Registration:** registrar and IANA ID, creation, expiry and last-changed dates, **domain age in days**, EPP status codes, nameservers, DNSSEC, and whether the domain is registered at all
- **DNS:** A, AAAA, CNAME, NS, MX and TXT records
- **Email setup:**
  - **email provider** detected from MX, with 30+ providers recognised (Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, Mimecast, Proofpoint, Cisco, MessageLabs…)
  - whether the domain accepts email
  - SPF record and its `all` qualifier
  - DMARC record and policy (`none`, `quarantine` or `reject`)
- **Tools in use:** SaaS services that verified the domain, such as Google, Microsoft 365, Atlassian, HubSpot, Stripe, Slack, Zoom, OpenAI and DocuSign
- **SSL/TLS:** valid or not (and why not), issuer, valid-from and valid-to, **days until expiry**, alternative names, TLS version
- **Website:**
  - HTTP status, final URL after redirects, response time
  - page title, meta description, language
  - `Server` and `X-Powered-By` headers
  - **CDN/hosting** (Cloudflare, Vercel, Netlify, Fastly, CloudFront, Shopify, Wix…)
  - HSTS

#### Sample result (trimmed)

```json
{
  "input": "https://www.stripe.com/pricing",
  "domain": "stripe.com",
  "registrar": "SafeNames Ltd.",
  "registeredAt": "1995-09-12T04:00:00Z",
  "expiresAt": "2027-09-11T04:00:00Z",
  "domainAgeDays": 11364,
  "nameservers": ["ns-1087.awsdns-07.org", "ns-423.awsdns-52.com"],
  "dnssec": false,
  "mxRecords": [{ "host": "aspmx.l.google.com", "priority": 1 }],
  "emailProvider": "Google Workspace",
  "spfAllQualifier": "~",
  "dmarcPolicy": "reject",
  "verifiedServices": ["Microsoft 365", "Anthropic", "Apple", "Atlassian", "Canva", "Cursor", "DocuSign", "Meta", "Google", "OpenAI", "Stripe"],
  "tlsValid": true,
  "tlsIssuer": "DigiCert, Inc.",
  "tlsDaysUntilExpiry": 48,
  "websiteStatus": 200,
  "websiteTitle": "Stripe | Financial Infrastructure to Grow Your Revenue",
  "edgeProvider": null,
  "errors": [],
  "checkedAt": "2026-10-23T01:48:47.923Z"
}
```

### How to use

| Field | What it does | Default |
|---|---|---|
| `domains` | Domains, URLs or emails, one per line. Each is reduced to its registrable domain (`blog.example.co.uk` becomes `example.co.uk`), and duplicates are removed | required |
| `checkRegistration` | RDAP registration data | on |
| `checkDns` | DNS records | on |
| `checkEmail` | Email provider, SPF, DMARC, verified SaaS tools | on |
| `checkTls` | SSL certificate | on |
| `checkWebsite` | One homepage request | on |
| `maxItems` | Stop after this many domains | 50 |
| `concurrency` | Domains inspected in parallel (1–20) | 8 |

**Examples**

- **Enrich a lead list:** paste 1,000 work emails. You get each company's email provider, domain age, website title and tech hints.
- **Security/compliance audit:** check which of your domains lack DMARC `reject`, have weak SPF, or have certificates expiring within 30 days.
- **Domain portfolio:** check expiry dates and registrars across all your domains in one run.

Turn off the checks you don't need to make runs faster. Registration only, for example, is a quick WHOIS-style lookup.

### Pricing

**$3 per 1,000 domains**, i.e. $0.003 per domain inspected, whichever checks you enable. 1,000 leads enriched costs $3.

### FAQ

**Is this legal?**
Yes. It reads public data through channels designed for automated access:

- registry RDAP services, the official IETF protocol that replaces WHOIS
- public DNS resolvers
- a standard TLS handshake
- one request to each site's homepage, just like a browser

No logins, no scraping of WHOIS websites, and no personal data. Registrant contact details are not collected.

**Why is registration data empty for some domains?**
Some country registries haven't published an RDAP service yet. Currently that includes .io, .co, .me, .de, .eu, .us, .ch, .es, .it and .jp. For those domains you still get DNS, email, SSL and website data, and `rdapNote` explains why registration is missing. .com, .net, .org, .ai, .app, .dev, .uk, .fr, .nl, .ca, .au, .in and over 1,000 other TLDs are covered.

**What does "Other / self-hosted" mean for email provider?**
The domain receives mail on servers that aren't one of the recognised providers, often its own mail servers.

**Why does `websiteStatus` show 403 for some sites?**
Some sites put a bot challenge (e.g. "Just a moment…") in front of every automated request. We report that honestly instead of trying to get around it.

**Integrations / API**
Run it from Clay, n8n, Make or Zapier, or call it through the Apify API and get results as JSON, CSV or Excel. Each domain's output is one flat record, so it maps straight onto spreadsheet columns.

### Integrations / API

#### 1. Enrich a lead list row by row (Clay)

Add company tech and email signals to every row that has a website or work email.

1. **Add enrichment → Apify → Run Apify Actor**, and choose *Domain Intelligence*.
2. Input. The column token has no quotes around it, and a work-email column works too:
   ```json
   { "domains": [{{Website}}], "maxItems": 1, "checkTls": false }
   ```
3. Map the fields you want into columns:
   - `emailProvider`: Google Workspace, Microsoft 365, etc.
   - `domainAgeDays`
   - `registrar`
   - `verifiedServices`: e.g. HubSpot, Atlassian, Stripe, OpenAI
   - `edgeProvider`: Cloudflare, Vercel, Shopify…
   - `websiteTitle`

**Tips:**

- Turn off the checks you don't use to make each row faster.
- For example, `"checkRegistration": false` gives email and tech signals only.
- Each row costs $0.003.

#### 2. Enrich a Google Sheet in bulk (n8n)

1. **Google Sheets → Get Rows:** read the column with domains, URLs or emails.
2. **Code node:** collect them into one input, `return [{ json: { domains: $input.all().map(i => i.json.Website), maxItems: 1000 } }]`.
3. **HTTP Request:** `POST https://api.apify.com/v2/acts/wakachobi~domain-intelligence/run-sync-get-dataset-items`, header `Authorization: Bearer <APIFY_TOKEN>`, body `{{ $json }}`.
   - Keep each call to about 300 domains. Lookups to any single registry (e.g. Verisign for all .com) are spaced 300 ms apart to respect its limits, so 300 .com domains take about 90 s or more, inside the 300 s sync limit.
   - For bigger lists, use the Apify node's run-and-wait (no 300 s limit), or loop over 300-row batches with n8n's *Loop Over Items*.
4. **Google Sheets → Update Row:** match on `domain`, and write `emailProvider`, `dmarcPolicy`, `domainAgeDays` and so on back into the sheet.

#### 3. Weekly domain-health check for your own domains (n8n or Apify schedule → email)

Catch expiring certificates, expiring domains and weak email security before they bite.

1. **Schedule:** weekly. Run *Domain Intelligence* on your domains: `{ "domains": ["example.com", "example.co.uk", "example-app.io"], "checkWebsite": false }`.
2. **Filter:** keep a domain if any of these is true:
   - `tlsDaysUntilExpiry` < 21
   - `expiresAt` is within 30 days
   - `dmarcPolicy` isn't `reject`
   - `spfAllQualifier` is `+` or missing
3. **Email:** send the filtered list to the ops or security inbox.

#### 4. Plain API call

```bash
curl -X POST "https://api.apify.com/v2/acts/wakachobi~domain-intelligence/run-sync-get-dataset-items?format=csv" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{ "domains": ["stripe.com", "notion.so", "jane@openai.com"] }' -o domains.csv
```

# Actor input Schema

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

One per line. Domains (stripe.com), full URLs (https://www.stripe.com/pricing) or email addresses (jane@stripe.com) all work; each is reduced to its registrable domain and duplicates are removed.

## `checkRegistration` (type: `boolean`):

Registrar, creation, expiry and update dates, domain age, status and DNSSEC, from the registry's official RDAP service.

## `checkDns` (type: `boolean`):

A, AAAA, CNAME, NS, MX and TXT records via public resolvers (1.1.1.1, 8.8.8.8).

## `checkEmail` (type: `boolean`):

Email provider detected from MX (Google Workspace, Microsoft 365, Zoho...), SPF and DMARC policy, and SaaS tools revealed by DNS verification records.

## `checkTls` (type: `boolean`):

Issuer, validity dates, days until expiry, alternative names and TLS version.

## `checkWebsite` (type: `boolean`):

One homepage request: HTTP status, final URL after redirects, title, meta description, language, server and CDN/hosting provider.

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

Stop after this many domains.

## `concurrency` (type: `integer`):

How many domains to inspect at once. Registries rate-limit, so values above ~10 rarely make runs faster.

## Actor input object example

```json
{
  "domains": [
    "stripe.com",
    "https://www.notion.so/product",
    "openai.com"
  ],
  "checkRegistration": true,
  "checkDns": true,
  "checkEmail": true,
  "checkTls": true,
  "checkWebsite": true,
  "maxItems": 50,
  "concurrency": 8
}
```

# Actor output Schema

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

No description

# 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",
        "https://www.notion.so/product",
        "openai.com"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("wakachobi/domain-intelligence").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",
        "https://www.notion.so/product",
        "openai.com",
    ],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("wakachobi/domain-intelligence").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",
    "https://www.notion.so/product",
    "openai.com"
  ],
  "maxItems": 50
}' |
apify call wakachobi/domain-intelligence --silent --output-dataset

```

## MCP server setup

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

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/cws0q5JO9OImQoLP4/builds/WgSXk00mlw4THovpD/openapi.json
