What does a TXT record do?
TXT is record type 16 from RFC 1035. The specification says only that it carries "descriptive text" — there is no schema, no defined encoding beyond character-strings, and no meaning assigned by DNS itself. Every use you care about is a convention layered on top: a prefix like v=spf1 or v=DMARC1 tells a consumer that this particular TXT record is for them, and everything else at that name is ignored.
That looseness is why TXT is where the internet puts things it needs to publish but has no record type for. In a typical production zone the TXT records at the apex are a pile of unrelated verification tokens from six vendors plus exactly one SPF record, and _dmarc, _domainkey, and _mta-sts labels carry the rest.
TXT syntax and fields
| Field | Example | Meaning |
|---|---|---|
| Name (owner) | _dmarc.google.com. | The name the text is attached to. Underscore-prefixed labels are conventional for protocol data. |
| TTL | 300 | Cache lifetime. |
| Class | IN | Internet class. |
| Type | TXT | Record type 16. |
| RDATA | "v=DMARC1; p=reject; ..." | One or more character-strings. Each string is length-prefixed with a single byte, so each is capped at 255 bytes. A record may hold many strings, up to the 65535-byte RDATA limit. |
The 255-byte limit, and why it is not what you think
This is the single most misunderstood detail about TXT records. The 255-byte cap applies to each character-string, not to the record. A TXT record can contain many strings, and consumers that care — SPF (RFC 7208) and DKIM (RFC 6376) both specify this — concatenate them with no separator before parsing.
A 2048-bit DKIM public key is roughly 400 characters, so it cannot fit in one string. Here is a real one, split across two:
s1.domainkey.u51742174.wl175.sendgrid.net. 1800 IN TXT "k=rsa; t=s; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn3fMCVpb7ryIRKOGXhXVGYmsWUitNlSckqGHOwNFZgFadplOrD+Qzf1XQkP7MH/VB/97DsAAJGtEXW1Uq71Hjnfr/DuBN/YfjF/gU70qEFb7q1sdIiNtjFL2TkOpoW+X/bhhPNheW/fYwyFb6ZHFM6LTgXyuimWRHTOUP3VjZzhNVda79nt+2WZYbS4l8HdMgWpT" "NHjpVw5PtXESA9KBg/evSRk5fIaXIX5eRXW3baoV9yVzD8O29/IL/DiSk+yNvaO0EHL5c4yGuZJhGzvpiznb2IDVdemJK4Dqzdy5FTN/SGYZhAEr7MguG3Z314hMS2scgMsOMgB64uj/6+6UwIDAQAB"Most DNS providers handle the chunking for you when you paste a long value into a web form. Some do not, and a few silently truncate at 255. If a freshly published DKIM key fails, dump the record with dig and count the characters after p= before blaming the signer. The DKIM checker will do that comparison for you.
What TXT records are used for
| Name | Prefix / format | Purpose |
|---|---|---|
| Zone apex | v=spf1 ... | SPF — which hosts may send mail as this domain. Exactly one per name. |
_dmarc.example.com | v=DMARC1; p=... | DMARC policy, alignment mode, and report addresses. |
sel._domainkey.example.com | v=DKIM1; k=rsa; p=... | DKIM public key for the selector sel. |
_mta-sts.example.com | v=STSv1; id=... | MTA-STS policy version pointer. |
_smtp._tls.example.com | v=TLSRPTv1; rua=... | TLS reporting destination. |
default._bimi.example.com | v=BIMI1; l=... | Brand logo location for BIMI. |
| Zone apex or a token label | google-site-verification=... | Vendor ownership proof. Dozens of these accumulate; they are harmless but worth pruning. |
Check each of these with the matching tool: SPF checker, DMARC checker, DKIM checker, MTA-STS checker, and BIMI checker.
Quoting and escaping
- In a zone file each character-string is wrapped in double quotes. Whitespace between quoted strings is a separator, not content.
- A literal double quote inside the text must be escaped as
\". A literal backslash is\\. - A semicolon outside quotes starts a zone-file comment. Inside quotes it is ordinary text — which is why DMARC records, full of semicolons, must be fully quoted.
- Most web-based DNS editors want the value without the outer quotes. Pasting
"v=spf1 -all"into such a form usually produces a record whose content literally includes the quote characters, and SPF then fails to parse. - Provider forms differ on whether the host field takes
_dmarcor_dmarc.example.com. Getting this wrong produces_dmarc.example.com.example.com. Verify after publishing, always.
Multiple TXT records at one name
A name can hold as many TXT records as you like, and resolvers return the whole set in unspecified order. Consumers filter by prefix. This works fine for verification tokens — but not for SPF.
RFC 7208 is explicit: if more than one TXT record at a name begins with v=spf1, the result is a PermError and receivers treat SPF as failed. Merging is the fix: one record with all the include: and ip4: mechanisms, not one record per vendor. And once merged, watch the 10-DNS-lookup limit — see SPF PermError: too many DNS lookups.
_dmarc and to a DKIM key at a given selector. Verification tokens are the only TXT records that safely multiply.TTL guidance
Use 300 while you are actively iterating on SPF or DMARC — you will publish, test, and republish several times, and a 3600 TTL turns a ten-minute task into an afternoon. Once the record is verified and stable, 3600 is the right resting value. Note that vendors performing ownership verification typically poll on their own schedule regardless of your TTL; a short TTL will not necessarily make verification succeed faster, but a long one can definitely make a failed attempt take longer to retry.
Common TXT record mistakes
- Two SPF records. The most common email-authentication break. Adding a vendor's suggested
v=spf1 include:vendor.net ~allnext to your existing record produces PermError, not a merge. - Splitting a DKIM key into two records instead of two strings. Signatures fail with a key-lookup error even though the record "looks right" in the UI.
- Including outer quotes in a web form. The record then contains literal
"characters and every parser rejects it. - Wrong host field.
_dmarc.example.comtyped into a field that already appends the zone gives_dmarc.example.com.example.com. - Using `~all` when the intent was `-all`, or vice versa — a policy decision, not a typo. See SPF ~all vs -all.
- Leaving stale verification tokens forever. Not harmful in itself, but a zone with 30 dead tokens is a zone nobody can audit. Remove them when you stop using the vendor.
- Publishing DMARC at the apex instead of `_dmarc`. A
v=DMARC1string atexample.comis invisible to every DMARC verifier. See DMARC record not found.
Check it with dig
# All TXT records at a name
dig +short cloudflare.com TXT
# Just the SPF record
dig +short cloudflare.com TXT | grep spf1
# DMARC policy
dig +short _dmarc.google.com TXT
# A DKIM key for a known selector
dig +short google._domainkey.stripe.com TXT
# Count how many SPF records exist — anything above 1 is a PermError
dig +short example.com TXT | grep -c 'v=spf1'
# Bypass caches and ask the authoritative server
dig +noall +answer @ns1.google.com _dmarc.google.com TXTFor a provider-by-provider walkthrough of publishing one, see Add a TXT record on Cloudflare, on Namecheap, or on GoDaddy.