How to Bulk-Check Email Deliverability: MX, SPF, DKIM
Audit MX, SPF, DKIM, DMARC and BIMI for thousands of domains via DNS-over-HTTPS. Get a parsed policy breakdown and a 0-100 deliverability score per domain.
Since Google and Yahoo tightened their bulk-sender requirements in 2024, a domain’s email authentication posture is no longer a nice-to-have — it’s the difference between the inbox and the spam folder, or an outright rejection. But checking it is tedious. To audit one domain you run a fistful of DNS queries by hand: an MX lookup, a TXT lookup for SPF, a TXT lookup at _dmarc., a probe of every plausible DKIM selector, and a BIMI check. Multiply that across a prospect list of a few thousand domains and it’s a full day of dig commands. This guide covers how to run that whole audit in bulk over DNS-over-HTTPS, what each record tells you, and how the scoring works.
What’s worth extracting
The checker resolves the five pillars of email deliverability per domain and returns one flat row. The fields, grouped by protocol:
- Score —
deliverabilityScore(0–100), agrade(A+ down to F),passCount(how many of the 5 protocols pass), andtotalChecks(always5). - MX —
hasMx,mxRecords(comma-separated priority + hostname),mxCount. - SPF —
hasSpf,spfRaw(the raw TXT value),spfPolicy(parsed enforcement: hardfail, softfail, neutral or fail),spfIncludes(theinclude:domains), andspfLookupCount(how many DNS lookups the record triggers). - DMARC —
hasDmarc,dmarcRaw,dmarcPolicy(none / quarantine / reject),dmarcPct(thepcttag),dmarcRua(aggregate report URI),dmarcRuf(forensic report URI),dmarcSubdomainPolicy(thesptag). - DKIM —
hasDkim,dkimSelectorsFound(selectors with a published key),dkimSelectorsChecked(all 31 probed). - BIMI —
hasBimi,bimiRaw,bimiSvgUrl(the brand logo SVG if present). - Diagnostics —
issues(a human-readable, semicolon-separated problem list),resolver(which DNS resolver answered),checkedAt(ISO 8601 timestamp).
That last field, issues, is what makes the output actionable rather than raw. Instead of eyeballing a TXT record, you get lines like “No DMARC record — no protection against domain spoofing” that you can hand to a non-technical stakeholder.
How the source actually works
There is no scraping and no login here — the tool queries public DNS. Specifically it uses DNS-over-HTTPS (DoH) against Cloudflare (cloudflare-dns.com) with an automatic fallback to Google (dns.google). DoH is just DNS wrapped in HTTPS GET requests, which means it runs anywhere without needing UDP port 53 open, and it’s not rate-limited the way a naive dig loop against a single resolver would be.
For each domain the actor runs a fixed sequence:
- MX — a type
MXquery; parses priority and hostname for each record. - SPF — a type
TXTquery on the apex; finds the record beginningv=spf1, then parses the enforcement mechanism and everyinclude:. - DMARC — a type
TXTquery at_dmarc.<domain>; parses all DMARC tags (p,pct,rua,ruf,sp). - DKIM — a type
TXTquery at<selector>._domainkey.<domain>for 31 common selectors (google, sendgrid, mailgun, microsoft, docusign, and more). - BIMI — a type
TXTquery atdefault._bimi.<domain>; extracts the SVG logo URL.
A minimal input is just a list of domains:
{
"domains": ["stripe.com", "github.com", "mailchimp.com", "shopify.com"],
"maxConcurrency": 10,
"proxyConfiguration": { "useApifyProxy": true }
}
Schemes and paths are stripped automatically, so https://example.com/pricing and example.com both resolve to the same audit. maxConcurrency controls how many domains are queried in parallel — default 10, up to 100 for large lists.
How the score is computed
The deliverabilityScore is a weighted sum, and the weights come straight from the README so you can reason about a result instead of trusting a black box:
- MX = 25 points — mail can be received.
- SPF = 25 points — full credit only for a hardfail policy (
-all); softer policies score lower. - DMARC = 25 points — full credit only for a
rejectpolicy;quarantineandnonescore less. - DKIM = 15 points — at least one selector publishes a key.
- BIMI = 8 points — a BIMI record is present.
- Bonus: +2 — for two or more MX records (redundancy).
So a domain that receives mail, enforces SPF hardfail, publishes DKIM and sets DMARC to reject scores in the mid-to-high 90s. A domain with MX and a permissive p=none DMARC scores far lower — and that gap is exactly the signal you’re auditing for.
▶ Open the Bulk Email Deliverability Checker on Apify — paste thousands of domains, get MX/SPF/DKIM/DMARC/BIMI parsed plus a 0–100 score per row. No API key, DNS-over-HTTPS. Export to CSV, JSON or Excel.
The access reality
Because this reads public DNS over HTTPS, there’s no anti-bot wall and no auth. The real constraints are three:
- Selector coverage for DKIM is heuristic. DKIM keys live at unpredictable selector names, and there is no way to enumerate them from DNS. The actor probes 31 common selectors (google, default, dkim, selector1, selector2, mail, s1, s2, k1, k2, amazonses, sendgrid, mailgun, mandrill, sparkpost, postmark, mimecast, proofpoint, docusign, zendesk, hubspot, salesforce, protonmail, ms365, microsoft, outlook, and more). If a domain uses a bespoke selector name, it won’t be found —
hasDkimcan read false even when DKIM is actually configured. This is a fundamental DNS limitation, not a bug. - It’s domain-level, not mailbox-level. This audits the DNS configuration that governs deliverability, not whether a specific address exists or accepts mail. For per-address validation you want a separate email verifier.
- Concurrency vs. resolver limits. Cranking
maxConcurrencytoward 100 is faster but can start bumping resolver rate limits; the Cloudflare-then-Google fallback absorbs a lot of that, and keeping the proxy enabled helps distribute requests.
Example output
One domain’s full report:
{
"domain": "stripe.com",
"deliverabilityScore": "95",
"grade": "A+",
"hasMx": "true",
"mxRecords": "10 aspmx.l.google.com, 20 alt1.aspmx.l.google.com",
"mxCount": "3",
"hasSpf": "true",
"spfRaw": "v=spf1 include:_spf.google.com include:_spf.stripe.com -all",
"spfPolicy": "hardfail (-all)",
"spfLookupCount": "2",
"hasDmarc": "true",
"dmarcPolicy": "reject",
"dmarcPct": "100",
"hasDkim": "true",
"dkimSelectorsFound": "google, mailgun",
"hasBimi": "true",
"bimiSvgUrl": "https://bimi.stripe.com/logo.svg",
"passCount": "5",
"issues": null,
"resolver": "cloudflare",
"checkedAt": "2026-06-24T12:00:00.000Z"
}
Typical use cases
- Cold email campaign prep — audit your prospect list before sending; sort ascending by
deliverabilityScoreto flag domains with no MX or weak SPF and skip the risky sends that would hurt your sender reputation. - Deliverability consulting — run bulk audits for clients, hand them the CSV as an email-security scorecard, and sell the remediation plan.
- Brand protection — scan your own domain portfolio for
dmarcPolicy: "none"to find domains vulnerable to exact-domain spoofing. - Compliance checks — SPF, DKIM and DMARC are now table stakes for the Google/Yahoo bulk-sender rules; grade every sending domain A+ to F and fix the gaps before they cause failures.
- M&A due diligence — assess an acquisition target’s email-security posture across all its domains in one run.
- Domain portfolio management — scan parked and managed domains for email readiness.
Cost and effort math
Rolling this yourself means writing DoH clients, a resilient Cloudflare-to-Google fallback, an SPF parser that counts recursive lookups, a DMARC tag parser, a 31-selector DKIM prober, a BIMI extractor, and a weighted scoring function — then running it at concurrency without tripping resolver limits. It’s a real weekend, plus upkeep as selectors and provider conventions drift.
The managed actor is pay-per-result: a fraction of a cent per domain audited, plus a tiny per-run start fee. Auditing a 2,000-domain prospect list costs a few dollars, runs in parallel, and hands you a spreadsheet. There’s no proxy bill to speak of because DNS-over-HTTPS is cheap traffic. For a one-off list you’d never bother building the parsers; for a recurring audit you schedule the actor and pipe the dataset to Slack or email on completion.
Common pitfalls
Specific to email-authentication auditing:
- The SPF 10-lookup limit is a silent killer. RFC 7208 caps an SPF record at 10 DNS lookups; exceed it and receivers return a
permerrorand your SPF effectively fails. WatchspfLookupCount— any value above 10 is a real problem hiding behind an otherwise valid-looking record. p=noneis not protection. A DMARC record withdmarcPolicy: "none"monitors but enforces nothing. It scores lower for a reason; don’t count it as “DMARC done.”- A missing DKIM selector isn’t proof of missing DKIM. If a domain uses a custom selector outside the probed 31,
hasDkimreads false. Confirm against the sending platform’s docs before telling a client they have no DKIM. - Domain-level audit ≠ mailbox validity. A perfect score means the domain is configured to send and receive well; it says nothing about whether
[email protected]exists. - Strip the scheme, but check the apex. The actor strips
https://and paths for you, but SPF and DKIM live on the exact domain — auditingwww.example.comwhen the mail domain isexample.comreturns a different (usually empty) result. - Some
issuesare advisory, not fatal. A missing BIMI record dings the score by only 8 points and isn’t a deliverability failure — prioritize the MX/SPF/DMARC problems first.
Wrapping up
Email authentication is boring, DNS-heavy, and consequential — exactly the kind of work worth automating. One domain is a few dig commands; a prospect list is a day you’ll never get back. The managed actor runs all five checks over DNS-over-HTTPS in parallel and returns a parsed, scored, issue-annotated row per domain that you can act on or forward as-is.
▶ Run the Bulk Email Deliverability Checker on Apify — one run audits thousands of domains across MX, SPF, DKIM, DMARC and BIMI with a 0–100 score and issues list per row. No API key. Start on Apify’s free monthly credit.
Related guides
How to Build a Deep-Research Retrieval Layer for AI Agents
Give an agent a topic and get ranked web sources, full-page Markdown, and recent news with citations — keyless multi-source retrieval for RAG and grounding.
How to Extract Structured Data from Any URL in 2026
Turn any web page into clean JSON without an LLM: parse schema.org JSON-LD, OpenGraph, tables, prices and contacts deterministically — no API key, no browser.
How to Add Live Web Search to AI Agents (No API Key)
Give your LLM fresh, citable search results without a Tavily or SerpAPI key. How live SERP extraction works: ranked results plus Markdown page content for RAG.