DNS TXT records are one of the most versatile tools in the domain management toolbox. Originally designed to hold human-readable text, they’ve evolved into the backbone of email authentication (SPF, DKIM, DMARC) and domain ownership verification. If you’ve ever connected a domain to Google Workspace, verified a site in Search Console, or set up a custom sender for an email marketing platform, you’ve used a TXT record.
This guide explains how TXT records work under the hood and why they’re the preferred method for domain ownership verification at scale.
What Is a DNS TXT Record?
A TXT record is a type of DNS resource record that stores arbitrary text data associated with a domain name. The DNS specification (RFC 1035, extended by RFC 1464) allows TXT records to hold up to 255 characters per string, with multiple strings allowed per record.
In practice, a TXT record for domain verification looks like this:
example.com. 300 IN TXT "domchekr-verification=7f3a9b1c2e4d5f6a"Breaking this down:
example.com.— the domain name (note the trailing dot, which is standard DNS notation)300— TTL in seconds (how long resolvers cache this record)IN— Internet classTXT— record type"domchekr-verification=7f3a9b1c2e4d5f6a"— the record data
How to Query TXT Records
Using dig
dig TXT example.comOutput:
;; ANSWER SECTION:example.com. 300 IN TXT "domchekr-verification=7f3a9b1c2e4d5f6a"example.com. 300 IN TXT "v=spf1 include:_spf.google.com ~all"A domain can have multiple TXT records — all of them are returned in the query response.
Using nslookup
nslookup -type=TXT example.comProgrammatically in Node.js
import { promises as dns } from 'dns';
async function getTxtRecords(domain: string): Promise<string[][]> { try { return await dns.resolveTxt(domain); } catch (err) { if ((err as NodeJS.ErrnoException).code === 'ENOTFOUND') { return []; // Domain doesn't exist } throw err; }}
async function verifyDomain(domain: string, token: string): Promise<boolean> { const records = await getTxtRecords(domain); return records.some(record => record.some(part => part.includes(`domchekr-verification=${token}`)) );}Note: dns.resolveTxt() returns a nested array — each outer element is a TXT record, and each inner element is a string part of that record (since TXT records can be split across multiple 255-byte strings).
Why TXT Records Are Ideal for Domain Verification
1. No Web Server Required
Unlike file-based or meta tag verification, TXT records don’t require the domain to have a running web server. This makes them perfect for domains used solely for email, subdomains under construction, or purely DNS-registered domains.
2. Survive Infrastructure Changes
Website migrations, server rebuilds, and CDN switches don’t affect DNS TXT records. Once set, a TXT record persists independently of where the website is hosted.
3. Highly Reliable
DNS is a globally distributed, highly redundant system. TXT record queries succeed even during partial network outages, making them more reliable than HTTP-based checks.
4. Easy to Automate
DNS APIs from providers like Cloudflare, Route 53, and Namecheap allow you to automate TXT record creation and deletion programmatically — enabling fully automated domain verification workflows.
Understanding DNS Propagation and TTL
DNS changes don’t take effect immediately worldwide. When you add or update a TXT record, the change propagates gradually as DNS resolvers around the world refresh their caches.
TTL (Time to Live) controls how long resolvers cache a record. A TTL of 300 means resolvers cache the record for 5 minutes before re-querying. A TTL of 86400 means 24 hours.
For domain verification, this means:
- Low TTL records (300–3600 seconds): Changes are visible within minutes globally.
- High TTL records (86400 seconds): Changes can take up to 24 hours to propagate everywhere.
Best practice for verification systems: Implement retry logic with exponential backoff. If a verification check fails, retry after 5 minutes, then 15, then 60, rather than marking it as permanently failed.
async function verifyWithRetry( domain: string, token: string, maxAttempts = 10): Promise<boolean> { const delays = [1, 5, 15, 30, 60, 120, 240, 480, 960, 1800]; // seconds
for (let i = 0; i < maxAttempts; i++) { const verified = await verifyDomain(domain, token); if (verified) return true;
if (i < maxAttempts - 1) { await new Promise(resolve => setTimeout(resolve, delays[i] * 1000)); } }
return false;}Security Considerations
Token Uniqueness
Each verification token must be globally unique and cryptographically random. A predictable token allows an attacker to guess or enumerate valid verification codes.
import { randomBytes } from 'crypto';
// Good: 128 bits of entropyconst token = randomBytes(16).toString('hex');
// Bad: predictableconst token = `${userId}-${Date.now()}`;Token Expiry
Tokens should expire after a reasonable time window (7–30 days). This limits the attack surface: even if a token is leaked, it becomes useless after expiry.
Continuous Monitoring
Domain ownership can change. After initial verification, periodically re-check TXT records. If the token disappears, trigger a re-verification flow and notify the domain owner.
Putting It All Together
TXT record verification is the most robust and developer-friendly method for proving domain ownership. It requires no web server, survives infrastructure changes, and integrates cleanly with DNS APIs.
If you’re building domain verification into your SaaS product, DomChekr handles all of this for you — including TXT record checking, retry logic, propagation monitoring, and webhook notifications — so you can ship faster and with confidence.