Domain Health Checker: DNS, SPF, DKIM, DMARC, SSL & Headers avatar

Domain Health Checker: DNS, SPF, DKIM, DMARC, SSL & Headers

Pricing

from $2.24 / 1,000 domain checkeds

Go to Apify Store
Domain Health Checker: DNS, SPF, DKIM, DMARC, SSL & Headers

Domain Health Checker: DNS, SPF, DKIM, DMARC, SSL & Headers

Check domain health in bulk: DNS records, SPF (with lookup count), DMARC policy, DKIM on common selectors, TLS certificate expiry and security headers. One flat row, issue list and 0-100 health score per domain. Public DNS plus one HTTPS GET. Pay per domain checked.

Pricing

from $2.24 / 1,000 domain checkeds

Rating

0.0

(0)

Developer

Data Done Right

Data Done Right

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

Domain Health Checker checks a list of domains in bulk and returns one flat row per domain: DNS records, SPF (with the DNS lookup count), DMARC policy, DKIM keys under common selectors, TLS certificate expiry and security headers, plus an issue list and a 0 to 100 health score.

What this does NOT do. It does not send any email and does not talk to mail servers. DKIM is checked on about 20 common selector names only, so "not found" never means "no DKIM". DMARC is read at _dmarc.<your domain> only; there is no fallback to a parent domain. Security headers come from one plain HTTPS GET of the home page (no browser, no login, no bot-protection workarounds); sites that refuse the request are reported as blocked and not judged. It is not a vulnerability scanner, a blocklist or reputation check, or a WHOIS tool, and it does not scan ports.

What you get

  • One row per domain with healthScore, issues[] (code, severity, message) and the raw values behind them.
  • Email authentication: spfStatus, spfPolicy, spfLookups, dmarcPolicy, dmarcPct, report addresses, dkimSelectorsFound, MX hosts.
  • Web security: tlsStatus, issuer, expiry date and days left, HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy.

Typical use: audit client or portfolio domains, find certificates that are about to expire, check SPF/DMARC before a campaign, or add a quick domain check to an AI agent or automation. Works through the Apify API, CSV/Excel/JSON export and as an MCP tool.

How to check SPF, DKIM and DMARC for many domains

  1. Paste the domains into Domains, one per line (URLs and emails are reduced to the host name).
  2. Leave Check TLS certificate and Check security headers off if you only want email authentication; this makes the run faster.
  3. Start the run and read spfStatus, dmarcStatus, dmarcPolicy and dkimSelectorsFound in the Email authentication view.
  4. Filter on issues for the problems (for example spf-missing, dmarc-policy-none, spf-too-many-lookups).

If your mail service uses its own DKIM selector, add it under Extra DKIM selectors (the selector is the part before ._domainkey in the DNS name).

How to check SSL certificate expiry for a list of domains

Turn Check DKIM and Check security headers off, paste your domains and run. tlsStatus, tlsExpires and tlsDaysLeft are in the TLS and headers view. Certificates that expire within 30 days raise a tls-expires-soon issue (high at 14 days or less). Expired, self-signed and wrong-host certificates are reported with their own status. The check connects to port 443 of the domain itself; subdomains such as shop.example.com are checked as given.

How to audit security headers for a website

Turn Check DKIM off, keep Check security headers on and run. The Actor sends one HTTPS GET to https://<domain>/, follows up to 5 redirects, and reports the six headers listed above for the final response. A missing header becomes an issue (HSTS and CSP medium, the others low). A CSP with frame-ancestors counts as clickjacking protection, so a missing X-Frame-Options is then not flagged.

Input

{
"domains": ["python.org", "github.com", "example.com"],
"checkDkim": true,
"checkTls": true,
"checkHeaders": true,
"maxDomains": 100
}
FieldDefaultWhat it does
domains3 sample domainsDomains to check, one per line. URLs and email addresses are reduced to the host name. Required.
maxDomains100Maximum domains per run (1 to 10,000); caps the cost.
checkDkimtrueLook up DKIM keys under about 20 common selectors.
extraDkimSelectorsemptyYour own selector names, tried in addition to the common ones.
checkTlstrueRead the TLS certificate on port 443.
checkHeaderstrueOne HTTPS GET for the security headers.
dnsResolverpublicpublic (Cloudflare, Google, Quad9), cloudflare, google, quad9 or system.
concurrency5Domains checked in parallel (1 to 20).
timeoutSecs15Timeout for the TLS handshake and the HTTPS request (3 to 60).

Output

Real output of a local run for github.com (shortened):

{
"input": "github.com",
"domain": "github.com",
"status": "ok",
"healthScore": 97,
"issueCount": 1,
"issues": [{"code": "missing-permissions-policy", "severity": "low", "message": "Response has no permissions-policy header"}],
"mxRecords": ["0 github-com.mail.protection.outlook.com"],
"hasMx": true,
"spfStatus": "valid",
"spfPolicy": "softfail",
"spfLookups": 10,
"dmarcStatus": "valid",
"dmarcPolicy": "quarantine",
"dkimStatus": "found",
"dkimSelectorsFound": ["google", "selector1", "k1", "k2", "k3", "s1", "s2", "zendesk1", "zendesk2", "cm"],
"dkimSelectorsChecked": 22,
"tlsStatus": "valid",
"tlsIssuer": "Sectigo Limited",
"tlsExpires": "2027-01-27",
"tlsDaysLeft": 84,
"headersStatus": "ok",
"hsts": "max-age=31536000; includeSubdomains; preload",
"missingSecurityHeaders": ["permissions-policy"],
"dnsResolver": "public",
"checkedAt": "2026-11-04T14:53:04+00:00"
}

Other fields: ipv4, ipv6, nameservers, caaRecords, txtRecordCount, nullMx, spfRecord, dmarcRecord, dmarcSubdomainPolicy, dmarcPct, dmarcReportAddresses, tlsSubject, tlsProtocol, tlsError, httpsStatusCode, httpsFinalUrl, httpsRedirects, csp, xContentTypeOptions, xFrameOptions, referrerPolicy, permissionsPolicy, headersError. The SUMMARY record has counts by status, the average health score and the DKIM selectors tried. Dates and certificate values depend on the day you run it.

Row status: ok, nxdomain (the domain does not exist), invalid (not a domain name), dns-error (DNS failed temporarily, try again), failed (unexpected error). Problem inputs are also listed in the FAILED record.

How the health score works

healthScore = 100 minus 20 for each high issue, 8 for each medium and 3 for each low (never below 0). It is a transparent checklist, not a security rating, and it is not comparable with other tools' scores. Every deduction is visible in issues.

AreaIssue codes (severity)
SPFspf-missing (high if the domain has MX, else low), spf-multiple-records (high), spf-pass-all (high), spf-neutral and spf-none (medium), spf-too-many-lookups (high, more than 10)
DMARCdmarc-missing (high if the domain has MX, else low), dmarc-invalid and dmarc-multiple-records (high), dmarc-policy-none (medium), dmarc-pct-below-100 and dmarc-no-reporting (low)
DKIMdkim-not-found (low, only for domains with MX)
DNScaa-missing (low)
TLStls-expired, tls-hostname-mismatch, tls-self-signed, tls-untrusted, tls-not-yet-valid (high), tls-expires-soon (high at 14 days or less, medium at 30), https-unreachable (medium)
Headersmissing-strict-transport-security and missing-content-security-policy (medium), the other four (low)

Notes on accuracy:

  • spfLookups counts include, a, mx, ptr, exists and redirect terms (RFC 7208) and follows include/redirect (at most 12 fetches, spfLookups can then be a lower bound). It does not expand the hosts behind an mx term.
  • tlsStatus: untrusted can also mean a certificate higher up the chain failed validation on the machine running the Actor; the error text says so and gives the site certificate's own expiry date.
  • Domains without A/AAAA records get no-web-host and skip the TLS and header checks.

How much does it cost

One event, domain-checked: $0.0028 per domain with a DNS verdict ($2.80 per 1,000). Not charged: invalid inputs, dns-error rows (temporary DNS failures), failed rows and duplicates. A domain that does not exist (nxdomain) is charged, because that is a definite answer.

DomainsCost
1,000$2.80
10,000$28.00
100,000$280.00

Set maxDomains or a spending limit on the run to cap the bill; the Actor stops cleanly when the limit is reached.

Use cases

  • Audit the email authentication of client domains before a mail migration or campaign.
  • Monitor certificate expiry across a portfolio of domains (run it on a schedule).
  • Find domains with no DMARC, a p=none policy or a broken SPF record.
  • Compare security headers across your own sites or after a hosting change.
  • Give an AI agent a one-call "is this domain set up properly" check.

FAQ

Does it prove a domain has no DKIM? No. DKIM keys can only be found by selector name and the selector is the sender's choice. About 20 common ones are tried (google, selector1, selector2, k1, default, s1, mandrill and others); add your own under Extra DKIM selectors. dkimStatus: not-found-in-common-selectors is a hint, and it is only a low-severity issue.

Which DNS servers are used? Public resolvers (Cloudflare, Google, Quad9 in turn), or the platform default if you choose system. Very large lists can hit resolver rate limits; failures show as dns-error, are not charged, and can be re-run.

Does it check the parent domain for DMARC? No. For mail.example.com it reads _dmarc.mail.example.com only, even though receivers may fall back to the organisational domain. Check the registered domain too.

Can it check internal or private hosts? No. Hosts that resolve to private, loopback or link-local addresses are refused, for both the TLS and the HTTP check (blocked).

Why does a site show headersStatus: blocked? The site answered 401, 403, 429 or 451 to a plain request. The Actor does not work around bot protection, so it does not judge those headers.

Does it test cipher suites, TLS versions or vulnerabilities? No. It reports the negotiated TLS version and the certificate only.

Does it follow redirects from http to https? No. It requests https://<domain>/ only and does not test the plain-HTTP redirect.

Use with the Apify API, MCP, n8n and Make

Python:

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("YOUR_USERNAME/domain-health-checker").call(run_input={"domains": ["example.com", "python.org"]})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["domain"], row["healthScore"], [i["code"] for i in row["issues"]])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('YOUR_USERNAME/domain-health-checker').call({ domains: ['example.com', 'python.org'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((r) => [r.domain, r.healthScore, r.tlsDaysLeft]));

In n8n or Make use the Apify node/module "Run Actor", pass domains and read the dataset items. For AI agents the Actor is available through the Apify MCP server; the input is one domains array.

  • Verify Email Addresses in Bulk: Syntax, MX & Disposable (check the mailboxes behind the domains)
  • HTTP Status Code Checker: Bulk URL, Website & Redirect Chains
  • Domain Age Checker: Registration Date, Expiry & RDAP Lookup
  • Website Technology Checker: CMS, WordPress & Tracking Pixels