Bulk DMARC Record Checker
Pricing
from $0.96 / 1,000 domain extracteds
Bulk DMARC Record Checker
Check DMARC records in bulk and export raw records, parsed policies, reporting destinations, alignment settings, and validation findings.
Pricing
from $0.96 / 1,000 domain extracteds
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Bulk DMARC Record Checker is a DMARC record checker for domain portfolios. Give it up to 5,000 domains or website URLs and receive one normalized audit row per unique domain with the raw TXT record, parsed policy tags, reporting destinations, alignment settings, validation findings, and explicit missing or DNS-error states.
It uses the public DNS record at _dmarc.<domain>. It does not crawl websites, require login cookies, or hide missing records by dropping rows.
What does Bulk DMARC Record Checker do?
The Actor performs these steps for every unique normalized domain:
- Converts a domain or URL to a lowercase ASCII hostname.
- Resolves TXT values at
_dmarc.<domain>. - Joins multi-string DNS TXT chunks correctly.
- Selects values beginning with the
DMARC1version marker. - Distinguishes one record, no record, multiple records, and DNS errors.
- Parses policy, reporting, percentage, alignment, failure, interval, and format tags.
- Emits structured findings for malformed, duplicate, invalid, unusual, and unknown tags.
- Saves one typed dataset item even when the record is missing or the resolver fails.
This output supports one-time checks and scheduled email-security posture audits. A scheduled Apify Task can run the same domain list repeatedly; each run's checkedAt timestamp and dataset provide a snapshot for downstream comparison.
Who is it for?
- Email-security teams auditing whether managed domains publish enforceable policies.
- IT and Google Workspace administrators checking policy, reporting, SPF alignment, and DKIM alignment.
- Managed service providers reviewing many customer domains in one repeatable run.
- Security consultants producing source-backed domain posture inventories.
- Data and compliance teams exporting normalized findings to a spreadsheet, database, or SIEM.
- Developers integrating DMARC record checks into onboarding or domain-management workflows.
Use Bulk DNS Records Lookup when you need A, AAAA, MX, NS, TXT, CNAME, and SOA records rather than DMARC-specific parsing. Use MX Record Checker when the job is specifically mail-exchanger discovery.
Why use this Actor?
A raw DNS lookup gives you strings. This Actor converts those strings into audit-ready fields while preserving the source record.
- Bulk input: up to 5,000 supplied domains per run.
- Explicit coverage: missing and resolver-error states are rows, not silent gaps.
- Audit evidence: every row includes the query name, raw record, timestamp, and duration.
- Policy parsing:
p,sp,pct,adkim,aspf,rua,ruf,fo,ri, andrfbecome typed fields. - Validation findings: stable codes make filtering and downstream alerting practical.
- International domains: Unicode hostnames normalize through IDNA/ASCII conversion.
- URL input:
https://www.domain.tld/pathis checked aswww.domain.tld. - Custom resolvers: optional DNS server IPs support resolver-specific audits.
- No browser or proxy: the Actor uses the DNS protocol directly.
What DMARC data is returned?
| Field | Meaning |
|---|---|
input | Original domain or URL supplied by the user |
domain | Normalized, deduplicated ASCII hostname |
queryName | DNS name queried, such as _dmarc.domain.tld |
status | valid, invalid, missing, multiple, or error |
hasRecord | Whether a DMARC-version TXT record was found |
isValid | Whether exactly one record passed implemented checks |
rawRecord | Single source record, or null when unavailable/ambiguous |
rawRecords | All detected DMARC-version records |
parsed.policy | Organizational policy: none, quarantine, or reject |
parsed.subdomainPolicy | Optional subdomain policy from sp |
parsed.percentage | Effective pct; defaults to 100 when omitted |
parsed.aggregateReportUris | Parsed rua destinations, including address and size limit |
parsed.forensicReportUris | Parsed ruf destinations |
parsed.dkimAlignment | adkim; defaults to relaxed (r) |
parsed.spfAlignment | aspf; defaults to relaxed (r) |
parsed.failureOptions | Parsed fo values |
parsed.reportIntervalSeconds | ri; defaults to 86,400 seconds |
parsed.reportFormat | rf; defaults to afrf |
parsed.tags | Every parsed tag and its original value |
parsed.unknownTags | Unrecognized tags preserved for forward compatibility |
findings | Structured validation errors, warnings, and information |
errorCode, errorMessage | Resolver details when status is error |
checkedAt | ISO 8601 result timestamp |
durationMs | Lookup and parsing duration for the domain |
How to run your first DMARC record check
- Open the Actor in Apify Console.
- Enter one or more domains in Domains.
- Keep the default concurrency and timeout for a first run.
- Click Start.
- Open the Dataset tab and select the DMARC audit overview.
- Filter
statusorisValid, or export the complete dataset as JSON, CSV, Excel, XML, or RSS.
Example input:
{"domains": ["google.com","yahoo.com","https://github.com/about","neverssl.com"],"concurrency": 20,"timeoutMs": 5000}
Duplicate normalized domains are checked once. In this example, a second github.com input would not create a duplicate charge or row.
Input parameters
domains
Required array of 1–5,000 domains or website URLs. Each entry must resolve to a syntactically valid public hostname containing at least one dot. IP addresses, empty values, and malformed labels fail input validation.
The hostname is used exactly as normalized. Supplying www.domain.tld checks _dmarc.www.domain.tld; it does not automatically change the request to the organizational domain.
concurrency
Optional integer from 1 to 100. The default is 20. Lower it when your custom recursive resolver applies strict rate limits.
timeoutMs
Optional timeout from 500 to 30,000 milliseconds for each resolver attempt. The default is 5,000.
dnsServers
Optional list of IPv4 or IPv6 recursive DNS server addresses. When set, the Actor preserves this resolver choice and does not substitute public fallback resolvers.
Example output
A live local check of google.com produced a row with this shape (timestamp and duration shortened for readability):
{"input": "google.com","domain": "google.com","queryName": "_dmarc.google.com","status": "valid","hasRecord": true,"isValid": true,"rawRecord": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com","rawRecords": ["v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com"],"parsed": {"version": "DMARC1","policy": "reject","subdomainPolicy": null,"percentage": 100,"aggregateReportUris": [{"uri": "mailto:mailauth-reports@google.com","scheme": "mailto","address": "mailauth-reports@google.com","sizeLimit": null}],"forensicReportUris": [],"dkimAlignment": "r","spfAlignment": "r","failureOptions": [],"reportIntervalSeconds": 86400,"reportFormat": ["afrf"],"tags": {"v": "DMARC1","p": "reject","rua": "mailto:mailauth-reports@google.com"},"unknownTags": {}},"findings": [],"errorCode": null,"errorMessage": null,"checkedAt": "2026-08-23T12:00:00.000Z","durationMs": 24}
Understanding statuses and findings
valid: one DMARC record was found and no error-severity finding was produced.invalid: one DMARC record was found, but required syntax or a supported tag value is invalid.missing: the DNS query had no DMARC-version TXT record.multiple: more than one DMARC-version record was found, so receivers cannot apply one unambiguous policy.error: DNS resolution failed for a reason other than an authoritative no-record result.
Finding severities are error, warning, and info. Stable codes include record_missing, multiple_records, missing_policy, invalid_policy, invalid_alignment, invalid_percentage, duplicate_tag, unknown_tag, and dns_lookup_failed.
Validation is an operational aid, not a guarantee that every receiver will interpret a policy identically. The Actor does not fetch aggregate reports or verify ownership of reporting mailboxes.
How much does it cost to check DMARC records?
The Actor uses pay-per-event pricing:
- one
startevent per run; - one
domainevent per unique domain result, including explicit missing and error rows.
Current pricing is a $0.001 start fee plus a per-domain price that decreases by Apify plan:
| Apify plan | Price per unique domain |
|---|---|
| Free | $0.00184 |
| Bronze | $0.0016 |
| Silver | $0.001248 |
| Gold | $0.00096 |
| Platinum | $0.00064 |
| Diamond | $0.000448 |
At the Bronze rate:
| Unique domains | Estimated Actor charge |
|---|---|
| 1 | $0.0026 |
| 25 | $0.041 |
| 100 | $0.161 |
| 1,000 | $1.601 |
The input limit, deduplication, and event names are part of the pricing contract. DNS records themselves are public; charges pay for the repeatable processing, validation, structured output, and Apify execution.
Scheduled audit and monitoring workflows
Create an Apify Task with a stable domains list, then attach a daily, weekly, or monthly schedule. Each run creates a separate timestamped dataset snapshot.
Useful downstream patterns include:
- Send each dataset to Google Sheets and filter domains whose
statusis notvalid. - Store snapshots in a warehouse and compare
rawRecordorparsed.policyover time. - Trigger a webhook after the run and create alerts for
missing,multiple, orerrorstates. - Enrich an asset inventory with policy, reporting, and alignment columns.
- Audit customer onboarding lists before email infrastructure changes.
The Actor reports current DNS answers. It does not retain history or send alerts by itself; Apify schedules, webhooks, integrations, and your downstream system provide those workflow layers.
Export and integrations
Every result is written to the default Apify dataset. Use Console export or the dataset API to retrieve JSON, JSONL, CSV, Excel, XML, or RSS.
Common integrations:
- Google Sheets for audit review;
- Make or Zapier for status-based workflows;
- Slack or email webhooks for policy changes;
- BigQuery, Snowflake, or PostgreSQL for snapshot comparison;
- SIEM and asset-management systems for posture enrichment;
- Apify API clients for application onboarding checks.
Run with the Apify API
Set APIFY_TOKEN in your environment rather than placing it in source code.
cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~bulk-dmarc-record-checker/runs" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"domains":["google.com","github.com"],"concurrency":10}'
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/bulk-dmarc-record-checker').call({domains: ['google.com', 'github.com', 'neverssl.com'],concurrency: 10,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/bulk-dmarc-record-checker').call(run_input={'domains': ['google.com', 'github.com', 'neverssl.com'],'concurrency': 10,})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
Use Bulk DMARC Record Checker through MCP
Add this Actor to Claude Code:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/bulk-dmarc-record-checker"
Claude Desktop setup
Add this server in Claude Desktop's MCP configuration. The same JSON format is also supported by editor clients:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/bulk-dmarc-record-checker"}}}
Cursor setup
Add the JSON server entry in Cursor's MCP settings, then enable the apify server for the workspace.
VS Code setup
Add the same HTTP MCP server in VS Code's MCP configuration and authorize it with your Apify account when prompted.
Example prompts:
- “Check DMARC for these 30 domains and return only missing or invalid records.”
- “Parse DMARC policy, rua, adkim, and aspf for google.com and github.com.”
- “Run the bulk DMARC checker on my approved asset list and summarize reject versus quarantine policies.”
Reliability, retries, and DNS behavior
The Actor uses the runtime recursive resolver with two bounded attempts. For transient timeout, refusal, or server-failure codes, it can make one recovery query through independent public recursive resolvers. Authoritative no-record results are not retried.
When dnsServers is supplied, the Actor does not replace those servers. This makes split-horizon or resolver-comparison results predictable, but availability depends on the supplied resolver.
DNS answers can differ temporarily because of caching, propagation, DNSSEC failures, and resolver location. The Actor reports the answer observed during the run, not a global propagation consensus.
Legality
- Maximum 5,000 input values per run.
- Maximum 100 concurrent domain checks.
- Only the exact normalized hostname is queried.
- DMARC organizational-domain fallback behavior is not simulated.
- External report authorization records are not followed or verified.
- The Actor does not create, publish, or modify DNS records.
- The Actor does not receive, parse, or store DMARC aggregate/forensic report files.
- A syntactically valid record can still represent a weak policy such as
p=none.
DNS records are generally public infrastructure data. Use the Actor only for domains and workflows you are authorized to assess, follow applicable contracts and organizational policies, and protect exported domain inventories when they are sensitive.
Troubleshooting
Why is the status missing when a website exists?
A working website does not imply that _dmarc.<domain> has a DMARC TXT record. Verify the exact queryName field and whether you supplied a hostname such as www.domain.tld rather than the intended organizational domain.
Why did I receive error instead of missing?
missing is reserved for authoritative no-record responses. error means resolution failed because of timeout, refusal, server failure, or another resolver condition. Inspect errorCode and errorMessage, rerun after the transient issue, or supply a known recursive resolver.
Why is a record marked multiple?
DMARC expects one policy record. Publishing multiple TXT records beginning with v=DMARC1 is ambiguous. Consolidate the tags into one record at your DNS provider.
Why does a URL check a subdomain?
URLs normalize to their exact hostname. https://www.domain.tld/page becomes www.domain.tld, not domain.tld. Supply the organizational domain explicitly when that is your audit target.
Frequently asked questions
Does this Actor create a DMARC record?
No. It checks and parses records that are already published. It can help identify fields needed in a record, but it never changes DNS.
Does it check SPF or DKIM selectors?
No. The product is intentionally DMARC-specific. Use the related DNS or MX Actors for broader DNS inventory, and a dedicated email-authentication workflow when SPF or selector discovery is required.
Are missing and DNS-error rows charged?
Yes. They are useful explicit audit results and use the same domain event as valid records. Duplicated normalized inputs are processed and charged once.
Can I schedule recurring checks?
Yes. Save the input as an Apify Task and attach a schedule. Snapshot comparison and alerting are handled through datasets, integrations, or your downstream system.
Does valid mean my email is fully protected?
No. It means one record passed the implemented syntax and value checks. Email protection also depends on aligned SPF/DKIM authentication, actual sending configuration, report review, and receiver behavior.
Related automation-lab Actors
- Bulk DNS Records Lookup — normalized A, AAAA, MX, NS, TXT, CNAME, and SOA inventory.
- MX Record Checker — mail-exchanger records and provider identification.
- SSL Certificate Checker — certificate validity and expiry checks for domain portfolios.
These links are complementary tools from automation-lab; third-party Store competitors are not presented as related products.