DMARC SPF MX Lookup API - Email DNS Security Check
Pricing
from $0.70 / 1,000 results
DMARC SPF MX Lookup API - Email DNS Security Check
No API key, no login. One call per domain list returns MX, SPF (parsed, DNS lookups against the limit of 10, includes resolved), DMARC policy and reports, DKIM keys, MTA-STS, TLS-RPT, BIMI, a score and a plain fix list. Monitor mode returns only domains whose records changed. A resolver outage says
Pricing
from $0.70 / 1,000 results
Rating
0.0
(0)
Developer
Martin Petrov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Features
Share
Problem: you onboard customers, run a deliverability tool, manage client domains or audit mail security and need to know whether a domain's email DNS is set up correctly. The usual way is a handful of dig commands and manual reading of SPF includes.
This API: up to 50 domains per call, answered from public DNS in a few seconds. One row per domain with everything in one place:
- MX: every host with its priority and whether the host resolves to an IP. Null MX is recognised.
- SPF: the raw record, every mechanism parsed, the
allqualifier, and the DNS lookup count against the limit of 10, with everyinclude:andredirect=resolved recursively. Multiple SPF records, missing includes and loops are reported. - DMARC: raw record, policy
p, subdomain policysp,pct,rua/ruf,adkim/aspf. - DKIM: the selectors you give plus the common ones (google, selector1, selector2, default, k1, s1, mail): key found, key type, key size in bits, revoked keys.
- MTA-STS: the TXT record and, if present, the policy mode, max age and mx list (fetched from
https://mta-sts.<domain>/.well-known/mta-sts.txt). TLS-RPT and BIMI records. - Score, grade and issues: a 0-100 score, a letter grade and a plain
issueslist. Every issue has a severity and a concretefix.
Why it is different
- An outage is never a false "no record". DNS-over-HTTPS from Google DNS with Cloudflare DNS as fallback. If neither answers, the row says
unavailablewith the reason and is not counted as a missing record. - One call, whole picture. No stitching of separate SPF, DMARC and MX calls.
- Domain change monitor:
onlyNew: true+monitorIdreturns only domains whose records changed since the last run, with the list of changed sections. - Domain level only: no mailbox checks, no SMTP connections, no personal data.
Example (API)
curl -X POST "https://api.apify.com/v2/acts/martin10291~email-dns-dmarc-spf-check/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"domains": ["github.com", "example.com"], "dkimSelectors": ["selector1"]}'
Output row (trimmed):
{"domain": "google.com", "status": "ok", "score": 100, "grade": "A", "issueCount": 0,"mx": {"found": true, "nullMx": false, "records": [{"host": "smtp.google.com", "priority": 10, "resolves": true}]},"spf": {"found": true, "record": "v=spf1 include:_spf.google.com ~all", "qualifierAll": "softfail","dnsLookups": 1, "lookupLimit": 10, "lookupLimitExceeded": false, "includes": ["_spf.google.com"], "errors": []},"dmarc": {"found": true, "record": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com", "policy": "reject", "pct": 100, "adkim": "r", "aspf": "r"},"dkim": {"found": false, "selectorsChecked": ["google", "selector1", "selector2", "default", "k1", "s1", "mail"], "keys": []},"mtaSts": {"txtFound": true, "policyFetched": true, "mode": "enforce", "maxAge": 86400},"tlsRpt": {"found": true}, "bimi": {"found": false},"issues": [{"severity": "info", "area": "spf", "issue": "SPF ends with '~all' (softfail). This is common and acceptable when DMARC is enforced.", "fix": "Use '-all' once you are sure every sender is listed."}],"checkedAt": "2026-11-12T14:29:05Z"}
Issue severities: high (mail fails or can be spoofed), medium, low, info (hints; info does not lower the score and is not counted in issueCount).
Schedule it / monitor domains
Run it daily or hourly with an Apify schedule and set onlyNew: true with a monitorId such as my-customers. The first run returns every domain (change: first_check); later runs return only domains where MX, SPF, DMARC, DKIM, MTA-STS, TLS-RPT or BIMI changed (change: changed, plus changedFields). Connect the dataset to a webhook, Slack, Zapier or Make through an Apify integration to get an alert when a customer's SPF or DMARC changes. A run that finds no change returns no rows and no charge.
Use from agents (MCP)
Add the Apify MCP server (https://mcp.apify.com?tools=martin10291/email-dns-dmarc-spf-check) to Claude, Cursor or any MCP client and ask: "Check the email DNS of these domains and list the fixes: ...".
Input
| Field | What it does |
|---|---|
domains | Domains, up to 50 (bare names like example.com) |
domain | Shortcut for a single domain |
dkimSelectors | Your own DKIM selectors, checked besides the common ones |
onlyNew / monitorId | Return only domains whose records changed since the last run with this Monitor ID |
Honest limits
- DKIM selectors are arbitrary names. Only the selectors you pass and the common ones are checked. "No DKIM key found" for the common selectors is an
infohint, not proof that DKIM is missing. Pass your selector indkimSelectors. - DMARC is read at
_dmarc.<the domain you give>. Subdomains do not fall back to the organizational domain; pass the domain mail is sent from. - SPF macros (
%{i}and similar) are not expanded. Such an include counts as one lookup and is noted inspf.notes. - The
mxmechanism's own host lookups and the void-lookup limit are not part of the count; the count follows the 10-term limit of RFC 7208. - The MTA-STS policy file is fetched only from
mta-sts.<domain>and only if that host resolves to public addresses; redirects are not followed. - DNS answers come from public resolvers and can be cached for a short time (the record's TTL).
FAQ
Pricing? $1.00 / 1000 results (one row per domain, or per changed domain in monitor mode).
Do I need a key? No. Public DNS only.
Does it send email or connect to mail servers? No. DNS lookups and the MTA-STS policy file only.
What does unavailable mean? The DNS resolvers did not answer for that domain. Try again; it never means the domain has no records.