SPF, DKIM & DMARC Checker: Bulk Domain Email Health Score avatar

SPF, DKIM & DMARC Checker: Bulk Domain Email Health Score

Pricing

from $0.75 / 1,000 domain checkeds

Go to Apify Store
SPF, DKIM & DMARC Checker: Bulk Domain Email Health Score

SPF, DKIM & DMARC Checker: Bulk Domain Email Health Score

SPF, DKIM and DMARC checker for domains in bulk: MX, SPF (with the 10-lookup limit), DMARC, DKIM, MTA-STS, TLS-RPT and BIMI, scored 0-100 with a concrete fix for each problem. Pay per domain.

Pricing

from $0.75 / 1,000 domain checkeds

Rating

0.0

(0)

Developer

LYFE Offshore

LYFE Offshore

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

15 days ago

Last modified

Share

Bulk SPF, DKIM and DMARC checker for email deliverability: give it a list of domains and it checks the email setup in DNS and returns a score from 0 to 100, what is wrong, and the fix: MX, SPF (including the 10-lookup limit that quietly breaks big records), DMARC, DKIM, MTA-STS, TLS-RPT and BIMI. Only DNS, plus one request to the domain's own MTA-STS policy file. No third-party service, nothing that can break when a vendor changes its site.

One run, real output

Eight domains, run locally on 4 October 2026 (DNS answers change; yours will be current):

DomainStatusScoreMail hostSPF endsSPF lookupsDMARCDKIM keys foundMTA-STS
google.comchecked93Google Workspace~all1rejectnone of the 28 triedenforce
github.comchecked84Microsoft 365~all10 of 10quarantinegoogle, selector1, k1, k2, k3, s1, s2, cm-
stripe.comchecked83Google Workspace~all7rejectgoogle, s1, s2, mandrill, cm-
shopify.comchecked86Google Workspace~all4rejectgoogle, mail-
mozilla.orgchecked86Google Workspace~all7rejectgoogle-
lyfeoffshore.comchecked57Google Workspace~all1nonegoogle-
example.comnull_mx84none (null MX)-all0rejectrevoked keys only-
notarealdomain-xyz-12345.comno_domain-------

The 7 domains that exist were billed; the made-up one was free. The row for lyfeoffshore.com carries the finding and the fix, not just a number (see the output example below).

stripe.com gets a warning of its own: its strongest DKIM key is 1024 bits, with the fix "Rotate to a 2048-bit key". github.com sits at exactly 10 of 10 SPF lookups: one more include from any provider and SPF breaks, and the row says so.

What it checks

CheckWhat you get
MXRecords by priority, mail provider recognised from the MX hosts (Google Workspace, Microsoft 365, Proton, Zoho, Mimecast, Proofpoint, Fastmail and others), every MX host must itself resolve, null MX (RFC 7505) recognised, implicit-MX fallback flagged
SPFRecord fetched and parsed. DNS lookups counted through every include and redirect against the limit of 10 (RFC 7208). Flags +all, ?all, a missing all, two SPF records, dead or looping includes, the ptr mechanism and syntax errors
DMARCp, sp, pct, rua, ruf, alignment. A subdomain without its own record is scored on its parent's policy and says so
DKIM28 common selectors tried (google, selector1, selector2, default, k1, s1, ...) plus your own. Key size read from the key; revoked keys and testing mode (t=y) reported. Wildcard *._domainkey records are not mistaken for real selectors
MTA-STSDNS record, and the policy file fetched from https://mta-sts.<domain>/.well-known/mta-sts.txt to read the mode (enforce, testing, none)
TLS-RPT, BIMIDNS records

The score. MX 20, SPF 30, DMARC 30, DKIM 10, and 10 for hardening (MTA-STS, TLS-RPT, BIMI), shown as a percentage. A good setup without MTA-STS and BIMI lands in the high 80s, which is fine; the hardening is a bonus. Every point lost shows up as a finding with severity (critical, warning, info, ok), an explanation and a concrete fix, sorted worst first.

What it does not do

  • It checks the domain's configuration, not whether a mailbox exists. info@company.com can sit on a perfect domain and bounce. For that, use the Catch-All Email Verifier.
  • DKIM cannot be fully discovered. DNS has no list of selectors, and a sender can name its selector anything. A row with no DKIM key found means none of the selectors tried exist, not that DKIM is absent (google.com above is the example: none of the 28 selectors exist there, which says nothing about whether it signs mail). When no key is found, DKIM is left out of the score instead of counted as a failure, and scoreBasis says so. Add your provider's selector in dkimSelectors to check it exactly.
  • No blocklist (DNSBL) check, on purpose. Spamhaus and similar lists refuse queries that come through public resolvers (measured on 4 October 2026 with Spamhaus' own test entry: no answer, or "query refused"). A check built on that would report every domain as clean.
  • It does not send mail, does not probe SMTP ports (Apify blocks them) and does not read DMARC reports.
  • DMARC for a subdomain is looked up on the parent by trimming labels; for domains under public suffixes like co.uk check the registered domain itself.

Input example

{ "domains": ["google.com", "https://stripe.com/pricing", "info@shopify.com"],
"dkimSelectors": ["mycompany1"], "checkMtaStsPolicy": true, "concurrency": 10 }

Domains, URLs and email addresses all work: the domain is taken from them. Duplicates are checked once. You can also point inputDatasetId at a dataset from another Actor; the domain is read from domainField, or else the first of domain, website, url, email.

Output example

One row per domain. A real row for lyfeoffshore.com from a local run on 5 October 2026, with the per-mechanism detail objects (mx, spf, dmarc, dkim, mtaSts, tlsRpt, bimi) left out for length and the findings trimmed to two of four:

{
"domain": "lyfeoffshore.com", "checkedAt": "2026-10-05T17:20:47.205Z",
"status": "checked", "billable": true, "score": 57, "scoreBasis": "all checks",
"mxProvider": "Google Workspace", "spfAll": "softfail", "spfLookups": 1,
"dmarcPolicy": "none", "dkimSelectors": ["google"], "mtaStsMode": null,
"topIssue": "No DMARC record. Anyone can spoof this domain without a policy to stop them, and Gmail and Yahoo require DMARC for bulk senders.",
"findings": [
{ "severity": "critical", "area": "dmarc", "message": "No DMARC record. ...",
"fix": "Publish a TXT record at _dmarc with \"v=DMARC1; p=none; rua=mailto:dmarc@<your domain>\", then tighten the policy." },
{ "severity": "ok", "area": "dkim", "message": "DKIM key found for selector google." }
]
}
FieldMeaning
score0 to 100, see "The score" above; null for domains that were not checked
scoreBasisWhat the score covers (for example, whether DKIM was left out because no key was found)
status / billablechecked, null_mx (receives no mail; still scored), no_domain, invalid_input, dns_error; whether the row was charged
mxProviderMail provider recognised from the MX hosts
spfAll / spfLookupsHow the SPF record ends, and DNS lookups counted through includes (limit 10)
dmarcPolicynone, quarantine or reject
dkimSelectorsSelectors where a DKIM key was found
mtaStsModeenforce, testing, none, or null without MTA-STS
topIssueThe worst finding in one line
findingsEvery finding with severity, area, message and fix, worst first
mx, spf, dmarc, dkim, mtaSts, tlsRpt, bimiFull detail per mechanism

A SUMMARY record holds the run totals (average score, domains without DMARC, SPF over the lookup limit).

Price

Price per 1,000 by your Apify plan (Apify applies the right column automatically):

FreeStarterScaleBusiness and up
Domain checked, per 1,000$2.00$1.40$1.00$0.75

No start fee. The figures below use the Free-plan price; on a paid plan the same run costs less.

Pay per event: $0.002 per domain checked, platform usage included, no start fee.

DomainsCost
1,000$2.00
10,000$20.00

Free: duplicates, invalid input, domains that do not exist, and domains where the resolver did not answer (dns_error). If DNS fails for every domain in a run, the run fails instead of finishing with empty rows. A run's maximum-charge limit caps how many domains are processed.

Use it from code or an AI agent

curl -X POST "https://api.apify.com/v2/acts/lyfe_tools~domain-email-health-check/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"domains": ["lyfeoffshore.com", "stripe.com"]}'

The response is the dataset rows as a JSON array. The Actor also works through the Apify MCP server (https://mcp.apify.com), so AI agents such as Claude or Cursor can call it as a tool: an agent sends domains and reads score, topIssue and findings[].fix.

Part of a lead-list workflow

  1. Find: Local Business Leads (role addresses such as info@, by city and category)
  2. Clean: Email List Cleaner
  3. Verify: Catch-All Email Verifier
  4. Check the domain: SPF, DKIM & DMARC Checker (this Actor)

Use it on your own sending domain before a campaign: missing DMARC or a broken SPF record hurts deliverability no matter how clean the list is. Prospects' domains can be checked too, as a signal (which mail provider, whether DMARC exists), not as proof that an address works. inputDatasetId reads the previous step's dataset, taking the domain from its domain or email column.

Next step: this is the last check in the flow. Fix any critical finding on your sending domain before you send.

FAQ

How do I check SPF, DKIM and DMARC for many domains at once? Put the domains (or URLs, or email addresses) in domains, or pass a dataset in inputDatasetId. Each unique domain gets one row.

Does it count SPF DNS lookups (the 10-lookup limit)? Yes, through every include and redirect, and it flags records at or over the limit.

Why does it say no DKIM key was found when my domain signs mail? Selectors cannot be listed in DNS. Add your provider's selector in dkimSelectors; without a found key, DKIM is left out of the score.

Does it check blacklists (DNSBL)? No, see "What it does not do".

Sources and limits

Public DNS only, about 35 queries per domain (28 of them DKIM selectors), plus one HTTPS request to mta-sts.<domain> when it publishes an MTA-STS record. Results are a snapshot of DNS at the moment of the run. Questions and problems: tools@lyfeoffshore.com.