# Domain Intel: DNS, WHOIS/RDAP, Email Security & Tech Stack (`hanielazevedo/domain-intel`) Actor

One row per domain: DNS records, hosting/CDN from IP ASN, RDAP registrar and expiry, SPF/DMARC/DKIM/MTA-STS/BIMI score, HTTPS/TLS, security headers grade and 7,600+ tech fingerprints. Open protocols only. Pay only for domains that resolve.

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

## Pricing

from $3.00 / 1,000 domain analyzeds

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: DNS, WHOIS/RDAP, Email Security & Tech Stack

One row per domain with everything you usually need five tools for: **DNS records + hosting/CDN (ASN)**, **registration data via RDAP** (the official successor of WHOIS), **email security** (SPF, DMARC, DKIM, MTA-STS, TLS-RPT, BIMI + an A–F score), **website/TLS/security headers**, **technology stack** (7,600+ open fingerprints) and optional **public contact emails & social links**.

Built only on open protocols and open data — no paid WHOIS, no BuiltWith API, no AI calls, no headless browser. That is why it is fast (≈ 30 domains in 10 s) and cheap.

**You only pay for domains that resolve.** Typos, dead and non-existent domains (NXDOMAIN), DNS errors and invalid input are returned for free with a clear error code.

### Who is it for?

- **Sales & lead generation** – enrich a list of company domains with tech stack (Shopify? HubSpot? Salesforce?), mail provider (Google Workspace vs Microsoft 365), public emails and social profiles.
- **Security audits & MSPs** – spot missing DMARC, `~all` SPF, too many SPF lookups, weak 1024-bit DKIM keys, missing HSTS/CSP, expiring certificates and domains.
- **Agencies** – pitch clients with a concrete "email deliverability & website security" report, exported to CSV.
- **M\&A / due diligence / brand protection** – domain age, registrar, expiry date, DNSSEC, hosting provider and parked domains across a portfolio.
- **AI agents** – a single structured call (via API or MCP) answers "what is this company running and is its email secure?".

### How to use it (step by step)

1. Open the Actor and paste domains or URLs in **Domains or URLs** (one per line; `https://www.example.com/page`, `Example.COM` and `münchen.de` are all accepted, normalized and de-duplicated).
2. Keep the defaults or switch modules off (RDAP, email security, DKIM probing, web, tech stack, contacts) to go faster.
3. Optionally set **Max total charge** in the run options — the Actor stops charging exactly at your limit (remaining domains get a free `BUDGET_EXCEEDED` row).
4. Click **Start**. Results appear in the **Overview**, **Email security**, **Leads** and **Infrastructure** views.
5. Download as JSON/Excel/CSV, or take the flat `SUMMARY.csv` from the key-value store (one line per domain, ready for spreadsheets/CRMs).

### Input

| Field | Default | What it does |
|---|---|---|
| `domains` | – | Domains or URLs (also accepts `urls` / `startUrls` via API) |
| `keepSubdomains` | false | Analyze `blog.example.com` as is instead of `example.com` |
| `hostingAsn` | true | Map IPs to ASN/hosting/CDN via Team Cymru DNS |
| `rdap` | true | Registrar, dates, status via RDAP (IANA bootstrap) |
| `emailSecurity` / `probeDkim` / `dkimSelectors` | true / true / \[] | SPF/DMARC/MTA-STS/TLS-RPT/BIMI + DKIM probing of ~30 common selectors plus yours |
| `web` / `techStack` / `contacts` | true | Homepage fetch (1 request, ≤8 redirects), TLS, headers, tech stack, emails & socials |
| `maxConcurrency` | 20 | Parallel domains (max 60) |
| `maxDomains` | – | Hard cap for the run |
| `dnsResolvers` | system | e.g. `["1.1.1.1","8.8.8.8"]` |

### Output (one row per domain)

Flat columns for tables/CSV plus nested detail objects (`dns`, `rdap`, `emailSecurity`, `web`, `techStack`, `modules`, `errors`, `timingsMs`). Real example (apify.com, 2026-10-31, shortened):

```json
{
  "domain": "apify.com", "status": "OK", "charged": true,
  "ips": ["3.170.42.100", "..."], "hostingProvider": "AWS", "asn": 16509, "dnsProvider": "Amazon Route 53",
  "mailProvider": "Google Workspace", "dnssec": true,
  "registrar": "Amazon Registrar, Inc.", "createdDate": "2009-06-02T17:14:10+00:00", "daysUntilExpiry": 3135,
  "emailSecurityScore": 100, "emailSecurityGrade": "A", "spoofingProtection": "strong",
  "spf": "present -all", "spfLookups": 10, "dmarcPolicy": "reject", "dkimSelectors": ["google"],
  "mtaSts": "enforce", "tlsRpt": true, "bimi": true,
  "finalUrl": "https://apify.com/", "httpStatus": 200, "https": true, "tlsIssuer": "Amazon",
  "securityHeadersGrade": "B", "title": "Apify: Marketplace of ready-to-run tools for AI",
  "technologies": ["Leadfeeder", "Linkedin Insight Tag", "Amazon CloudFront", "Algolia", "HSTS", "..."],
  "dnsTechnologies": ["Mixpanel", "HubSpot", "Mailgun", "..."],
  "emails": ["support@apify.com"], "socialLinks": {"x": ["https://x.com/apify"], "github": ["https://github.com/apify"]},
  "modules": {"dns": {"status": "ok"}, "rdap": {"status": "ok"}, "email": {"status": "ok"}, "web": {"status": "ok"}, "tech": {"status": "ok"}},
  "errors": []
}
```

`technologies` = evidence from the website (headers, HTML, scripts, cookies, meta). `dnsTechnologies` = only seen as DNS-TXT verification tokens (the company verified a domain with that vendor; it may not be in active use). `techStack[]` has category, version, confidence and `detectedBy` for each.

**Status values:** `OK`, `PARTIAL` (DNS resolved, some module failed — see `errors`), `NXDOMAIN`, `NO_DNS_RECORDS`, `DNS_ERROR`, `INVALID_INPUT`, `BUDGET_EXCEEDED`. Only `OK` and `PARTIAL` are charged.

**Error codes** (stable, per module): `INVALID_DOMAIN`, `NXDOMAIN`, `DNS_NO_RECORDS`, `DNS_TIMEOUT`, `DNS_SERVFAIL`, `DNS_ERROR`, `ASN_LOOKUP_FAILED`, `RDAP_UNSUPPORTED_TLD`, `RDAP_NOT_FOUND`, `RDAP_RATE_LIMITED`, `RDAP_HTTP_ERROR`, `RDAP_TIMEOUT`, `RDAP_BAD_RESPONSE`, `EMAIL_TIMEOUT`, `WEB_DNS_ERROR`, `WEB_CONNECT_ERROR`, `WEB_TIMEOUT`, `WEB_TLS_ERROR`, `WEB_TOO_MANY_REDIRECTS`, `WEB_HTTP_ERROR`, `TLS_NO_HTTPS`, `TLS_CERT_INVALID`, `TECH_TIMEOUT`, `BUDGET_EXCEEDED`, `MODULE_CRASHED`.

**Email security score** (0–100): SPF 25, DMARC 35, DKIM 20, MTA-STS 10, TLS-RPT 5 (the last three only if the domain receives mail), BIMI 5, normalized. A ≥ 90, B ≥ 75, C ≥ 60, D ≥ 40, else F. Each problem is listed in `emailSecurity.findings` with code, severity and a plain-English message (e.g. `SPF_TOO_MANY_LOOKUPS`, `DMARC_MISSING`, `DKIM_1024_BIT_KEY`).

### Pricing

Pay per event: **one `domain-analyzed` event per domain that resolves in DNS**. No start fee. Free: NXDOMAIN, DNS errors, invalid input, anything over your max total charge.

### How it compares (Apify Store, checked 2026-10-31)

| Actor | Scope | Price model (as listed) |
|---|---|---|
| **Domain Intel (this)** | DNS+ASN, RDAP, SPF/DMARC/DKIM/MTA-STS/TLS-RPT/BIMI score, TLS, headers, tech, contacts | per resolving domain, no start fee |
| BuiltWith – technology scraper (most used in the niche) | tech stack | $0.002 / result |
| santamaria-automations – domain WHOIS & DNS | WHOIS + DNS | $0.001 start + $0.003 / result |
| agenscrape – WHOIS domain lookup | WHOIS | $0.0025 / result |
| automation-lab – Wappalyzer technology lookup | tech stack | $0.005 start + $0.00024 / result |
| Email-security checkers (several, ≤ 3 monthly users each) | SPF/DMARC (some DKIM) | $0.0008–$0.006 / result |
Prices and features of third-party Actors change; verify on their pages.

### Use via API, integrations and MCP

Run synchronously and get the rows back (replace the token; `~` separates user and Actor name):

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

Python: `ApifyClient(token).actor("hanielazevedo/domain-intel").call(run_input={"domains": [...]})`, then read `defaultDatasetId`. The flat CSV is at `.../key-value-stores/{defaultKeyValueStoreId}/records/SUMMARY.csv`, run totals at `OUTPUT`.

**AI agents (MCP):** add Apify's MCP server (`https://mcp.apify.com`, e.g. `https://mcp.apify.com?tools=hanielazevedo/domain-intel`) to Claude, Cursor, VS Code or any MCP client; the agent gets a tool that takes `domains` and returns the rows above. Tip for agents: switch off `probeDkim` and `contacts` for the fastest answers.

Works with Apify integrations (Zapier, Make, n8n, Google Sheets, webhooks) and scheduling.

### FAQ

**Is this WHOIS?** It uses RDAP, the IETF-standard JSON replacement for WHOIS that ICANN requires for gTLDs. Registries are found through the official IANA bootstrap; requests are paced per server and honour `Retry-After`.
**Why is registrant name empty?** Since GDPR, registries redact personal data. We return registrant organization/country only when the registry publishes them, and never personal names.
**Why `RDAP_UNSUPPORTED_TLD` for .de, .so …?** Some ccTLDs have no public RDAP service. All other modules still run.
**Why did DKIM say "not found" for a domain that signs mail?** DKIM selectors cannot be listed; we probe ~30 common ones (Google, Microsoft 365, Mailchimp/Mandrill, SendGrid, HubSpot, Zoho, Proton, Fastmail, Mailjet, …). Add your own in `dkimSelectors`. Google's rotating date-based selectors are not guessable.
**Some sites show `WEB_HTTP_ERROR` 403?** Some sites block non-browser clients (bot protection). DNS, RDAP and email data are still returned and the row is `PARTIAL`.
**Is it legal?** It reads public DNS, public registration data and one public homepage per domain — the same as a browser. Use contact data in line with GDPR/LGPD/CAN-SPAM.

### Limitations

- One homepage request, no JavaScript rendering: technologies that only appear after JS runs (or behind bot walls) are missed; DNS-only detections are reported separately.
- Hosting/CDN is inferred from ASN and CNAMEs; a site behind a CDN shows the CDN, not the origin host.
- Parked detection uses parking nameservers and page text; not exhaustive.
- RDAP coverage depends on each registry (some ccTLDs missing, some rate-limit heavily — large batches of one ccTLD can return `RDAP_RATE_LIMITED`).
- Results reflect DNS/web state at run time and the resolver used.

### Data sources & licences

- Technology fingerprints: [enthec/webappanalyzer](https://github.com/enthec/webappanalyzer) (GPL-3.0), pinned commit, fetched unmodified at build time. Commit is reported in the run `OUTPUT`.
- IP→ASN: Team Cymru IP-to-ASN DNS service (free, public).
- RDAP: IANA RDAP bootstrap registry and registry/registrar RDAP servers.
- Public Suffix List via `tldextract` (MPL-2.0), bundled snapshot (no network).
- Libraries: dnspython (ISC), httpx (BSD), cryptography (Apache-2.0/BSD), idna (BSD), Apify SDK (Apache-2.0).

# Actor input Schema

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

Domains, URLs or email addresses, one per line. They are normalised (scheme, path, port, www. removed), converted to punycode (IDN) and de-duplicated. Example: apify.com, https://www.github.com/about, info@example.org.

## `keepSubdomains` (type: `boolean`):

Off (default): shop.example.com is analysed as example.com. On: the exact host is analysed.

## `hostingAsn` (type: `boolean`):

Look up the ASN and network owner of up to 4 IPv4 + 2 IPv6 addresses via the free Team Cymru DNS service, and infer hosting and CDN.

## `rdap` (type: `boolean`):

Registrar, created/updated/expiry dates, days until expiry, EPP status and nameservers from the registry's official RDAP server (IANA bootstrap). Some ccTLDs have no RDAP: they return RDAP_UNSUPPORTED_TLD.

## `emailSecurity` (type: `boolean`):

SPF (with RFC 7208 DNS-lookup count), DMARC, DKIM selector probing, MTA-STS (incl. policy file), TLS-RPT and BIMI, with a 0-100 score, grade and findings.

## `probeDkim` (type: `boolean`):

Check about 30 common DKIM selectors (google, selector1, selector2, k1, s1, mandrill, zoho...). DKIM under a custom selector cannot be discovered by anyone without a sample email.

## `dkimSelectors` (type: `array`):

Optional extra selectors to check for every domain.

## `web` (type: `boolean`):

One GET of the homepage (redirects followed manually), HTTPS certificate issuer and expiry, security-headers grade, title, meta description, parked-domain detection.

## `techStack` (type: `boolean`):

Detect technologies from the same response, DNS and certificate using 7,600+ open webappanalyzer fingerprints (no headless browser).

## `contacts` (type: `boolean`):

Extract social profile links and email addresses published on the homepage.

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

Domains analysed in parallel.

## `maxDomains` (type: `integer`):

Optional cap on how many unique domains to analyse (useful for tests).

## `dnsResolvers` (type: `array`):

Optional resolver IPs. Default: the platform resolver, falling back to 1.1.1.1, 8.8.8.8, 9.9.9.9.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "github.com",
    "google.com"
  ],
  "keepSubdomains": false,
  "hostingAsn": true,
  "rdap": true,
  "emailSecurity": true,
  "probeDkim": true,
  "dkimSelectors": [],
  "web": true,
  "techStack": true,
  "contacts": true,
  "maxConcurrency": 20,
  "dnsResolvers": []
}
```

# Actor output Schema

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

No description

## `full` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `summary` (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": [
        "apify.com",
        "github.com",
        "google.com"
    ]
};

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

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

```

## MCP server setup

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