TXT: arbitrary text
A name to a string. TXT was supposed to be a comments field; it grew up to be the carrier for SPF, DKIM, DMARC, ACME challenges, domain ownership proofs, and every other piece of structured metadata that someone decided should live in DNS.
| Type number | 16 |
| RFC | RFC 1035 §3.3.14 |
| RDATA | One or more character strings, each up to 255 bytes, concatenated by the consumer |
What it holds#
A sequence of <length><bytes> string segments. On the wire each segment is at most 255 bytes; consumers join the segments back together before parsing (display tools like dig show them as separate quoted strings). The string itself is opaque: the meaning is whatever convention the consumer adopts.
txt.example.isitdns.net. TXT "It was DNS. It is always DNS."
example.com. TXT "v=spf1 include:_spf.mailprovider.com ~all"
_dmarc.example.com. TXT "v=DMARC1; p=none; adkim=r; aspf=r"
_acme-challenge.example.com. TXT "abc123..."When you'll use it#
The four big uses:
| Purpose | Pattern |
|---|---|
| SPF | <domain> TXT "v=spf1 ..." (one record per domain max) |
| DKIM | <selector>._domainkey.<domain> TXT "v=DKIM1; k=rsa; p=..." |
| DMARC | _dmarc.<domain> TXT "v=DMARC1; ..." |
| ACME DNS-01 | _acme-challenge.<name> TXT "<base64url digest>" (RFC 8555 §8.4): added and removed by your ACME client (certbot etc.) during cert issuance |
| Domain verification | <vendor>=<token> at the apex (Google, Microsoft, Apple, and many more); some vendors want the token at a dedicated underscore subdomain instead, so follow their instructions exactly |
A simple example you can query right now:
dig @1.1.1.1 txt.example.isitdns.net TXT +short"It was DNS. It is always DNS."nslookup -type=TXT txt.example.isitdns.net 1.1.1.1Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
txt.example.isitdns.net text = "It was DNS. It is always DNS."When not to use it#
- For machine-discoverable services with well-defined record types (SRV, CAA, HTTPS/SVCB, etc.): don't reach for TXT when a typed record exists.
- For ownership records that already have a typed alternative: e.g., don't put a host's address in TXT.
- For anything secret. DNS is public. Putting secrets in TXT is putting them in
digoutput for everyone. See query-types for how resolvers and caches expose every answer they receive.
dig examples#
Apex SPF#
dig @1.1.1.1 example.com TXT +short"v=spf1 -all"
"_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"nslookup -type=TXT example.com 1.1.1.1Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
example.com text = "v=spf1 -all"
example.com text = "_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"DKIM at a selector#
dig @1.1.1.1 sig1._domainkey.example.com TXT +short"v=DKIM1; p="nslookup -type=TXT sig1._domainkey.example.com 1.1.1.1Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
sig1._domainkey.example.com text = "v=DKIM1; p="An empty p= field means the key has been revoked (RFC 6376 §3.6.1). A validly publishing domain would show a Base64-encoded RSA or Ed25519 public key there.
ACME DNS-01 challenge (mid-renewal)#
dig @1.1.1.1 _acme-challenge.example.com TXT +short"12Z-wRjmkwPupycBbFJ3ZjujOps9gCGmBPj9BzUSvyA"
"DUB6OB4ruWFHMZ7mVn1z01dC6kZBeCjthZsKCP94VjE"
"EHeiHtGZ-zmDoSCWFUlc59SAmtiZVEDwHB1kos0M76Y"
"Y1I_ADGr2MsnUUJs7A0wu5dnKYzRPz-YcQRIjuSzXN4"nslookup can show this, but the output is verbose. Use
dig +shortfor scripts.
Multiple tokens appear when several certificates are being validated at once. Wildcards also land here: *.example.com validates at _acme-challenge.example.com with the *. stripped (RFC 8555 §7.1.3), so a combined example.com + *.example.com order leaves two tokens at the same name. The CA accepts when any one of the published records matches its challenge (RFC 8555 §8.4).
DMARC#
dig @1.1.1.1 _dmarc.example.com TXT +short"v=DMARC1;p=reject;sp=reject;adkim=s;aspf=s"nslookup -type=TXT _dmarc.example.com 1.1.1.1Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
_dmarc.example.com text = "v=DMARC1;p=reject;sp=reject;adkim=s;aspf=s"DoH query (HTTPS)#
DoH is just DNS-over-HTTPS. The JSON format uses application/dns-json, a Cloudflare/Google extension not mandated by RFC 8484:
curl -s -H 'accept: application/dns-json' \
'https://cloudflare-dns.com/dns-query?name=txt.example.isitdns.net&type=TXT' \
| jq .Answer[
{
"name": "txt.example.isitdns.net",
"type": 16,
"TTL": 300,
"data": "\"It was DNS. It is always DNS.\""
}
]The TTL field is the time remaining in the resolver's cache: a cache miss shows the record's full 300, and repeat queries count down from there.
nslookup cannot do DoH/DoT/DoQ. On Windows,
Resolve-DnsNameuses the system-configured DoH resolver when the OS is set up for encrypted DNS; there is no-DnsOverHttpsparameter and it does not accept an arbitrary endpoint as-Server. To probe a specific DoH service, use thecurlform above.
Gotchas#
- 255-byte string limit. A TXT record can hold multiple 255-byte strings, but a single string is capped at 255. Long DKIM public keys (2048-bit RSA) exceed 255 bytes and must be split using quoted-string concatenation in the zone file: ``
text selector1._domainkey TXT "v=DKIM1; k=rsa; p=ABC..." "DEF...XYZ"`` Consumers join consecutive strings before parsing. Whether the split happens for you depends on the provider: some management UIs split long strings automatically on input, others (and hand-written zone files) make you write the quoted segments yourself. - One SPF per domain. Multiple SPF TXT records at the same name is invalid per RFC 7208 §3.2; receiving servers will (correctly) treat it as a
permerror. If you need multiple include rules, combine them:v=spf1 include:a include:b ~all. - There is no SPF record type anymore. A dedicated
SPFRRtype (type 99) existed during SPF's experimental phase; it was discontinued, and SPF data must be published as TXT only (RFC 7208 §3.1). If your DNS provider still offers a record type named SPF, skip it. - Case-insensitive name, case-preserving RDATA. DNS names are case-insensitive; TXT strings are case-sensitive. ACME, DKIM, etc. all care about exact bytes.
- Quoting and escaping. Spaces inside TXT must be inside quotes. Backslashes escape special characters. A TXT with literal
"needs\". Most DNS-management APIs accept the raw string and handle escaping for you. - Public. Already said it. Repeating because someone always tries.
- DMARC must live at
_dmarc.<domain>: not at the apex. SPF must live at the apex. DKIM at<selector>._domainkey.<domain>. Misplacing any of these silently disables email auth. See email-records for the full placement rules. - TTL matters for ACME. A high TTL (e.g., 3600) lets resolvers cache the old token, or a negative answer from before the record existed, long after your client publishes a fresh one; validation and pre-checks then see stale data until the cache expires. Keep
_acme-challengeTTL at 60-300 seconds. - Verification tokens accumulate. Apex TXT sets grow one
<vendor>=<token>at a time and nobody deletes them. Prune tokens for services you no longer use: every TXT query for the name (including every SPF check) hauls back the whole set.