# Bulk DMARC, SPF & DKIM Checker – Email Authentication Audit (`yuvalstudios/dmarc-spf-dkim-checker`) Actor

Audit thousands of domains for DMARC policy, SPF (incl. 10-lookup limit), DKIM selectors, MTA-STS, TLS-RPT and BIMI. Score, grade, issues, mail provider. Pure DNS, no API key.

- **URL**: https://apify.com/yuvalstudios/dmarc-spf-dkim-checker.md
- **Developed by:** [Yuval Gabay](https://apify.com/yuvalstudios) (community)
- **Categories:** Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 domain checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bulk DMARC, SPF & DKIM Checker – Email Authentication Audit

Audit **any number of domains** for email authentication in one run. For each domain you get **DMARC** (policy, subdomain policy, pct, rua/ruf), **SPF** (record, `all` qualifier, **recursive DNS-lookup count vs. the 10-lookup limit**, duplicate records), **DKIM** (probes ~35 common selectors plus your own, with key type and size, revoked keys, CNAME delegation), **MX** and detected mail provider (Google Workspace, Microsoft 365, Proofpoint...), plus **MTA-STS, TLS-RPT and BIMI**. Every domain also gets a **0–100 score, an A–F grade and a plain-English issues list**.

It runs on DNS lookups only. No external API or key is needed, and DNS-over-HTTPS (Cloudflare, with Google as fallback) is the default for reliability.

### Who uses it

- **Cold-email agencies and deliverability consultants**: check client and sending domains before a campaign.
- **MSPs and IT agencies**: audit a whole client portfolio and find upsell opportunities (no DMARC = a sales lead).
- **Security teams**: spot spoofable domains (no DMARC or p=none) across subsidiaries.
- **Lead generation**: run a list of prospect domains with `onlyWithIssues` to find companies that need DMARC help.

### Input example

```json
{
  "domains": [
    "example.com",
    "https://www.stripe.com",
    "info@shopify.com"
  ],
  "extraDkimSelectors": [
    "mycompany"
  ],
  "onlyWithIssues": false,
  "concurrency": 10
}
```

### Output example

One real row (contact fields masked):

```json
{
  "domain": "apify.com",
  "score": 100,
  "grade": "A",
  "mx": [
    "aspmx.l.google.com",
    "alt1.aspmx.l.google.com",
    "alt2.aspmx.l.google.com"
  ],
  "mailProvider": "Google Workspace",
  "spfRecord": "v=spf1 a mx include:_spf.google.com include:mailgun.org include:amazonses.com include:19497222.spf05.hubspotemail.net -all",
  "spfAllQualifier": "fail",
  "spfLookupCount": 10,
  "dmarcRecord": "v=DMARC1; p=reject; sp=reject; pct=100; rua=mailto:dmarc-reports@apify.com; ri=604800",
  "dmarcPolicy": "reject",
  "dmarcSubdomainPolicy": "reject",
  "dmarcPct": 100,
  "dmarcRua": "mailto:dmarc-reports@apify.com",
  "dmarcRuf": null,
  "dkimSelectorsFound": [
    {
      "selector": "google",
      "keyType": "rsa",
      "revoked": false,
      "keyBits": 2048
    }
  ],
  "dkimRevokedSelectors": 0,
  "mtaSts": true,
  "tlsRpt": true
}
```

The dataset has a table view, and you can export to CSV, Excel or JSON, or use the API, Zapier, Make or Google Sheets.

### Notes

- DKIM can't be listed from DNS. The actor probes common selectors, so 'No DKIM key found' means none was found on those selectors. Add your ESP's selector if you know it.
- Accepts domains, URLs or email addresses.
- 1,000 domains take about 2–4 minutes at concurrency 10–20.

### What's new (October 2026)

- **Who sends mail for the domain:** `spfSenders` maps SPF includes to services (Google Workspace, Microsoft 365, SendGrid, HubSpot, Salesforce and more).
- **DNSSEC:** `dnssec` is true when the domain validates with DNSSEC.
- **`fixFirst`:** the most important fix in plain English.

### Pricing

Pay per result: **$0.001 per domain** ($1.00 per 1,000 domains).

### How to use

1. Click **Try for free** (or **Start**) — the form is pre-filled with a small working example.
2. Adjust the filters and **Max results**, then run. Most runs finish in under a minute.
3. Open the **Output** tab to view the table, or export CSV, Excel or JSON, or pull it via the API, Zapier, Make, Google Sheets or webhooks.

### FAQ

**Where does the data come from?** From public DNS (DNS-over-HTTPS via Cloudflare/Google). No login or API key is needed.

**How fresh is it?** Live: every run queries DNS at run time.

**Is it legal to use?** The data is public government data (or public DNS records). You are responsible for how you use it, e.g. CAN-SPAM/GDPR rules when contacting businesses.

**What happens if the source is slow or down?** Requests are retried with backoff. If the source fails mid-run, results already collected are kept and the run finishes with a clear status message instead of crashing. The run also stops cleanly before its timeout.

**Where is the run summary?** In the key-value store record `OUTPUT_SUMMARY` (counts, filters applied, why the run stopped).

**I need a field or filter that's missing.** Open an issue on the Issues tab.

### Related actors

- [FDA Recalls: food, drug & device enforcement reports](https://apify.com/yuvalstudios/fda-recalls)
- [USAspending Federal Awards: new contracts & grants](https://apify.com/yuvalstudios/usaspending-awards)
- [Grants.gov Federal Grant Opportunities](https://apify.com/yuvalstudios/grants-gov-opportunities)
- [SEC Form D private offerings (startup funding)](https://apify.com/yuvalstudios/sec-form-d)
- [UK New Companies (Companies House)](https://apify.com/yuvalstudios/uk-new-companies)
- [FMCSA new trucking carriers](https://apify.com/yuvalstudios/fmcsa-carriers)
- [Israel Open Data (data.gov.il)](https://apify.com/yuvalstudios/israel-open-data)

Built by Yuval Studios.

### Data source & disclaimer

- **Source:** live public DNS records (DMARC, SPF, DKIM, MX, MTA-STS, TLS-RPT, BIMI) queried over DNS-over-HTTPS (Cloudflare and Google public resolvers).
- **How fresh:** real time: each run reads the current DNS, which domain owners can change at any time (subject to DNS caching/TTL). Each row has `scrapedAt` (when this run fetched it) and `checkedAt`.
- **Licence & attribution:** DNS records are public technical data with no licence restrictions. The score is our own heuristic, not a certification or a security audit.
- **Disclaimer:** Data is provided **as is** from public records, without warranty of any kind. Records can contain errors, omissions or delays from the source or from processing, so check anything important against the official source. This actor and its output are **not legal, financial, compliance or medical advice**. You are responsible for using the data lawfully: only scan domains you own, manage, or have a legitimate reason to assess, and follow CAN-SPAM/GDPR if you use results in outreach. This actor is independent and **not affiliated with or endorsed by** Cloudflare, Google or any email-security vendor.
- **Last verified:** 2026-10-19.

# Actor input Schema

## `domains` (type: `array`):

Domains, URLs or email addresses (domain is extracted).

## `extraDkimSelectors` (type: `array`):

Added to ~35 common selectors (google, selector1, k1, s1, ...)

## `useDefaultSelectors` (type: `boolean`):

Try about 35 common DKIM selectors on each domain.

## `onlyWithIssues` (type: `boolean`):

Good for lead lists: domains with missing/weak DMARC.

## `concurrency` (type: `integer`):

How many domains to check in parallel.

## `dnsMode` (type: `string`):

How DNS lookups are done. DNS-over-HTTPS is the most reliable on Apify.

## `dnsServers` (type: `array`):

Only for system mode, e.g. 1.1.1.1, 8.8.8.8

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "github.com"
  ],
  "useDefaultSelectors": true,
  "onlyWithIssues": false,
  "concurrency": 10,
  "dnsMode": "doh"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "apify.com",
        "github.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yuvalstudios/dmarc-spf-dkim-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "apify.com",
        "github.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("yuvalstudios/dmarc-spf-dkim-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "apify.com",
    "github.com"
  ]
}' |
apify call yuvalstudios/dmarc-spf-dkim-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yuvalstudios/dmarc-spf-dkim-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/t8qfmQpPp6yAfZVIe/builds/9R9Xn6l0irS6qTd9t/openapi.json
