# Domain Intelligence — WHOIS, DNS, TLS & Email Security (`relevate/domain-intelligence`) Actor

Everything official about a domain in one clean JSON: RDAP registration data (registrar, dates, status), full DNS, SPF/DMARC mail security, the live TLS certificate, robots.txt and sitemaps, and Wayback history — with explicit, sourced risk flags. Official registries and protocols only, no scraping.

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

## Pricing

from $5.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/platform/actors/running/actors-in-store#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

## Domain Intelligence — WHOIS/RDAP, DNS, TLS & Email Security in One Call

Check any domain against every **official** source at once and get back one clean JSON: who registered it and until when, its full DNS, whether its email can be spoofed, whether its HTTPS certificate is actually valid, what it tells crawlers, and how far back the archive goes.

No scraping, no captchas, no proxies. Every field comes from a registry or an internet protocol — RDAP, DNS-over-HTTPS, a real TLS handshake, `robots.txt`, and the Wayback Machine CDX index. That is why this Actor does not break when a website changes its markup.

### Why one Actor instead of five

Domain checks are normally spread across a WHOIS lookup, a DNS tool, an SSL checker and a sitemap finder — four runs, four schemas, four things to stitch together. This Actor does the whole set concurrently and returns a single record per domain, with a one-word `verdict` you can branch on and a `flags` array where **every finding names the source that produced it**.

### What you get per domain

| Section | Contents |
|---|---|
| `registration` | Registrar and its IANA ID, abuse contact, registration / expiry / last-changed dates, registry status codes, nameservers, DNSSEC. Read over **RDAP**, the IETF replacement for WHOIS. |
| `dns` | A, AAAA, MX, NS, TXT, SOA, CAA records, the detected mail provider, and the mail-security posture: **SPF** (with its policy) and **DMARC** (with `p=`). |
| `tls` | Issuer, subject, validity window, **days until expiry**, every subject alternative name, whether the certificate really covers the domain, negotiated protocol. |
| `robots` | Declared sitemaps, number of disallow rules, whether the site blocks all crawlers. |
| `archive` | First and last successful Wayback snapshot — real evidence of age, independent of the registration date. Optional. |
| `flags` | Explicit findings, each with `code`, `severity`, `message` and `source`. |
| `verdict` | `clean`, `notice`, `warning` or `alert` — the worst severity found. |

#### Flags it raises

`domainExpired` · `domainExpiringSoon` · `newlyRegistered` (under 90 days — a standard phishing signal) · `domainNotRegistered` · `registryHold` · `transferLockMissing` · `dnssecUnsigned` · `doesNotResolve` · `noMailRecords` · `spfMissing` · `dmarcMissing` · `dmarcPolicyNone` · `parkedDomain` · `httpsUnavailable` · `certificateExpired` · `certificateExpiringSoon` · `certificateHostnameMismatch` · `certificateNotTrusted` · `robotsBlocksAllCrawlers` · `noSitemapDeclared` · `noArchiveHistory`

### Input

Paste domains in any shape. URLs and email addresses are cleaned up automatically, so `https://www.example.com/pricing` and `info@example.com` both become `example.com`.

```json
{
  "domains": ["apify.com", "https://www.example.com/pricing", "info@example.org"],
  "includeRegistration": true,
  "includeDns": true,
  "includeTls": true,
  "includeRobots": true,
  "includeWayback": false,
  "maxResults": 100,
  "minExpectedResults": 0
}
```

Turn off any section you do not need — each one you skip makes the run faster and cheaper. `includeWayback` is off by default because the archive index is the slowest source.

### Sample output (trimmed)

```json
{
  "domain": "apify.com",
  "checkedOn": "2026-08-08",
  "verdict": "clean",
  "flagCount": 0,
  "flags": [],
  "registration": {
    "available": true,
    "registrar": "Amazon Registrar, Inc.",
    "registeredOn": "2009-06-02T17:14:10Z",
    "expiresOn": "2035-06-02T17:14:10Z",
    "statuses": ["client transfer prohibited"],
    "dnssec": true,
    "registrantRedacted": true,
    "source": "https://rdap.verisign.com/com/v1/domain/apify.com"
  },
  "dns": {
    "ipv4": ["18.66.26.11"],
    "mx": ["aspmx.l.google.com"],
    "mailProvider": "Google Workspace",
    "spf": "v=spf1 include:_spf.google.com -all",
    "spfPolicy": "-",
    "dmarcPolicy": "reject",
    "resolves": true
  },
  "tls": {
    "available": true,
    "issuer": "Amazon",
    "validTo": "2027-01-16",
    "daysUntilExpiry": 161,
    "coversDomain": true,
    "authorized": true
  }
}
```

### Built for AI agents

- **One small JSON per domain**, no nested crawl output to post-process.
- **Fast** — every source is queried concurrently; a domain typically finishes in a few seconds.
- **Idempotent** — same domain, same answer. No sessions, no cookies, no login.
- **Honest failure** — when a source cannot answer, you get `available: false` and a plain-language `reason` instead of a silently missing field. A subdomain is looked up at its registered parent, and that parent is reported in `registeredDomain`.

### Typical uses

- **Vendor and counterparty due diligence** — how old is this supplier's domain, does it expire next month, is it parked?
- **Phishing and fraud triage** — a domain registered 11 days ago with no DMARC and a mismatched certificate.
- **Email deliverability audits** — find every domain in a portfolio missing SPF or running DMARC `p=none`.
- **Certificate expiry monitoring** — schedule it daily and alert on `certificateExpiringSoon`.
- **Lead and account enrichment** — mail provider, hosting, and registrar for a list of company domains.

### Scheduling and health checks

Set `minExpectedResults` to the number of domains you expect. If the run produces fewer, it **fails loudly** instead of quietly returning less — so a scheduled monitor tells you when something upstream changed. Pair it with a Schedule and Apify's failure notifications.

### Coverage and limits

- **RDAP** covers all gTLDs (`.com`, `.net`, `.org`, and the new ones) plus many ccTLDs. Some ccTLDs — `.eu` and `.io` among them — publish no RDAP service in the IANA bootstrap; the Actor says so explicitly in `registration.reason` and still returns DNS, TLS and the rest.
- **Registrant identity** is redacted by most registries under the GDPR. This Actor reports *that* a redaction is in place (`registrantRedacted`) and never attempts to unmask a private individual. It returns registrar and abuse contacts, which are company data.
- **Wayback history is best-effort.** The archive index is slow and inconsistent — on domains with very large archives it can exceed the 20-second budget. When that happens you get `archive.available: false` with the reason, and every other section is unaffected. This is why the section is off by default.
- **Rate limits** are the public ones of each source; the Actor retries transient failures with backoff.

### Pricing

Pay per event: a small charge to start the run, then a per-domain charge. You pay for domains checked, not for compute time.

# Actor input Schema

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

Domain names to check. URLs and email addresses are accepted too — anything extra is stripped, so "https://www.example.com/pricing" and "info@example.com" both resolve to example.com.

## `includeRegistration` (type: `boolean`):

Registrar, registration and expiry dates, registry status codes, nameservers, DNSSEC and the registrar's abuse contact, read from the domain registry over RDAP. Registrant identity is redacted by most registries under the GDPR — this Actor reports the redaction, never a private individual.

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

A, AAAA, MX, NS, TXT, SOA and CAA records over DNS-over-HTTPS, plus the mail-security posture agents usually ask for: SPF, DMARC and its policy, and a guess at the mail provider.

## `includeTls` (type: `boolean`):

Opens a real TLS handshake on port 443 and reads the certificate: issuer, validity window, days until expiry, all subject alternative names, and whether the certificate actually covers this domain. Expired and mismatched certificates are reported rather than treated as an error.

## `includeRobots` (type: `boolean`):

Fetches robots.txt, lists the sitemaps it declares, counts disallow rules and detects a site that blocks all crawlers.

## `includeWayback` (type: `boolean`):

First and last archived snapshot from web.archive.org — evidence of how long the domain has really been in use, independent of the registration date. Off by default because it adds a few seconds per domain.

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

Safety cap on how many domains are checked in one run.

## `minExpectedResults` (type: `integer`):

Fail the run if fewer than this many domains are checked. Use it in scheduled pipelines to get alerted when a source changes. 0 disables the check.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "europa.eu",
    "expired.badssl.com"
  ],
  "includeRegistration": true,
  "includeDns": true,
  "includeTls": true,
  "includeRobots": true,
  "includeWayback": false,
  "maxResults": 100,
  "minExpectedResults": 0
}
```

# 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",
        "europa.eu",
        "expired.badssl.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("relevate/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": [
        "apify.com",
        "europa.eu",
        "expired.badssl.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("relevate/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": [
    "apify.com",
    "europa.eu",
    "expired.badssl.com"
  ]
}' |
apify call relevate/domain-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,relevate/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/DqILnh16N53zgE0cW/builds/oPTx2SynABsm9L5rV/openapi.json
