Domain Intelligence & Enrichment — WHOIS, DNS, Email Provider
Pricing
from $2.10 / 1,000 domain enricheds
Domain Intelligence & Enrichment — WHOIS, DNS, Email Provider
Bulk domain enrichment and DNS check, one row per domain or email: email provider (Google Workspace, M365, Proofpoint), DMARC/SPF/DKIM, WHOIS/RDAP domain age and registrar, SSL type (EV/OV/DV), hosting ASN (AWS, Cloudflare), CDN, tech stack and a maturity score.
Pricing
from $2.10 / 1,000 domain enricheds
Rating
0.0
(0)
Developer
Brenton Keller
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 days ago
Last modified
Categories
Share
Domain Intelligence Check
What does a company run, and how seriously does it run it?
Bulk domain enrichment: a WHOIS lookup, a DNS check and an email-provider check in one row. Input domains, URLs or email addresses and get one row for each:
- who handles the company's mail (Google Workspace, Microsoft 365, or a security gateway such as Proofpoint)
- whether its domain is protected against spoofing (SPF, DMARC, DKIM)
- how old the domain is and who registered it
- what kind of TLS certificate it serves
- what sits in front of its website, and which network hosts it (AWS, Google Cloud, Cloudflare, or the company's own network)
- which SaaS tools it has verified ownership with
A maturity score adds those up, and maturity_signals gives the reasons for the score.
stripe.com 92 registered 31 years ago · Google Workspace · DMARC p=reject · EV certificateaccenture.com 100 registered 26 years ago · mail behind Proofpoint · DMARC p=reject · OV cert · CloudFrontnotion.so 70 registered 11.5 years ago · DMARC p=quarantine · behind Cloudflare · no MX on this domain
Everything comes from public infrastructure: DNS (including an IP-to-ASN lookup), RDAP/WHOIS, a TLS handshake and one request to the homepage. That is why it is fast. 14 inputs took 1.5 s and there's no proxy to pay for.
Paste a column of emails
A lead list is usually a column of email addresses, so the actor accepts them directly:
jane@figma.com→figma.comhttps://shop.acme.co.uk/x→acme.co.uk
Each line you submit gets its own row, with your original text in query, so the results join
straight back onto your sheet.
Free mailbox domains (gmail.com, outlook.com, yahoo.com …) say nothing about a person's employer. They are returned with a note and not charged.
Use it from the API, Clay, or a weekly schedule
API: one call, rows back
run-sync-get-dataset-items starts a run, waits for it and returns the rows in one request.
A small batch comes back in about 3–4 seconds.
curl -X POST "https://api.apify.com/v2/acts/brenton8907~domain-intel-check/run-sync-get-dataset-items?token=$APIFY_TOKEN&maxTotalChargeUsd=0.01" \-H "Content-Type: application/json" \-d '{"domains": ["jane@linear.app"]}'
[{"query": "jane@linear.app", "domain": "linear.app", "checked_at": "2026-10-12T19:26:41Z","email_provider": "google_workspace", "dmarc_policy": "reject", "maturity_score": 82,"hosting_provider": "cloudflare", ...}]
fields=query,domain,email_provider,dmarc_policy,maturity_scoretrims the columns returned.format=csvreturns CSV instead of JSON.maxTotalChargeUsdis a hard spend ceiling for the call.
From Python, with pip install apify-client (version 3.x):
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("brenton8907/domain-intel-check").call(run_input={"domains": ["stripe.com", "jane@figma.com"]})rows = client.dataset(run.default_dataset_id).list_items().items
Clay: add it as a column (any Clay plan)
Clay's native Apify integration is included in all Clay plans. You connect your own Apify account.
- In your table, Add enrichment → search "Apify" → Run Apify Actor.
- Connect your Apify account with your API token from the Integrations page in Apify Console.
- Choose the actor
brenton8907/domain-intel-check. - In Input Data, enter
{"domains": [<Domain column>]}, inserting your email or domain column as the token. Put the key in quotes but not the column token; Clay's docs ask for it this way. Email addresses work as-is, so there's no need to extract the domain first. - Run it on one row, open the result cell, and add the fields you need as columns. Most
tables want
email_provider,email_security,dmarc_policy,domain_age_years,hosting_provider,maturity_scoreandhint.
Clay's Auto-update and conditional-run settings work as for any other enrichment.
Rows for free mailboxes (gmail.com…) and non-existent domains come back with
charged: false and a hint.
Alternative: Clay HTTP API column (Growth plan and above)
Use Add enrichment → HTTP API:
- Method
POST - URL
https://api.apify.com/v2/acts/brenton8907~domain-intel-check/run-sync-get-dataset-items - Query parameters
token: your Apify API token, stored as a Clay secret.maxTotalChargeUsd:0.01, as a per-row spend ceiling.- Optionally
fields:query,email_provider,email_provider_kind,email_security,dmarc_policy,registered_on,domain_age_years,hosting_provider,cdn,maturity_score,maturity_signals,hint, to keep Clay's field picker short.
- Header
Content-Type: application/json - Body
{"domains": ["{{Email}}"]}. Replace{{Email}}with your email or domain column; both work, so there's no need to extract the domain first.
The response is a one-element array; map fields from item 0.
For hundreds of rows, one batch run with every value in domains is faster and cheaper on
Clay credits than a call per row. Join the output back on query, which echoes your input
exactly as you sent it.
Weekly monitoring: schedule it and diff by date
- In Apify Console, save your input (the domain list) as a Task.
- Open the Task's Schedule and choose weekly.
- Each run writes a new dataset. Every row carries
checked_at(UTC, when that domain was checked), so two weeks of the same domain can be compared directly.
What's worth diffing week to week:
email_provider: a move to Google Workspace or M365, or a gateway addeddmarc_policy:none→quarantine/rejectmeans a security project is under waytls_expires_on: a certificate about to lapsehosting_provider/cdn: an infrastructure migrationmta_sts,bimi: new email-security spendtxt_verified_services: new SaaS tools verified
To get the latest rows into a sheet, use Apify's Google Sheets integration on the Task, or fetch
https://api.apify.com/v2/actor-tasks/<TASK_ID>/runs/last/dataset/items?format=csv&token=….
Output
| Field | Example | Notes |
|---|---|---|
checked_at | 2026-10-12T19:26:41Z | When this row's checks finished, in UTC. It's on every row, including errors, for diffing scheduled runs. |
maturity_score | 92 | 0–100. The weights are below. |
maturity_signals | ["domain registered 31.1 years ago", "uses google workspace", "DMARC p=reject enforced", "EV certificate (organisation validated)"] | |
email_provider | google_workspace, microsoft_365, proofpoint, self_hosted, no_mx … | Read from MX records. |
email_provider_kind | mailbox · gateway · forwarder · self_hosted · none · unknown | |
email_security | enforced · partial · monitoring · spf_only · none | The DMARC/SPF posture in one word. |
dmarc_policy / dmarc_pct | reject / 100 | |
spf_all | fail (-all), softfail (~all) … | |
spf_senders | ["google", "hubspot", "zendesk", "postmark"] | Services allowed to send mail as the domain. |
dkim_selectors_found | ["google", "s1", "s2"] | |
mta_sts | enforce · testing · none · policy_unreachable · policy_invalid · absent | Whether inbound mail must use TLS. Read from the published policy file, not just the DNS record, and checked against RFC 8461: the version, a mode, max_age, and at least one mx unless the mode is none. When the DNS record exists but the policy can't be used, mail servers ignore it. policy_unreachable means the policy file couldn't be fetched; policy_invalid means it was fetched but is incomplete. |
tls_rpt | true | Publishes TLS failure reporting. |
bimi / bimi_vmc | true / true | Brand logo in the inbox. bimi_vmc means a Verified Mark Certificate, a paid trademark check (paypal.com, cnn.com). |
txt_verified_services | ["atlassian", "docusign", "microsoft_365", "slack", "stripe"] | SaaS tools whose domain-verification record is published. |
registered_on / domain_age_years | 1995-09-12 / 31.1 | The age of the domain, not the company. A bought domain carries its original date: cal.com reads 1997 and vercel.com 1999. |
registrar / registrant_org | MarkMonitor Inc. / British Broadcasting Corporation | The organisation only, and only when it is published. |
tls_valid / tls_cert_type | true / EV | The type comes from the certificate's CA/Browser Forum policy ID, not a guess from the issuer name. |
tls_issuer / tls_subject_org / tls_days_to_expiry | DigiCert, Inc. / Stripe, LLC / 64 | |
cdn / cdn_source / hosting_platform | fastly / asn / shopify | The CDN is read from response headers. If the headers name none, it falls back to the hosting network when that network is a CDN (nytimes.com sends no Fastly header but sits on Fastly). cdn_source says which. AWS addresses are never assumed to be CloudFront, because the same network also carries plain servers. |
web_host | www.toyota.co.jp | The host the website checks ran on. It falls back to www. when the bare domain has no address. |
redirects_to_https / hsts_max_age / security_headers_present | true / 63072000 / [...] | |
hosting_provider / hosting_asn / hosting_asn_org | aws / 16509 / Amazon.com, Inc. | The network serving the domain's IP address. own_network means the company announces its own address space (accenture.com on AS3573), which few companies do. |
dns_provider / dnssec / has_ipv6 / caa_issuers | aws_route53 / true / true / ["digicert.com"] | |
hint | Set whenever an answer needs a caveat. Read it. | |
charged | true | Whether this row was billed. |
Raw records (mx_hosts, spf_record, dmarc_record, nameservers) are included, so you
can check any classification yourself.
Read these before trusting a column
email_provider comes from MX, never from SPF. SPF lists who may send mail as the
domain, which includes every marketing and transactional tool, not who receives it. A test
version that read SPF reported Amazon SES as Pfizer's mail provider. SPF goes into
spf_senders instead, where it's accurate and useful.
A security gateway is reported as the gateway. When MX points at Proofpoint, Mimecast or
Cisco, the mailbox behind it is hidden. We return proofpoint / gateway rather than a guess.
"Uses Proofpoint" is a strong signal in its own right: it implies an enterprise security budget.
no_mx is an answer, not an error. About 28% of a real prospect list has no MX record,
and most of those domains still serve a website. Companies often split their web and mail
domains: notion.so has no MX, and Notion's mail runs on makenotion.com.
No DKIM found isn't proof there's no DKIM. DKIM keys sit under selector names that can't be
listed from DNS. The actor tries 12 common selectors and reports how many it checked. Add your
own in extraDkimSelectors.
hosting_provider is whoever serves the address, not the origin behind it. With a CDN in
front, it's the CDN: paypal.com shows fastly. It's read from the IPv4 address of the bare
domain, so a site that serves only from www. may show a different network there. When the
address has no BGP origin, or the ASN service returns something unexpected, the hosting
columns are left empty and hint says which happened.
txt_verified_services means "verified at some point". A verification token can outlive
the subscription.
Maturity score
| Component | Points |
|---|---|
| Domain age ≥10 years / ≥5 / ≥2 | 20 / 15 / 8 |
| Mail behind a security gateway / on Google Workspace or M365 / any other real mailbox | 15 / 12 / 6 |
| DMARC enforced (quarantine or reject at 100%) / partial / monitoring only | 15 / 10 / 5 |
SPF ends in -all or ~all | 5 |
| DKIM key found | 5 |
| Valid TLS certificate | 10 |
| … that is OV or EV (organisation validated) | +10 |
| HTTP redirects to HTTPS with HSTS / without HSTS | 10 / 5 |
| Behind a CDN (by headers or hosting network) | 5 |
| 3 or more security headers | 5 |
MTA-STS and BIMI appear in maturity_signals but carry no points, so scores stay comparable
with earlier runs.
"Couldn't check" isn't scored as "doesn't have". Three components depend on a check that can fail to get an answer:
- domain age (some registries, like DENIC for .de, publish no creation date)
- TLS (port 443 timed out)
- the website (the homepage timed out)
When one of those can't be measured, it's listed in maturity_unmeasured and left out of the
score: the score becomes the share of the measurable points earned. A definite answer still
counts against the domain: a refused connection on port 443, a name that doesn't resolve, or a
failed TLS handshake all score 0.
Pricing
| Event | Price | When |
|---|---|---|
domain-intel | $0.003 | One domain enriched. |
Not charged:
- invalid input: a company name, a public suffix such as
co.uk, an IP address, or a malformed domain such asstripe..com. Typos are rejected with the reason, never "corrected" into someone else's domain. - free mailbox domains
- domains that don't resolve
- any row that ends in an error, including a DNS lookup that every resolver refused or failed. That is reported as an error, never as "no MX" or "no DMARC"
Every row says whether it was charged in charged.
Coverage
- Registration data comes from RDAP (the IANA bootstrap list) and falls back to WHOIS for TLDs without RDAP. In testing that included .io, .co, .so and .jp. Older .co.jp names publish the registrant organisation but no creation date.
- Some registries publish no creation date at all (DENIC for .de, for example). Those rows have a null age and say so.
- The registrant organisation is often redacted under GDPR. It is shown only when a real organisation is published. Privacy-service placeholders and personal names, emails and phone numbers are never returned.
Limitations
- Email-provider detection matches known MX hostnames. A provider that doesn't appear in the
list is reported as
other, with the rawmx_hostsalongside so you can classify it yourself.