Email & domains
DMARC checker
Coverage: Works with domains from any country. We look for the record as receiving servers do: at the domain itself and, if it has none, at its parent domains (up to five levels). Report addresses are only shown by their domain.
Open toolOn this page
Purpose
Check a domain’s DMARC record: its policy (none, quarantine or reject), whether it comes from a parent domain, the share of email it applies to, the alignment and where the reports go.
Requirements
Anyone can read these guides, no account needed. Some tools require Pro, as indicated in each guide.
DMARC tells receiving servers what to do with an email that claims to come from a domain but fails its checks: deliver it, send it to spam or reject it. Type a domain, an email address or a link and we’ll show you its DMARC policy and what it means.
How to use it
Type the domain you want to check, or paste an email address or a link: we only use its domain.
Press “Check DMARC”. We look for its record at _dmarc and, if there’s none, at its parent domains, as receiving servers do.
Look at the policy: “reject” or “quarantine” on 100% of the email protects the domain; “none” only monitors.
Synthetic example
Invented example, not a real lookup. Do not call or open its links.
v=DMARC1; p=reject; rua=mailto:[email protected]Interpret the result
This domain has no DMARC: It doesn’t ask receivers to stop email that pretends to come from it, which makes it easier to impersonate.
The DMARC record has errors: Receivers may ignore it, which leaves the domain as if it had no DMARC. The signals below say what’s wrong.
DMARC only monitors: The policy is “none”: the domain gets reports, but fake email in its name is still delivered.
DMARC protects only part of the email: The policy applies to a share of the email that fails; the rest is delivered as if there were no policy.
Fake email goes to spam: The policy is “quarantine”: receivers send email that fails the checks to the spam folder.
Fake email is rejected: The policy is “reject”: receivers refuse email that pretends to come from this domain. It’s the strongest protection.
none: monitor only
quarantine: send to spam
reject: refuse delivery
Limitations
We read the domain’s public DNS records. If you type an email address or a link, only its domain leaves your browser. The domain you look up isn’t stored.
Troubleshooting
That doesn’t look like a public domain. Try something like example.com.
DNS didn’t answer in time. Try again in a few seconds.
You’ve run a lot of checks in a row. Wait a minute and try again.
Use with the API
Needs an API key and credits. Each completed call costs 1 credit, even when there is no data. An active Pro account includes 20 credits per UTC calendar month, shared by every API route and spent first; unused monthly credits do not roll over. Credits bought on your account page work without Pro and never expire.
Errors are never charged: 401 invalid_api_key (missing or invalid key), 403 pro_required (no Pro credits and no purchased credits), 422 invalid input, 429 quota_exceeded (no credits left), rate_limit_exceeded or ai_busy (the AI of sms-check is at capacity), 503 tool_warming (the data is still being prepared) or tool or provider unavailable. After a 429 or 503, retry once the seconds in the Retry-After header have passed.
A domain’s DMARC policy (RFC 7489, with the DMARCbis walk up to parent domains): the record, where it was found, the effective policy (none, quarantine or reject), the percentage, the DKIM and SPF alignment and the domains that receive the reports, never a full address. Nothing is stored.
Send the JSON body to the tool's own route, or to POST /v2/tools with the tool field added. Both routes return the same result.
POST https://api.nocall.io/v2/dmarc-check
POST https://api.nocall.io/v2/tools {"tool":"dmarc-check","domain":"example.com"}Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| domain | string (1–320) | Yes | A domain, or an email address or link whose domain is used, up to 320 characters. Public names only: IP addresses, single labels and special-use names (.local, .internal, .test…) are a 422. |
REQUEST_ID="$(uuidgen)" && [ -n "$REQUEST_ID" ] &&
curl --request POST 'https://api.nocall.io/v2/dmarc-check' \
--header "Authorization: Bearer $NOCALL_API_KEY" \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $REQUEST_ID" \
--data '{"domain":"example.com"}'import json
import os
import urllib.request
import uuid
api_key = os.environ.get('NOCALL_API_KEY')
if not api_key:
raise SystemExit('Set NOCALL_API_KEY')
request = urllib.request.Request(
'https://api.nocall.io/v2/dmarc-check',
method='POST',
data=json.dumps({'domain': 'example.com'}).encode(),
headers={
'Authorization': 'Bearer ' + api_key,
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4()),
},
)
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
print(result['data']['result'], result['meta']['unitsCharged'])import { randomUUID } from 'node:crypto';
const requestId = randomUUID();
const apiKey = process.env.NOCALL_API_KEY;
if (!apiKey) throw new Error('Set NOCALL_API_KEY');
const response = await fetch('https://api.nocall.io/v2/dmarc-check', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + apiKey,
'Content-Type': 'application/json',
'Idempotency-Key': requestId,
},
body: JSON.stringify({ domain: 'example.com' }),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error?.code ?? 'request_failed');
console.log(result.data.result, result.meta.unitsCharged);Example response (200)
This is the documented example from the API reference. Lookups use a fictional number, and aggregates and AI answers show the shape of the result, not live data.
{
"data": {
"tool": "dmarc-check",
"result": {
"domain": "example.com",
"domainAscii": "example.com",
"found": true,
"record": "v=DMARC1; p=none; rua=mailto:[email protected]",
"foundAt": "example.com",
"inherited": false,
"policy": "none",
"subdomainPolicy": null,
"effectivePolicy": "none",
"percentage": 100,
"alignment": {
"dkim": "relaxed",
"spf": "relaxed"
},
"reports": {
"aggregate": [
"example.com"
],
"failure": []
},
"signals": [
"policy_none"
],
"valid": true,
"attention": true
}
},
"meta": {
"requestId": "req_example",
"unitsCharged": 1,
"usage": {
"periodStart": "2026-10-01",
"unitLimit": 20,
"unitsUsed": 3,
"unitsRemaining": 17
}
}
}Result fields (data.result)
| Field | Type | Description |
|---|---|---|
| domain | string | The domain in Unicode. |
| domainAscii | string | The same domain in ASCII (punycode), as DNS sees it. |
| found | boolean | Whether a DMARC record applies to the domain (its own or a parent’s). |
| record | string | null | The DMARC record; null when there is none or more than one. |
| foundAt | string | null | The domain whose _dmarc record applies (this one or a parent), in Unicode. |
| inherited | boolean | Whether the record is a parent domain’s (DMARCbis tree walk). |
| policy | "none" | "quarantine" | "reject" | null | The p= tag: none, quarantine or reject. |
| subdomainPolicy | "none" | "quarantine" | "reject" | null | The sp= tag, or null. |
| effectivePolicy | "none" | "quarantine" | "reject" | null | What applies to this domain: p, or sp when the record is inherited. |
| percentage | integer (0–100) | pct: the share of failing email the policy applies to, 100 when absent. |
| alignment | object | The DKIM and SPF alignment (adkim and aspf): relaxed or strict. |
| reports | object | Domains that receive the aggregate (rua) and failure (ruf) reports; never a full address. |
| signals | array<"no_dmarc" | "multiple_records" | "syntax_error" | "policy_none" | "partial_percentage" | "no_aggregate_reports" | "inherited" | "weaker_subdomain_policy"> | no_dmarc, multiple_records, syntax_error, policy_none, partial_percentage, no_aggregate_reports, inherited or weaker_subdomain_policy. |
| valid | boolean | Whether the record parses and has a policy. |
| attention | boolean | Whether the result deserves a look: no DMARC, an invalid record, the none policy or a percentage below 100. |
Frequently asked questions
What is DMARC?
Domain-based Message Authentication, Reporting and Conformance: a DNS record that tells receivers what to do with email that uses a domain in “From” but fails SPF and DKIM. It also asks for reports, so the owner can see who sends email in the domain’s name.
What do none, quarantine and reject mean?
“none” only monitors: email is delivered as usual and the owner gets reports. “quarantine” sends email that fails to spam. “reject” refuses it. Domains usually start with “none”, read the reports and work their way up to “reject”.
If a domain has DMARC, is all its email genuine?
No. DMARC makes it hard to use that exact domain in “From”, but a scammer can register a look-alike domain with its own DMARC. Check the sender’s domain letter by letter, or paste the headers into “Is this email real?”.
Why does it say the record is inherited?
A subdomain without a record of its own (mail.example.com) uses the one of its parent domain (example.com), with the subdomain policy (sp) if it has one.
