/commands/dig/dig-txt-record-spf-dmarc
dig TXT: check SPF, DMARC and domain verification TXT records
- tool
- dig / nslookup
- versions
- BIND 9.18, BIND 9.20
- os
- linux, macos, windows
dig example.com TXT +short prints every TXT record on a name, one record per line in double quotes. Mail and verification records live at fixed names: SPF on the domain itself, DMARC on _dmarc.DOMAIN, DKIM on SELECTOR._domainkey.DOMAIN, ACME DNS challenges on _acme-challenge.DOMAIN. Query the exact name, or you will see a different set of records.
dig example.com TXT +short # all TXT records at the apex (SPF lives here)
dig _dmarc.example.com TXT +short # DMARC policy
dig s1._domainkey.example.com TXT +short # DKIM public key for selector "s1"
dig _acme-challenge.example.com TXT +short # Let's Encrypt DNS-01 tokenWhere each record lives
| Record | Name to query | Starts with |
|---|---|---|
| SPF | example.com | v=spf1 |
| DMARC | _dmarc.example.com | v=DMARC1 |
| DKIM | SELECTOR._domainkey.example.com | v=DKIM1 (the selector is in the s= tag of the DKIM-Signature header) |
| ACME DNS-01 | _acme-challenge.example.com | A random token, no prefix |
| Site verification | Usually example.com | A provider-specific string such as google-site-verification=... |
Find the SPF record among many
The apex often carries several TXT records (verification strings for different services). Filter for the SPF one:
dig example.com TXT +short | grep -i 'v=spf1'
dig example.com TXT +short | grep -ci 'v=spf1' # must print 1More than one v=spf1 record makes SPF evaluation fail with permerror (RFC 7208, section 4.5). SPF also limits DNS lookups caused by include, a, mx, ptr, exists and redirect to 10 per check (section 4.6.4); follow each include: with another dig TXT to count them.
Long values
DKIM keys exceed the 255-byte limit of a DNS character-string, so they appear as several quoted pieces on one line: "v=DKIM1; k=rsa; p=MIIB..." "...IDAQAB". That is one record; the receiver joins the pieces. Two separate lines, on the other hand, are two records.
Check propagation
After editing a record, ask the zone's authoritative server first, then a public resolver:
dig example.com NS +short
dig @ns1.example.net _dmarc.example.com TXT +short
dig @8.8.8.8 _dmarc.example.com TXT +shortIf the authoritative server shows the new value and the resolver the old one, wait for the TTL of the cached record to expire. If the authoritative server shows the old value, the change was not saved in the zone that is actually delegated. An empty answer with status: NOERROR in the full output means the name exists without TXT data; NXDOMAIN means the name does not exist, often a typo in _dmarc or the selector.
FAQ
Why is my TXT record split into several quoted strings?
A single DNS character-string holds at most 255 bytes, so longer values (DKIM keys, long SPF records) are stored as several strings in one record. Receivers concatenate them without spaces, so the split does not change the value.
Can a domain have two SPF records?
No. RFC 7208 says that if a domain publishes more than one TXT record starting with v=spf1, the SPF check returns permerror. Merge the mechanisms into a single record.
My provider asks for a TXT record on @. What name do I query?
@ means the zone apex, so query the bare domain, for example dig example.com TXT +short. Verification records on a subdomain such as _acme-challenge.example.com are queried by their full name.