Is your domain's email set up correctly?

Free check of SPF, DKIM, DMARC, BIMI and MX records, plus MTA-STS and TLS-RPT. Get a 0–100 score and plain-English fixes. No sign-up.

Advanced: DKIM selector

Examples: github.com · paypal.com · example.com

What each record does

MX

Mail exchanger records tell other servers where to deliver email for your domain. A domain that never handles mail can publish a “null MX” (0 .) to say so.

SPF

A TXT record listing the servers allowed to send mail for your domain, ending in -all or ~all. Receivers may follow at most 10 DNS lookups (include, a, mx, exists, redirect); go over and SPF returns a permanent error (permerror), which most receivers treat as a fail. SPF guide

DKIM

Your mail server signs each message; receivers verify the signature with a public key published at <selector>._domainkey.yourdomain. Selectors can't be listed via DNS, so we try common ones, plus provider-specific ones when your MX or SPF points to a known mail service (for example Microsoft 365, SendGrid, Mailchimp, Mailgun, Zendesk). You can also enter your own. DKIM guide

DMARC

Published at _dmarc.yourdomain. It tells receivers what to do when SPF and DKIM don't align with the visible From address: p=none (monitor), quarantine (spam folder) or reject. It also sets where reports go (rua). DMARC guide

BIMI

Optional. Lets supporting inboxes show your logo. Published at default._bimi.yourdomain with an SVG logo (l=) and usually a VMC/CMC certificate (a=). It requires DMARC at quarantine or reject. BIMI guide

MTA-STS

Optional. Tells other mail servers to deliver to you only over encrypted, certificate-checked TLS. A TXT record at _mta-sts.yourdomain (v=STSv1; id=…) points to a policy file at https://mta-sts.yourdomain/.well-known/mta-sts.txt with a mode (testing or enforce), your allowed MX hosts and a max_age. MTA-STS guide

TLS-RPT

Optional. A TXT record at _smtp._tls.yourdomain (v=TLSRPTv1; rua=mailto:…) that asks sending servers for daily reports about TLS problems delivering to you. Pairs with MTA-STS. TLS-RPT guide

How scoring works

MX 10 · SPF 25 · DMARC 30 · DKIM 25 · BIMI 10 = 100 points. MTA-STS (up to 3) and TLS-RPT (up to 2) add up to 5 bonus points, and the total is capped at 100, so a missing optional record never lowers your score. Bonus points apply only when SPF passes and DMARC is at quarantine or reject. Grades: A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, otherwise F. The score covers only what's visible in public DNS (plus the MTA-STS policy file).

Free JSON API

Using an AI assistant or agent? DnsGuard is also a remote MCP server: see For AI agents.

No key needed. CORS is enabled, so you can call it from a browser. Please keep it to a reasonable volume: requests are rate-limited per IP (about 20 checks/min), and results are cached for 2 minutes. DnsGuard is free to run only up to a point, so all anonymous visitors together share about 5,000 checks per UTC day; if that runs out you'll get a clear message, and a free API key still works.

Endpoint

GET /api/check?domain=<domain>[&selector=<dkim-selector>]

Example

curl "https://YOUR-HOST/api/check?domain=example.com"

Response (abridged)

{
  "domain": "example.com",
  "score": 95, "maxScore": 100, "grade": "A",
  "scoreBreakdown": { "base": 93, "bonus": 2, "bonusMax": 5, "cap": 100 },
  "checks": {
    "mx":    { "status": "pass", "score": 10, "maxScore": 10, "records": [...], "findings": [...], "recommendations": [...] },
    "spf":   { "status": "pass", "record": "v=spf1 -all", "lookupCount": 0, "lookupLimit": 10, ... },
    "dmarc": { "status": "warn", "policy": "reject", "pct": 100, "rua": [], "alignment": {...}, ... },
    "dkim":  { "status": "info", "selectorsChecked": [...], "keys": [...], ... },
    "bimi":  { "status": "info", "logoUrl": null, "vmcUrl": null, ... },
    "mtaSts": { "status": "info", "score": 0, "maxScore": 3, "bonus": true, "record": null, "mode": null, "mxPatterns": [], "maxAge": null, ... },
    "tlsRpt": { "status": "pass", "score": 2, "maxScore": 2, "bonus": true, "record": "v=TLSRPTv1; rua=mailto:tls@example.com", "rua": [...], ... }
  },
  "notes": [...],
  "meta": { "version": "0.7.2", "dnsQueries": 31, "durationMs": 180 }
}

status is one of pass, warn, fail or info. Each finding is { "level", "message" }. mtaSts and tlsRpt carry "bonus": true: their points are added on top of the five core checks and score is capped at 100 (scoreBreakdown shows both parts). mtaSts also has policyUrl, policyFetch (ok, httpStatus, error), mxCoverage (covered, uncovered) and id.

Errors

HTTPcodeMeaning
400invalid_domain / invalid_selectorInput failed validation
422domain_not_foundDomain does not exist (NXDOMAIN)
401invalid_api_keyBearer / X-Api-Key present but unknown
429rate_limited / daily_quota_exceeded / daily_capacity_reachedToo many requests (per minute, your key's daily cap, or the shared daily allowance); see Retry-After
502 / 504dns_unavailable / timeoutUpstream DNS failed or was too slow; retry

Error body: { "error": { "code": "invalid_domain", "message": "…" } }. Health check: GET /api/health.

Free API key (higher limits)

Anonymous use stays at about 20 checks/min per IP. Sign in with Google to mint one free API key with about 120 checks/min and a cap of 1,000 checks/day (UTC day). Key holders also have part of the shared daily allowance kept for them (about 8,000 checks per UTC day across all users, of which anonymous use can take at most about 5,000). Need more? See DnsGuard Pro ($9/mo, about 600 checks/min and 10,000/day).

Send a free key on every request:

Authorization: Bearer dg_live_…
# or
X-Api-Key: dg_live_…
curl -H "Authorization: Bearer dg_live_YOUR_KEY" \
  "https://YOUR-HOST/api/check?domain=example.com"

Pro license keys (prefix DNSG, issued by Polar after subscribe) use the same headers:

Authorization: Bearer DNSG-…
# or
X-Api-Key: DNSG-…
curl -H "Authorization: Bearer DNSG-YOUR_LICENSE_KEY" \
  "https://YOUR-HOST/api/check?domain=example.com"

Checking whether Google sign-in is available…

Continue with Google

Google sign-in uses a server-side OAuth redirect (no Google JavaScript on this page) and asks only for the openid and email scopes. Your Google email must be verified. A short-lived CSRF cookie is set only during sign-in.

Lost your key? Click Continue with Google again. You'll see "You already have a free API key" with a Rotate key button. Rotating takes one more Google sign-in, then shows a new key and deletes the old one, which stops working within about a minute.

For AI agents (MCP)

DnsGuard is also a remote Model Context Protocol (MCP) server, so AI assistants and agents can check a domain for you. Most MCP clients accept this config; some use a different format (for example, VS Code uses a servers key). Clients with a settings screen just need the URL https://dnsguard.mike-tusa.workers.dev/mcp.

{
  "mcpServers": {
    "dnsguard": {
      "type": "http",
      "url": "https://dnsguard.mike-tusa.workers.dev/mcp"
    }
  }
}

It has one read-only tool, check_domain (domain, plus an optional dkim_selector), and scores exactly like the JSON API. The limits are the same too: no key is needed for light use. For higher limits, have your client send Authorization: Bearer dg_live_… (free key) or Authorization: Bearer DNSG-… (Pro). Each tool call counts as one check.

Machine-readable docs: llms.txt · OpenAPI 3.1 spec · MCP endpoint POST /mcp (Streamable HTTP, stateless JSON responses).

DnsGuard Pro — $9/mo

Higher API limits for production use: about 600 checks/min and 10,000 checks/day (UTC) per license. After you subscribe, Polar issues a license key with prefix DNSG. Send it as Authorization: Bearer DNSG-… (or X-Api-Key) the same way as a free key. Responses include x-dnsguard-tier: pro.

Subscribe with Polar

Polar is the merchant of record (checkout, tax, refunds). Cancel or manage billing in your Polar customer portal. DnsGuard validates Pro licenses via a shared license store written by our fleet payment gateway after Polar subscription events; we store only hashed usage counters, not the raw license key.

Optional: notify me about digests

A weekly monitoring digest (email when SPF, DKIM, DMARC or BIMI records change) and higher plans are coming later. Leave your email if you want a heads-up — not required to use Pro.

Remove my digest notify email

Enter the address you signed up with. If it's on the list, it's deleted right away. For privacy, you'll see the same message either way.

Privacy

Last updated: 6 October 2026 (added the MTA-STS policy-file fetch).

A check only reads public data: DNS records, and, if the domain publishes an MTA-STS record, its public policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt (that web server sees a request from Cloudflare's network, not from your IP). We look up DNS through DNS-over-HTTPS resolvers (Cloudflare cloudflare-dns.com, falling back to Google dns.google), so those providers see the names being queried. We don't store the domains you check or your IP address. The site runs on Cloudflare Workers, and Cloudflare processes requests in order to serve it. Results are held in memory for up to 2 minutes for caching, and your IP is used only in short-lived counters for rate limiting. To keep the free service within its hosting budget we also keep site-wide daily totals (plain counts of checks and waitlist requests, with no IPs, keys or domains), deleted after about 2 days.

Digest notify list: if you opt in, we store only your email address and the time you signed up, in Cloudflare Workers KV. We use it only to email you about weekly monitoring digests or higher plans when they launch. We don't sell or share it, and we don't store your IP address with it. You can delete it yourself at any time with the Remove my digest notify email form; removal takes effect immediately.

Free API account (Google sign-in): when Google OAuth is enabled, we store your Google account id (sub), email, key id, key hash (SHA-256, never the raw key after issuance) and created time in a separate Workers KV namespace. We request only the openid and email scopes from Google (no name or profile photo). To enforce the free daily cap we also keep a per-key daily usage counter: the number of checks made with your key on each UTC day, stored in a Cloudflare Durable Object under your Google account id. Counters are deleted automatically after about 2 days. We don't store your IP address or the domains you check with any of this. A short-lived HttpOnly CSRF cookie is set only during the Google sign-in redirect and cleared afterward. You can replace a lost key yourself with Rotate key (see the API section). To delete your free API account data, email the contact address below.

DnsGuard Pro (Polar): Pro licenses are validated via a shared license store written by our fleet payment gateway after Polar subscription events. DnsGuard stores only hashed usage counters for rate and daily limits (SHA-256 of the license key; never the raw key). Polar is the merchant of record for checkout, tax, and refunds — cancel or manage billing through Polar. Contact for DnsGuard privacy or deletion requests stays the same address below.

No analytics and no third-party scripts. We don't use cookies except the short-lived OAuth CSRF cookie during Google sign-in.

Contact: questions, or a privacy or deletion request: digitalpromohub.support+dnsguard@gmail.com.