# Bulk WHOIS & DNS Lookup: RDAP, SSL Expiry, SPF & DMARC (`steadyline/domain-intel`) Actor

Bulk domain lookup: RDAP/WHOIS registrar, creation and expiry dates, DNS records (A, AAAA, MX, NS, TXT, CAA, SOA), SSL certificate expiry and issuer, SPF/DMARC/BIMI/MTA-STS checks, mail and DNS provider detection, and a health score. $1 per 1,000 domains. By Steadyline Data.

- **URL**: https://apify.com/steadyline/domain-intel.md
- **Developed by:** [Steadyline Data](https://apify.com/steadyline) (community)
- **Categories:** Developer tools, Business, Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 domain checkeds

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 Intel: WHOIS/RDAP, DNS, SSL, SPF & DMARC in bulk

Paste a list of domains (or URLs) and get one clean row per domain with:

- **RDAP / WHOIS**: registrar, IANA ID, abuse contact, creation / update / expiry dates, domain age, days until expiry, EPP status, nameservers, DNSSEC. The registry's RDAP server is found through the official IANA bootstrap, with rdap.org as a fallback.
- **DNS**: A, AAAA, CNAME, MX, NS, TXT, CAA, SOA, from public resolvers 1.1.1.1 and 8.8.8.8.
- **SSL certificate** on port 443: issuer, validity dates, days left, SANs, trust status, TLS version.
- **Email authentication**: SPF (syntax, `all` qualifier, includes, lookup count, issues), DMARC (policy, sp, pct, rua; inherited from the organizational domain if the subdomain has none), BIMI, MTA-STS (record plus policy mode) and TLS-RPT.
- **Provider detection**: the mail provider (Google Workspace, Microsoft 365, Proofpoint, …) and the DNS provider (Cloudflare, Route 53, NS1, …), inferred from MX and NS records.
- **Health score** from 0 to 100, with each deduction listed so you can see why.
- Optional: **subdomains from Certificate Transparency** logs (crt.sh).

Use cases: lead enrichment (company email stack, domain age), security and compliance audits (SPF/DMARC/certificate hygiene), expiry monitoring across a portfolio, and due diligence.

### Use cases

- **Expiry monitoring:** catch domain registrations and SSL certificates that expire soon, on a schedule.
- **Email authentication audits:** SPF, DMARC, BIMI and MTA-STS for every client or vendor domain.
- **Sales enrichment:** domain age and mail provider (Google Workspace, Microsoft 365) as firmographic signals.
- **Security and vendor due diligence:** registrar, DNS host, certificate issuer and subdomains from certificate transparency.
- **Portfolio management** for agencies and domain investors.

### Input

```json
{ "domains": ["apify.com", "https://www.github.com/about", "bbc.co.uk"], "includeCtSubdomains": false }
```

Each check can be switched off (`includeRdap`, `includeDns`, `includeSsl`, `includeEmailAuth`). Invalid entries and duplicates are skipped and never charged.

### Output sample (shortened)

```json
{
  "domain": "github.com", "status": "ok", "healthScore": 83,
  "registrar": "MarkMonitor Inc.", "createdAt": "2007-10-09T18:20:50Z", "expiresAt": "2028-10-09T18:20:50Z", "domainDaysLeft": 710,
  "sslIssuer": "Sectigo Limited", "sslDaysLeft": 89, "sslTrusted": true,
  "mailProvider": "Google Workspace", "dnsProvider": "NS1, Amazon Route 53",
  "spfValid": true, "dmarcPolicy": "reject", "emailAuthIssues": [],
  "rdap": { "registrarIanaId": "292", "status": ["client transfer prohibited"], "nameservers": ["dns1.p08.nsone.net"], "dnssec": false },
  "dns": { "a": ["140.82.112.3"], "mx": [{ "priority": 1, "exchange": "aspmx.l.google.com" }], "txt": ["v=spf1 ..."], "caa": [] },
  "ssl": { "validTo": "2027-01-27T23:59:59.000Z", "sans": ["github.com", "www.github.com"], "tlsProtocol": "TLSv1.3" },
  "emailAuth": { "spf": { "allQualifier": "fail", "includes": ["_spf.google.com"] }, "dmarc": { "policy": "reject", "rua": ["mailto:..."] }, "bimi": { "present": false }, "mtaSts": { "present": false } },
  "health": { "score": 83, "notes": ["-2 no CAA record"] }
}
```

The dataset has three views: **Overview**, **Email authentication** and **Expiry watch**.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `domain-checked` | **$0.001** per domain | A domain where DNS or RDAP answered. All enabled checks are included. |
| `ct-subdomains` | **$0.001** per domain | Only if you enable CT subdomains and crt.sh returns at least one subdomain. |

Invalid inputs, lookups that fail completely, and domains with no DNS and no RDAP record (unregistered) are **never charged**; they still appear in the dataset with `status` set. You also pay normal Apify platform usage, which is small because there is no browser.

**Cost example:** 1,000 domains with default settings cost about **$1.00** in events, plus a few cents of platform usage.

### Notes and limits

- RDAP replaces WHOIS for gTLDs. Some ccTLDs (for example .de) don't offer public RDAP, so `rdap` may be missing while DNS/SSL/email checks still work.
- Registrant personal data is redacted by registries, and this Actor does not try to recover it. Only the registrant organization/country is kept, and only when the registry publishes it.
- The SPF lookup count covers the top level only (nested includes are not expanded).

### Use it from AI agents (MCP), Zapier, Make, n8n or the API

**AI agents (Claude, Cursor, VS Code, ChatGPT and other MCP clients).** Add Apify's hosted MCP server with just this Actor as a tool:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=steadyline/domain-intel"
    }
  }
}
```

Sign in with Apify (OAuth) on first connect, or add an `Authorization: Bearer <APIFY_TOKEN>` header. Then ask your agent, for example:

> Use steadyline/domain-intel to check these 100 domains and list the ones whose SSL certificate or registration expires in the next 30 days, plus any with no DMARC policy.

The agent sees this Actor's input schema and output fields, so it can call it without extra prompting. Agents that use the general Apify MCP server can also find it with `search-actors`.

This Actor uses pay-per-event pricing with limited permissions, so it can also be run through Apify's agentic payments (no Apify account needed for the agent). See the [Apify docs](https://docs.apify.com/platform/integrations/mcp#agentic-payments).

**Zapier, Make and n8n.** Use the official Apify app: Zapier "Run Actor" action, Make "Run an Actor" module, or the n8n Apify node. Choose `steadyline/domain-intel`, paste the input below, then use "Get dataset items" (or the run's dataset) to send results to Google Sheets, Slack, a CRM or a database.

**API (any language).** Run it and get the results in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/steadyline~domain-intel/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["apify.com", "github.com"]}'
```

Or with the Python client (`pip install apify-client`):

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("steadyline/domain-intel").call(run_input={"domains": ["apify.com", "github.com"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Works well with other Steadyline Data tools

- **Email list hygiene:** clean addresses with [Email Deliverability Checker](https://apify.com/steadyline/email-deliverability-checker), then audit the remaining company domains here.
- **Domain due diligence:** this Actor + [Tech Stack Detector](https://apify.com/steadyline/tech-stack-detector) + [Website Screenshot](https://apify.com/steadyline/website-screenshot), about $0.005 per domain.
- Related: [Email Deliverability Checker](https://apify.com/steadyline/email-deliverability-checker), [Tech Stack Detector](https://apify.com/steadyline/tech-stack-detector), [Website Screenshot API](https://apify.com/steadyline/website-screenshot).

### FAQ

**Is this a WHOIS lookup?**
It uses RDAP, the ICANN-standard successor to WHOIS, for registrar and dates, plus live DNS and TLS checks.

**Can I find subdomains?**
Yes, turn on `includeCtSubdomains` to list subdomains from certificate-transparency logs (billed as `ct-subdomains`, $0.001 per domain).

**What does it cost?**
$0.001 per domain checked, so $1 per 1,000.

**Can I run it on a schedule?** Yes. Create an Apify Schedule (or a saved Task with a schedule) and connect a webhook or integration to receive results.

**Need a feature or found a bug?** Open an issue on the Issues tab of this page or email steadylinedata@proton.me. Built and maintained by **Steadyline Data**.

### Acceptable use

The Actor only reads public DNS, RDAP, Certificate Transparency and TLS handshake data, at a polite concurrency. Use it for domains you own, manage or have a legitimate interest in researching. Don't use it for spam or abuse. You're responsible for complying with applicable laws and the terms of the registries you query.

***

Built and maintained by **Steadyline Data**. Found an issue? Open one on the Actor's Issues tab.

# Actor input Schema

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

Domains or URLs (e.g. example.com, https://www.example.com/page). Duplicates and invalid entries are skipped and never charged.

## `includeRdap` (type: `boolean`):

Registrar, creation/expiry dates, status, nameservers, DNSSEC (from the registry RDAP service).

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

A, AAAA, CNAME, MX, NS, TXT, CAA, SOA plus mail/DNS provider detection.

## `includeSsl` (type: `boolean`):

Issuer, validity, days until expiry, SANs and trust status from port 443.

## `includeEmailAuth` (type: `boolean`):

SPF, DMARC, BIMI, MTA-STS and TLS-RPT checks with issues listed.

## `includeCtSubdomains` (type: `boolean`):

List subdomains seen in public CT logs (crt.sh). Charged as a separate event per domain when it succeeds. crt.sh can be slow.

## `maxCtSubdomains` (type: `integer`):

Cap on subdomains returned per domain.

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

Domains processed in parallel.

## `timeoutSecs` (type: `integer`):

Timeout for each DNS/RDAP/TLS lookup.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "github.com"
  ],
  "includeRdap": true,
  "includeDns": true,
  "includeSsl": true,
  "includeEmailAuth": true,
  "includeCtSubdomains": false,
  "maxCtSubdomains": 200,
  "maxConcurrency": 10,
  "timeoutSecs": 15
}
```

# Actor output Schema

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

One row per domain.

## `emailAuth` (type: `string`):

SPF / DMARC findings per domain.

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

Domain and certificate expiry.

# 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",
        "github.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyline/domain-intel").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",
        "github.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadyline/domain-intel").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",
    "github.com"
  ]
}' |
apify call steadyline/domain-intel --silent --output-dataset

```

## MCP server setup

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

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/PDwrpPwI57poYhnCC/builds/fEks2q3Z3IsnlQE2P/openapi.json
