Bulk DMARC, SPF & DKIM Checker + Email Provider & SaaS Finder
Pricing
from $0.80 / 1,000 domain checkeds
Bulk DMARC, SPF & DKIM Checker + Email Provider & SaaS Finder
Check thousands of domains for email security in one run: MX records and mail provider (Google Workspace, Microsoft 365...), SPF with lookup count, DKIM selectors, DMARC policy, BIMI, MTA-STS, TLS-RPT, a 0-100 grade with fixes, and SaaS tools from DNS verification records. USD 1 per 1,000 domains.
Pricing
from $0.80 / 1,000 domain checkeds
Rating
0.0
(0)
Developer
JT Palms
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 days ago
Last modified
Categories
Share
Bulk DMARC, SPF and DKIM Checker + Email Provider and SaaS Finder
Paste a list of domains (or email addresses, or URLs) and get one row per domain with its email security setup: the mail provider (Google Workspace, Microsoft 365 and others), any security gateway in front of it, SPF with its DNS lookup count, DKIM keys found, the DMARC policy, BIMI, MTA-STS and TLS-RPT, a 0-100 grade with plain-English fixes, and the SaaS tools the domain has verified in DNS (Atlassian, Stripe, DocuSign, Zapier, OpenAI and about 70 more).
Everything comes from public DNS records that the domain owner publishes. Nothing is scraped, no mail server is contacted and no mailbox is checked.
USD 1 per 1,000 domains, plus a tiny start fee per run (see Pricing). Invalid inputs and domains that do not exist are free.
What people use it for
- MSP and IT security prospecting. Find prospects on Microsoft 365 or Google Workspace with no DMARC, or DMARC stuck at
p=none. That is a standard, concrete opener for a security conversation, and thefixescolumn tells you exactly what to offer. Turn ononlyProblemsto get only the domains that need work. - Deliverability pre-flight before a campaign. Check your own sending domains and your clients' domains before every send: Gmail and Yahoo require SPF, DKIM and DMARC from bulk senders, and SPF breaks silently when it needs more than 10 DNS lookups.
- Vendor and supplier risk checks. See which suppliers protect their domain against spoofing (DMARC
reject) and which could be impersonated in an invoice fraud email. - Sales targeting and routing. Use the mail provider, the sending services in SPF (HubSpot, Salesforce, SendGrid, Mailchimp...) and the DNS-verified SaaS tools as firmographic signals.
Sample output
Real DNS answers on 2026-10-05 (default settings):
| domain | grade | mailProvider | securityGateway | dmarcPolicy | spfAll | spfLookupCount | dkimSelectorsFound | MTA-STS | TLS-RPT | SaaS found |
|---|---|---|---|---|---|---|---|---|---|---|
| shopify.com | 92 | Google Workspace | reject | ~all | 4 | google, mail, pm | no | no | 23 | |
| microsoft.com | 100 | Microsoft 365 | reject | -all | 7 | selector2 | yes | yes | 16 | |
| github.com | 87 | Microsoft 365 | quarantine | ~all | 10 | google, selector1, k1, k2, k3, s1, s2, cm | no | no | 16 | |
| ford.com | 92 | Proofpoint | reject | ~all | 2 | k2, k3, s1, s2, dkim | no | no | 28 | |
| crawlee.dev | 35 | missing | missing | 0 | none found | no | no | 1 |
crawlee.dev gets 35 because it has no DMARC (-30), no SPF (-25) and no DKIM key among the common selectors (-10). It has no MX record, so MTA-STS and TLS-RPT are not counted against it.
One full row (shopify.com; dnsVerifiedServices trimmed to 10 of the 23 found):
{"input": "shopify.com","domain": "shopify.com","acceptsMail": true,"mx": [{ "host": "aspmx.l.google.com", "priority": 1 },{ "host": "alt1.aspmx.l.google.com", "priority": 5 },{ "host": "alt2.aspmx.l.google.com", "priority": 5 },{ "host": "alt3.aspmx.l.google.com", "priority": 10 },{ "host": "alt4.aspmx.l.google.com", "priority": 10 }],"mailProvider": "Google Workspace","mailProviderSource": "mx","securityGateway": null,"spfRecord": "v=spf1 include:_spf.google.com include:mail.zendesk.com include:sendgrid.net ~all","spfCount": 1,"spfAll": "~all","spfLookupCount": 4,"spfIncludes": ["_spf.google.com", "mail.zendesk.com", "sendgrid.net"],"spfServices": ["Google", "Zendesk", "SendGrid"],"spfErrors": [],"dmarcRecord": "v=DMARC1; p=reject; pct=100; fo=1; rua=mailto:...;ruf=mailto:...","dmarcPolicy": "reject","dmarcSubdomainPolicy": null,"dmarcPct": 100,"ruaDomains": ["shopify.com"],"dmarcAlignment": { "dkim": "relaxed", "spf": "relaxed" },"dkimSelectorsFound": ["google", "mail", "pm"],"dkimKeys": [{ "selector": "google", "keyType": "rsa", "bits": 1024 },{ "selector": "mail", "keyType": "rsa", "bits": 1024 },{ "selector": "pm", "keyType": "rsa", "bits": null }],"bimiPresent": true,"bimiLogo": "https://vmc.digicert.com/8833b699-1227-41ee-b185-cc2d9a08e213.svg","bimiVmc": true,"mtaStsPresent": false,"mtaStsMode": null,"tlsRptPresent": false,"dnsVerifiedServices": ["Microsoft 365", "Google", "Atlassian", "DocuSign", "Stripe", "Zapier", "Klaviyo", "OpenAI", "Facebook (Meta)", "Apple"],"grade": 92,"fixes": ["Publish an MTA-STS policy", "Publish a TLS-RPT record"],"checkedAt": "2026-10-05T16:59:37.155Z","error": null}
What it checks
Since February 2024, Gmail and Yahoo Mail require senders of about 5,000 or more messages a day to their users to publish SPF, DKIM and a DMARC record (p=none is enough to start), and every sender needs at least SPF or DKIM. These are the records this actor reads:
- MX and mail provider. The MX hosts and priorities, matched against a dated table of providers (Google Workspace, Microsoft 365 including the newer
*.mx.microsofthosts, Zoho, Proton, Fastmail, Yahoo, GoDaddy, IONOS, OVHcloud and others) and of security gateways (Proofpoint, Mimecast, Barracuda, Cisco Secure Email, Broadcom/Symantec and others). A null MX (0 .) means the domain accepts no mail. - SPF. The
v=spf1record, how many there are (more than one is an error), how it ends (-all,~all,?all,+all, ornone), and the DNS lookups a receiver must make, counted the way RFC 7208 does:include,a,mx,ptr,existsandredirecteach cost one, nested includes are followed, loops are caught, and more than 10 is an error. Includes are mapped to sending services (SendGrid, Mailgun, Amazon SES, Mailchimp, HubSpot, Salesforce, Zendesk and others). - DMARC. The
_dmarcrecord: policy (none,quarantine,reject), subdomain policy,pct, DKIM and SPF alignment, and the domains that receive the aggregate reports (ruaDomains, which often names the DMARC vendor). - DKIM. About 27 common selectors are tried (google, selector1 and selector2 for Microsoft 365, k1 to k3, s1 and s2, default, dkim, mail, zoho, protonmail, fm1 to fm3, mandrill, amazonses, mailjet and more) plus any you add. Each key found is reported with its type and size. Revoked keys (empty
p=) and wildcard answers are not counted. - BIMI. The
default._bimirecord, the logo URL and whether a certificate (VMC) is published. - MTA-STS. The
_mta-stsrecord. WithcheckMtaStsPolicyon, the policy file is read to get its mode (enforce, testing or none). - TLS-RPT. The
_smtp._tlsrecord for TLS failure reports. - SaaS from DNS verification records. TXT records such as
MS=,atlassian-domain-verification,stripe-verificationordocusign=show which tools the company has verified its domain with. Only the tool names are output, never the tokens.
Records are recognised by their version prefix only. Some domains answer every unknown name with a wildcard (shopify.com returns SPF, BIMI and DMARC strings at _mta-sts.shopify.com); those strings are correctly ignored.
The grade
Every domain starts at 100. Points come off for:
| Problem | Points |
|---|---|
No DMARC record (or an invalid one: several records, or no valid p=) | -30 |
DMARC p=none | -15 |
DMARC p=quarantine | -5 |
| No SPF record | -25 |
| More than one SPF record | -15 |
SPF ends in +all | -25 |
SPF ends in ?all, or has no all at all (same meaning) | -10 |
| SPF needs more than 10 DNS lookups | -10 |
| No DKIM key found among the common selectors | -10 |
| No MTA-STS record | -5 |
| No TLS-RPT record | -3 |
| BIMI | information only |
The lowest possible grade is 2. fixes lists what to do, largest deduction first, then information-only notes (MTA-STS still in testing mode, DMARC pct under 100, DKIM keys shorter than 1024 bits, a policy file that could not be read).
Two rules keep parked domains fair: a domain with no MX hosts (a null MX, or no MX at all) is not penalised for missing MTA-STS or TLS-RPT, which protect incoming mail; and a domain whose SPF record is exactly v=spf1 -all (it authorises no sender) is not penalised for missing DKIM. A correctly parked domain such as example.com scores 100.
Input
| Field | What it does |
|---|---|
domains | Domains, email addresses or URLs, one per line. Each is reduced to its registered domain with the Public Suffix List (https://www.python.org/downloads/ becomes python.org, mail.example.co.uk becomes example.co.uk). For an email address only the part after the @ is used. Duplicates are checked once. Invalid entries get a row with an error and are free. |
maxDomains | Check at most this many unique domains (default 10,000). Domains past the limit are skipped and not charged. |
extraDkimSelectors | Your own DKIM selector names to try on every domain, for example custom1 (up to 50). |
includeSaasDetection | On by default. Maps TXT verification records to tool names in dnsVerifiedServices. |
checkMtaStsPolicy | Off by default. For domains with an MTA-STS record, one HTTPS request to https://mta-sts.<domain>/.well-known/mta-sts.txt to read the mode. |
onlyProblems | Off by default. Output only domains with a grade under 70. Domains with 70 or more are checked but left out and not charged. |
concurrency | Domains checked at the same time (default 20, up to 50). |
Output fields
| Field | Meaning |
|---|---|
input, domain | What you entered (an email address is shown as (email) domain.com, never in full) and the registered domain checked. |
acceptsMail | true with MX hosts, false with a null MX, or with no MX and no A record; null with no MX but an A record (mail servers may then try that address, so it is unknown). |
mx | MX hosts with priorities, lowest priority first. |
mailProvider, mailProviderSource | The mailbox provider. mailProviderSource is mx when it comes from the MX hosts, or spf when the MX is a security gateway and the SPF record includes Microsoft 365 or Google. Other means an MX host not in the table (often self-hosted); null means no provider could be named. |
securityGateway | The inbound filtering service in the MX, if any (Proofpoint, Mimecast...). |
spfRecord, spfCount, spfAll | The SPF record, how many SPF records exist, and how it ends (-all, ~all, ?all, +all, none, or null without SPF). With redirect=, the ending of the redirected record is used. |
spfLookupCount, spfIncludes, spfServices, spfErrors | DNS lookups SPF needs, the include and redirect targets in the domain's own record, the sending services found anywhere in the include tree, and problems (over 10 lookups, loops, missing include targets, several records). |
dmarcRecord | The DMARC record, with every mailto: address replaced by mailto:.... |
dmarcPolicy, dmarcSubdomainPolicy, dmarcPct, dmarcAlignment | Parsed DMARC settings. dmarcPct is null when the record has no pct tag. Alignment is relaxed unless the record says s (strict). |
ruaDomains | Domains that receive the aggregate reports (never the addresses). |
dkimSelectorsFound, dkimKeys | Selectors with a published key, and each key's type (rsa or ed25519) and size in bits (null when the key cannot be parsed). |
bimiPresent, bimiLogo, bimiVmc | BIMI record with a logo, the logo URL, and whether a certificate (a=) is published. A record with an empty logo (a BIMI opt-out) counts as not present. |
mtaStsPresent, mtaStsMode | MTA-STS record found; the policy mode only with checkMtaStsPolicy. |
tlsRptPresent | TLS-RPT record found. |
dnsVerifiedServices | SaaS tools from TXT verification records (names only). |
grade, fixes | The 0-100 grade and what to fix, in order. |
checkedAt, error | When the domain was checked, and why a row has no data (domain does not exist, an invalid input, or a DNS failure). |
The run's key-value store also holds a SUMMARY record with counts (checked, billed, not existing, DNS failures, left out by onlyProblems) and DNS statistics.
Pricing
| What | Price |
|---|---|
| Domain checked (one row with all checks and a grade) | USD 0.001 (USD 1 per 1,000) |
| Run start | USD 0.00005 per run |
Invalid input, domain does not exist, DNS failure, domains past maxDomains, domains left out by onlyProblems | Free |
Worked examples on the free plan:
- The default input (3 domains): 3 x 0.001 + 0.00005 = USD 0.00305.
- 1,000 prospect domains: about USD 1.00.
- 10,000 domains with
onlyProblemson, of which 3,200 grade under 70: 3,200 x 0.001 = USD 3.20 (plus the start fee).
Higher Apify plans get a discount on the per-domain price (10% on Silver, 20% on Gold and above). You can set a maximum cost per run in the run options: the actor checks no more domains than that budget can pay for, stops cleanly when it is reached, and keeps every row written so far.
Schedule it weekly. Save your list as a task and schedule it: you will see when a prospect moves from p=none to reject, when a domain changes mail provider, or when someone breaks their SPF.
How it queries DNS
- About 35 to 40 small DNS queries per domain, most of them DKIM selector guesses. Answers that many domains share (such as
_spf.google.com) are cached for the run. - The container's own resolver answers first. Only after a timeout or a server failure is a query asked once more, after a short back-off, at a public resolver (Cloudflare 1.1.1.1 or Quad9 9.9.9.9, taken in turn). Definite answers (the name does not exist) are never retried.
- All queries share one rate limit (250 per second, at most 64 in flight; the public fallback resolvers get their own lower limit), so 1,000 domains take roughly 2 to 3 minutes.
- Per-query timeout 5 seconds.
Limits and honesty
- DKIM selectors cannot be listed. DNS has no way to ask "which DKIM keys does this domain have", so the actor tries common selector names. "None found" is not proof that a domain has no DKIM; its selector may have a custom name. Add known selectors in
extraDkimSelectors. - Registered domains only. Subdomains are reduced to their registered domain (
mail.example.comis checked asexample.com), so a subdomain with its own SPF or DMARC record is not checked separately. - A snapshot. Each row shows the DNS answers at
checkedAt. Records change; schedule runs to track them. - Provider and SaaS tables are dated (2026-10-05) and cover the common services. An unknown MX host shows as
Other; an unknown TXT record is simply not listed. - The mail provider comes from the MX hosts. Behind a gateway it is inferred from SPF only when SPF includes Microsoft 365 or Google; otherwise it stays
null. - DNS failures are free. If a domain's name servers time out or fail even after the retry, its row says so in
errorand it is not charged; run it again later.
Privacy
- No mailbox checks, no SMTP connections, no address verification.
- No email address is ever output. Email inputs are reduced to their domain (the
inputcolumn shows(email) domain.com), DMARC report addresses are reduced to domains, and anymailto:address in a record is masked. - Verification tokens in TXT records are never output, only the tool names.
What this does not do
- It reads published DNS records only (plus, if you turn it on, the public MTA-STS policy file). It does not send mail, connect to mail servers, test inbox placement, or verify that an email address exists.
- It does not read DMARC reports or tell you who is sending mail as the domain.
- It does not validate DKIM signatures or SPF results for real messages; it checks the published setup.
- It does not check blacklists or IP reputation.
- It does not visit the domain's website; the only web request is the optional MTA-STS policy file (see Related actors for website checks).
Related actors
- Bulk WHOIS Lookup (RDAP): Domain Availability & Expiry Checker: WHOIS lookup for thousands of domains through RDAP, the official successor to WHOIS: available or registered, registrar, creation date,...
- Company Enrichment From Domain: Tech Stack, Socials, Hiring: Company enrichment from a list of website domains: company name, description, official social links, tech stack (CMS, ecommerce,...
- Tech Stack Detector: Website Technology Lookup in Bulk: Website technology lookup in bulk: the CMS, ecommerce platform, analytics, frameworks, CDN, hosting, payment, email and marketing tools...
- Domain Authority Checker: Backlink Rank from Open Data: Bulk domain authority checker built on open data: website authority and backlink strength from the Majestic Million (referring subnets...
FAQ
Why is "no DKIM found" only -10 points? Because the actor can only guess selector names. A domain may sign every message with a selector named after a date or a vendor ID.
Why did a well-known company get a low grade? The grade measures published protections, not the company. Many large companies still run DMARC at p=none or have no MTA-STS.
Can I check 100,000 domains? Yes. Raise maxDomains (default 10,000) and the run timeout (default 1 hour): at the shared rate limit, 10,000 domains take roughly 25 minutes and 100,000 roughly 4 hours.
Something missing or wrong? Open an issue on the actor page with the domain.