# Domain Intelligence - DNS, SSL, RDAP, Email Security & Tech (`fabrikit/domain-intelligence`) Actor

Bulk domain checker: one record per domain with DNS (A, MX, NS, TXT, CAA, SOA), SPF/DMARC/DKIM/MTA-STS/BIMI, SSL expiry, HTTP redirects and HSTS, RDAP registration and availability, optional tech stack. No API keys. From US$2.00 per 1,000 domains.

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

## Pricing

from $2.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 Intelligence - DNS, SSL, RDAP, email security and tech stack for thousands of domains

Paste a list of domains (or URLs) and get **one clean record per domain** with everything you usually need five tools for:

| Block | What you get |
|---|---|
| **DNS** | A, AAAA, MX, NS, TXT, CNAME, CAA and SOA, resolved through resolvers you choose (default 1.1.1.1 and 8.8.8.8) with an automatic DNS-over-HTTPS fallback |
| **Email security** | SPF (parsed, with the real DNS-lookup count), DMARC policy / percentage / alignment, DKIM selector probe (~40 common selectors + your own), MTA-STS (policy fetched), BIMI, mail provider, plain-English issues list |
| **SSL/TLS** | Issuer, valid from / to, **days to expiry**, SANs, protocol, cipher, key type, chain, trust errors (expired, self-signed, hostname mismatch, weak key) |
| **HTTP** | Final URL after redirects, status code, redirect chain, `Server`, HSTS (max-age, preload), security headers present, time to first byte |
| **Registration (RDAP)** | Registrar, created / updated / **expires** dates, domain age, status flags, nameservers, DNSSEC - via the IANA RDAP bootstrap, so it works for 1,200+ TLDs |
| **Availability** | `available` / `registered` / `likely-available`, with the basis and a confidence level (RDAP 404 = not registered) |
| **Tech stack** (add-on) | CMS, e-commerce platform, analytics, tag managers, CDN, hosting, frameworks, DNS and email provider (~200 technologies) |

No API keys, no logins, no proxy. Everything uses open protocols (DNS, TLS, HTTPS, RDAP).

**Partial results never fail the run.** Each check has its own timeout and error. A dead site only loses its own HTTP/SSL check; the DNS, email and RDAP parts of the record are still delivered, and `checks` / `errors` tell you exactly what happened.

### Privacy

Only company-level technical data is collected. RDAP registrant, administrative, technical and abuse contacts are **never read**; only the registrar is kept. Mailbox addresses found in DMARC `rua`/`ruf` tags are masked (`mailto:***@example.com`), and the SOA contact mailbox is dropped.

### Input

```json
{
  "domains": ["apify.com", "https://www.github.com/pricing", "example.org"],
  "detectTech": true
}
```

| Field | Default | Description |
|---|---|---|
| `domains` | - | Domains or URLs, one per line. Only the host is used. Duplicates removed; invalid entries skipped and **not charged**. |
| `checkDns`, `checkEmailSecurity`, `checkSsl`, `checkHttp`, `checkRdap` | `true` | Switch each block on or off. |
| `detectTech` | `false` | Technology detection add-on (reuses the homepage fetched by the HTTP check). |
| `resolvers` | `1.1.1.1`, `8.8.8.8` | Recursive resolvers (IPs). |
| `dohFallback` | `true` | Retry failed UDP lookups over Cloudflare/Google DNS-over-HTTPS. |
| `extraDkimSelectors` | `[]` | Selectors to probe in addition to the built-in list. |
| `concurrency` | `25` | Domains in parallel (1-200). |
| `checkTimeoutSecs` | `10` | Timeout per check. |
| `maxItems` | `100000` | Cap on domains per run. |

### Output example (shortened)

```json
{
  "domain": "github.com",
  "registrableDomain": "github.com",
  "tld": "com",
  "status": "ok",
  "dns": { "status": "ok", "a": ["140.82.121.4"], "mx": [{ "priority": 1, "exchange": "aspmx.l.google.com" }], "ns": ["dns1.p08.nsone.net"], "caa": [{ "flags": 0, "tag": "issue", "value": "digicert.com" }], "resolvedVia": "udp" },
  "email": {
    "provider": "Google Workspace",
    "spf": { "present": true, "policy": "~all", "dnsLookups": 9 },
    "dmarc": { "present": true, "policy": "reject", "pct": 100, "aggregateReports": true },
    "dkim": { "probed": 43, "found": [{ "selector": "google", "keyType": "rsa", "approxKeyBits": 2048 }] },
    "mtaSts": { "present": false }, "bimi": { "present": false },
    "issues": []
  },
  "ssl": { "valid": true, "issuer": { "commonName": "Sectigo Public Server Authentication CA DV E36" }, "validTo": "2026-11-29T23:59:59.000Z", "daysToExpiry": 47, "protocol": "TLSv1.3", "issues": [] },
  "http": { "finalUrl": "https://github.com/", "statusCode": 200, "server": "github.com", "hsts": { "maxAge": 31536000, "includeSubDomains": true, "preload": true }, "ttfbMs": 210 },
  "rdap": { "registered": true, "registrar": "MarkMonitor Inc.", "registeredAt": "2007-10-09T18:20:50.000Z", "expiresAt": "2028-10-09T18:20:50.000Z", "daysToExpiry": 727, "dnssec": false },
  "availability": { "status": "registered", "available": false, "confidence": "high", "basis": "rdap-record" },
  "tech": [{ "name": "Google Workspace", "category": "Email provider", "evidence": ["dns:mx"] }],
  "checks": { "dns": "ok", "email": "ok", "ssl": "ok", "http": "ok", "rdap": "ok", "tech": "ok" },
  "errors": {}
}
```

`status` is `ok`, `partial` (a check timed out or errored), `nxdomain` (the name does not resolve) or `failed`.

### Pricing (pay per event)

| Event | Price |
|---|---|
| `domain-result` - one domain record, all checks included | **US$2.00 per 1,000 domains** |
| `tech-detection` - add-on, only when `detectTech` is on | US$1.00 per 1,000 domains |

Invalid inputs and duplicates are free. A run capped by your spending limit stops cleanly and keeps what it has.

### Use cases

- **Domain portfolio monitoring**: certificate and registration expiry across hundreds of domains, in one scheduled run.
- **Email deliverability audits**: find domains without SPF/DMARC, `p=none` policies, SPF over the 10-lookup limit.
- **Lead enrichment and segmentation**: which CMS / e-commerce platform / mail provider does each prospect use?
- **Domain investing and brand protection**: availability and expiry dates at scale; spot lookalike domains.
- **Security and compliance sweeps**: HSTS, security headers, outdated TLS, self-signed or expired certificates.

### FAQ

**Is availability 100% accurate?** An RDAP 404 means the registry has no record of the name, which is how registries report an unregistered domain. It does not detect premium, reserved or restricted names, so treat it as "likely available". TLDs without RDAP (several country codes) fall back to a low-confidence DNS verdict.

**Why was my DKIM selector not found?** DKIM selectors are secret by design; the probe covers ~40 widely used ones. Add yours in `extraDkimSelectors`.

**How fast is it?** Roughly 2 domains per second with every check on (about 4 minutes for 500 domains in our local test). Turn off blocks you do not need to go faster.

**Does it need a proxy?** No.

### En español

Pega una lista de dominios o URLs y obtén un registro por dominio con DNS (A, MX, NS, TXT, CAA, SOA), seguridad de correo (SPF, DMARC, DKIM, MTA-STS, BIMI), certificado SSL con días para vencer, HTTP (redirecciones, HSTS), datos de registro por RDAP (registrador, fechas, vencimiento), disponibilidad del dominio y, opcionalmente, las tecnologías que usa el sitio. Sin API keys ni proxy. Si un chequeo falla, el resto del registro se entrega igual. Precio: US$2,00 por 1.000 dominios (+ US$1,00 por 1.000 si activas la detección de tecnologías). No se recopilan datos de personas: solo el registrador.

# Actor input Schema

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

Domains to check, one per line: `example.com`, `www.example.com`, or full URLs such as `https://example.com/pricing` (only the host is used). Duplicates are removed. Thousands per run are fine. Invalid entries are skipped and not charged.

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

A, AAAA, MX, NS, TXT, CNAME, CAA and SOA records.

## `checkEmailSecurity` (type: `boolean`):

SPF (parsed, with DNS-lookup count), DMARC policy, DKIM selector probe, MTA-STS, BIMI, mail provider and a list of issues.

## `checkSsl` (type: `boolean`):

Issuer, validity dates, days to expiry, SANs, protocol, key type, chain and trust problems (expired, self-signed, hostname mismatch).

## `checkHttp` (type: `boolean`):

Final URL after redirects, status code, server header, HSTS, security headers and response time.

## `checkRdap` (type: `boolean`):

Registrar, created / updated / expiry dates, status flags, nameservers and DNSSEC from the registry's RDAP service, plus an availability verdict (RDAP 404 = likely available). Registrant and contact details are never collected.

## `detectTech` (type: `boolean`):

Detect CMS, e-commerce platform, analytics, CDN, framework, hosting and email provider from the homepage, headers and DNS. Billed as the `tech-detection` add-on per domain.

## `resolvers` (type: `array`):

IP addresses of recursive resolvers to query. Examples: `1.1.1.1` (Cloudflare), `8.8.8.8` (Google), `9.9.9.9` (Quad9).

## `dohFallback` (type: `boolean`):

If a UDP query fails (timeouts, SERVFAIL), retry through Cloudflare and Google DNS-over-HTTPS.

## `extraDkimSelectors` (type: `array`):

Additional DKIM selectors to probe on top of ~40 common ones (`google`, `selector1`, `k1`, `s1`, `mandrill`, ...). DKIM selectors are secret by design, so a missing selector does not mean DKIM is off.

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

Domains checked in parallel. 25 is a good default; raise to 50-100 for very large lists on 1 GB+ memory.

## `checkTimeoutSecs` (type: `integer`):

Network timeout for each individual check. A slow or dead domain only loses its own check, never the run.

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

Stop after this many domains.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "github.com",
    "stripe.com",
    "example.org"
  ],
  "checkDns": true,
  "checkEmailSecurity": true,
  "checkSsl": true,
  "checkHttp": true,
  "checkRdap": true,
  "detectTech": true,
  "resolvers": [
    "1.1.1.1",
    "8.8.8.8"
  ],
  "dohFallback": true,
  "extraDkimSelectors": [],
  "concurrency": 25,
  "checkTimeoutSecs": 10,
  "maxItems": 100000
}
```

# Actor output Schema

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

All records collected during the run

# 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",
        "stripe.com",
        "example.org"
    ],
    "detectTech": true,
    "resolvers": [
        "1.1.1.1",
        "8.8.8.8"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/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",
        "github.com",
        "stripe.com",
        "example.org",
    ],
    "detectTech": True,
    "resolvers": [
        "1.1.1.1",
        "8.8.8.8",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/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",
    "github.com",
    "stripe.com",
    "example.org"
  ],
  "detectTech": true,
  "resolvers": [
    "1.1.1.1",
    "8.8.8.8"
  ]
}' |
apify call fabrikit/domain-intelligence --silent --output-dataset

```

## MCP server setup

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