Type something to search...
What is a TXT record and what is it used for?

What is a TXT record and what is it used for?

A TXT record is a DNS record that holds free-form text attached to a domain name. It was originally meant for human-readable notes, but today it's mostly used to publish machine-readable information that other services look up: email authentication policies such as SPF, DKIM and DMARC, proof that you own a domain, certificate validation tokens, and security policies for mail transport. Any system that can query DNS can read a TXT record, which makes it a convenient place to publish small pieces of public configuration.

Because so many services rely on TXT records, most domains end up with several of them, and it's easy to break something with a stray quote or a duplicate entry. In this article you'll learn how TXT records are structured, the length limits that catch people out, the most common uses and the naming conventions behind them, how to query and manage TXT records with command-line tools and APIs, and how to keep them tidy and secure.

How a TXT Record Is Structured

In a zone file, a TXT record looks like this:

example.com.    3600    IN    TXT    "v=spf1 include:_spf.example.net -all"
  • example.com.: The name the record belongs to. TXT records can live on the root domain or on any subdomain, such as _dmarc.example.com.
  • 3600: The TTL in seconds.
  • TXT: The record type.
  • "v=spf1 ...": The data, written as one or more quoted character strings.

A name can hold multiple TXT records. Each one is returned separately, and the systems that read them pick out the one they care about, usually by looking for a known prefix such as v=spf1 or v=DMARC1:

example.com.    3600    IN    TXT    "v=spf1 include:_spf.example.net -all"
example.com.    3600    IN    TXT    "example-verification=8f3c2a9d71b04e6f"
example.com.    3600    IN    TXT    "another-service-site-verification=Qm9vMTIz"

The 255-Character Limit

The underlying DNS format (RFC 1035) stores each character string with a one-byte length prefix, so a single string can be at most 255 bytes long. A single TXT record can contain several strings, though, and that's how long values such as 2048-bit DKIM keys are published:

selector1._domainkey.example.com.  3600  IN  TXT  ( "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7Zx"
    "Jq0nK3vB1sR4mT8wLpXc2E5fH9uV6aN0dG7iY3kO1rZ4bQ8sW2eC5nM9hJ6tF0gP3vL7xK1yD4aS"
    "...remaining key data..." )

The parentheses only let the record span several lines in the zone file. On the wire, this is one TXT record containing several strings.

How those strings are joined depends on the protocol reading them. SPF (RFC 7208) and DKIM (RFC 6376) both say the strings are concatenated with no space between them, so you can split anywhere. Other consumers may treat each string separately, so only split values when the service you're configuring tells you to, or when the value is too long to fit.

Overall Size

There's no fixed limit on the total size of a TXT record set beyond the general 65,535-byte limit for DNS records, but large answers have practical costs. Responses over roughly 1,232 bytes risk being truncated over UDP, which forces resolvers to retry over TCP. If a single name holds dozens of verification strings, every SPF lookup against it has to download all of them. That's a good reason to keep the root domain lean.

What TXT Records Are Used For

Most TXT uses follow a naming convention: either a prefix in the value (such as v=spf1) or a special underscore label in the name (such as _dmarc). Underscore labels keep each service's data on its own name, so lookups return only the record that matters.

UseNameExample value
SPFexample.comv=spf1 include:_spf.example.net -all
DKIMselector._domainkey.example.comv=DKIM1; k=rsa; p=MIIB...
DMARC_dmarc.example.comv=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
Domain verificationUsually example.comvendor-verification=abc123
ACME DNS-01 challenge_acme-challenge.example.comA one-time token from the CA
MTA-STS_mta-sts.example.comv=STSv1; id=20261013T0100
SMTP TLS reporting_smtp._tls.example.comv=TLSRPTv1; rua=mailto:tls-reports@example.com
BIMIdefault._bimi.example.comv=BIMI1; l=https://example.com/logo.svg

Email Authentication

The single biggest use of TXT records is email. SPF lists the servers allowed to send mail for your domain and sits on the domain itself. DKIM publishes public keys at a selector under _domainkey. DMARC sits at _dmarc and tells receivers what to do when SPF and DKIM checks fail. Each has its own detailed rules, but from a DNS point of view they're all just TXT records at particular names.

The most important TXT rule for email is that a domain must have only one SPF record. Two TXT records starting with v=spf1 cause SPF to return a permanent error. If a new service asks you to "add an SPF record", merge its include: into your existing record rather than creating a second one.

Domain Ownership Verification

Cloud services, search consoles, and SaaS platforms often ask you to prove you control a domain by publishing a random token they give you. They then query DNS for it. Because only someone with access to your DNS can add the record, its presence is proof of control. These tokens are usually harmless to leave in place, but they accumulate over the years.

Certificate Validation With ACME

Certificate authorities such as Let's Encrypt can validate domain control with the DNS-01 challenge. Your ACME client creates a TXT record at _acme-challenge.<name> containing a token derived from the challenge, the CA checks it, and the client removes it afterwards. DNS-01 is the only ACME method that can issue wildcard certificates, and it works for servers that aren't reachable from the internet.

With Certbot and a DNS plugin, the TXT record is created and cleaned up automatically:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

Mail Transport Security

MTA-STS uses a TXT record at _mta-sts to announce that a policy exists and to signal when it changes, through the id value. The policy itself is served over HTTPS. TLS-RPT uses a TXT record at _smtp._tls to tell other mail servers where to send reports about TLS failures when delivering to you.

Service Discovery and Notes

TXT records are also used alongside SRV records in DNS-based service discovery to carry key-value metadata about a service. And you'll still occasionally see plain notes, such as a contact address or a description, which is what the record type was originally for.

Querying TXT Records

Using dig

dig example.com TXT +noall +answer
example.com.        3600    IN    TXT    "v=spf1 include:_spf.example.net -all"
example.com.        3600    IN    TXT    "example-verification=8f3c2a9d71b04e6f"

For a record at an underscore name, query that name directly:

dig _dmarc.example.com TXT +short
"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

When a record is split into multiple strings, dig shows each string in its own set of quotes:

"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEF" "AAOCAQ8AMIIBCgKCAQEAy7Zx..."

That's normal, and it isn't two separate records.

Using nslookup and PowerShell

nslookup -type=txt example.com
Resolve-DnsName -Name _dmarc.example.com -Type TXT | Select-Object -ExpandProperty Strings

Checking for Duplicate SPF Records

A quick shell one-liner counts the SPF records on a domain. Anything other than 1 needs attention:

dig example.com TXT +short | grep -c '"v=spf1'

Creating TXT Records

In a Zone File

If you run BIND or another server that uses zone files, add the record, increment the SOA serial, then check and reload the zone:

_mta-sts.example.com.      3600  IN  TXT  "v=STSv1; id=20261013T0100"
_smtp._tls.example.com.    3600  IN  TXT  "v=TLSRPTv1; rua=mailto:tls-reports@example.com"
sudo named-checkzone example.com /etc/bind/zones/db.example.com
sudo rndc reload example.com

Watch out for quotes inside values. If a value genuinely needs a double quote, escape it as \". A semicolon outside quotes starts a comment in zone files, which is another reason to always quote TXT data.

Through a Provider API

Most DNS hosts let you create TXT records through an API. With Cloudflare, for example:

curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "TXT",
    "name": "_dmarc.example.com",
    "content": "\"v=DMARC1; p=none; rua=mailto:dmarc@example.com\"",
    "ttl": 3600
  }'

In web dashboards, you usually paste the value without quotes and the provider adds them. If you paste quotes into a field that adds its own, you can end up with literal quote characters in the data, which breaks parsers such as SPF. Always query the record afterwards to see what was actually published.

With Terraform on Route 53

Route 53 requires TXT values to be quoted, and long values to be split. In Terraform, the aws_route53_record resource adds the outer quotes for you, and you split a long value into multiple strings by inserting \"\" where you want the break:

resource "aws_route53_record" "dkim" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "selector1._domainkey.example.com"
  type    = "TXT"
  ttl     = 3600
  records = [
    "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7Zx\"\"Jq0nK3vB1sR4mT8wLpXc2E5fH9uV6aN0dG7iY3kO1rZ4bQ8sW2eC5nM9hJ6tF0gP3vL7xK1yD4aS"
  ]
}

All TXT records for one name go into a single aws_route53_record resource as separate entries in the records list, because Route 53 manages them as one record set.

Keeping TXT Records Tidy and Secure

TXT records are public. Anyone can list the ones on your root domain, and that reveals a surprising amount: which email provider you use, which marketing tools send for you, which cloud and SaaS vendors you've signed up for. Attackers use this for reconnaissance and to craft more convincing phishing.

A few habits help:

  1. Audit regularly: Remove verification tokens for services you no longer use and include: entries for retired senders.
  2. Prefer subdomain-scoped tokens: Where a service lets you verify on an underscore subdomain rather than the root, choose that. It keeps the root small and its answer fast.
  3. Keep one SPF record: Merge rather than add.
  4. Remove ACME tokens: ACME clients normally clean up, but failed runs can leave stale _acme-challenge records.
  5. Protect your DNS account: Because TXT records prove domain ownership to so many services, anyone who can edit them can claim your domain elsewhere. Use two-factor authentication and limit API tokens to the zones and permissions they need.

Checking What a Domain Reveals

This small Python script pulls the TXT records from a domain's root and a few well-known underscore names, so you can see your public footprint at a glance:

import sys

import dns.resolver

NAMES = ["", "_dmarc.", "_mta-sts.", "_smtp._tls.", "default._bimi."]


def txt_values(name):
    try:
        answers = dns.resolver.resolve(name, "TXT")
    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
        return []
    return [b"".join(r.strings).decode("utf-8", "replace") for r in answers]


domain = sys.argv[1] if len(sys.argv) > 1 else "example.com"
for prefix in NAMES:
    name = prefix + domain
    for value in txt_values(name):
        print(f"{name:<32} {value}")
pip install dnspython
python txt_audit.py example.com

Note how the script joins the strings with b"".join(...). That mirrors how SPF and DKIM consumers reassemble a split record.


FAQ: TXT Records

Yes. A name can hold many TXT records, and each service looks for the one it needs. The exception is SPF, where you must have only one record starting with v=spf1 on a given name.

Each character string inside a TXT record is limited to 255 bytes, but a record can contain several strings. Long values such as DKIM keys are split into multiple strings that the reading software joins back together.

In zone files, yes. In web dashboards it depends on the provider. Most add quotes automatically, so check the published record with dig afterwards to make sure no literal quote characters ended up in the value.

Usually, yes, once you've stopped using the service. Some services recheck verification periodically, so if you still use one, removing its token may cause it to mark your domain as unverified.

Underscore labels give each protocol its own name, so a lookup returns only that protocol's record. They also can't clash with normal hostnames, because hostnames aren't allowed to contain underscores.

A brand new name is usually visible within minutes, limited only by how quickly your provider publishes changes and by any negative caching from earlier lookups. Changes to an existing record depend on its TTL.


Conclusion

A TXT record is simply text attached to a DNS name, but it has become the standard place to publish email policies, ownership proofs, certificate challenges and transport security settings. Understanding the 255-byte string limit, the underscore naming conventions, and the one-SPF-record rule covers most of what you need to manage them confidently.

Treat your TXT records as public configuration that deserves regular review. Query them after every change, remove entries for services you've stopped using, and protect the account that controls them, because whoever can edit your TXT records can prove they own your domain.

Tags :
Share :

Related Posts

What is the difference between an A record and a CNAME record?

What is the difference between an A record and a CNAME record?

The difference between an A record and a CNAME record is what they point to. An A record points a hostname directly at an IPv4 address, such

Dive Deeper
What are the best DNS providers for websites?

What are the best DNS providers for websites?

The best DNS providers for most websites are Cloudflare for a fast, free, easy starting point, Amazon Route 53 if you already run on AWS, **G

Dive Deeper
What are the best public DNS resolvers?

What are the best public DNS resolvers?

The best public DNS resolvers for most people are Cloudflare (1.1.1.1) for speed and privacy, Google Public DNS (8.8.8.8) for reliability and

Dive Deeper