What's the limit of what can be in a TXT record?
Some places say 255 bytes. They are wrong. Within a TXT record there are multiple character-strings (RFC 1035 section 3.3.14) and those are limited in length, however there can be many of them.
The actual limit is limited by the size of the DNS payload, which for UDP is these days around 1232 bytes. That is obviously quite low. However if we use TCP, which doesn't require anything special, other than the normal fallback to TCP that DNS does, then we can serve up to 64KB.
I set out to demonstrate exactly that, by using Google Public DNS's JSON API and then serving large TXT responses over TCP, from a custom server.
This mostly just works, the main issue is not with the length, but with binary data, because JSON isn't really designed to handle binary data. Therefore there is some slightly custom JSON parsing. Using raw binary data in a TXT record avoids the overhead of Base64 or another encoding, meaning more data can be packed in.
👉 See it in action. For more read the comments in image.html.
Non-browser
It is possible to query this via dig. Although turning it back into binary output is a bit tricky, as the presentation form of DNS responses is escaped for output.
You can retrieve the data with dig and a little Perl to unescape and combine the character sequences:
$ dig +short dog.log.battery.st TXT | perl -pe'chomp; s/" "//g; s/^"//; s/"$//; s/\\(\d{3})/chr $1/eg; s/\\([\\"])/$1/g' > dog.avif $ sha256sum dog.avif 7058fbd20ef2af84d5efb0ae7d91f87ce7a912380636c468b32f2c759cbb9130 dog.avif(This is actually just a modified version of the Perl one liner from my Wikipedia over DNS from 2008, nothing changes.)
Because the web version uses Google's JSON resolver we know it doesn't have problems querying very large TXT records, however your local recursor may not support this. If it doesn't work you can add @dns.google to the dig command line to send the query to Google's Public DNS servers (or any other open recursor, @9.9.9.9 seems to work too).
Why?
I thought it was a cute hack when I realised it was possible.
For those interested in security there is a consideration here, attackers have long tunnelled over DNS, but tunnelling large payloads to a browser is potentially something new. Because Google Public DNS has a certificate that includes 8.8.8.8 and so on, traffic can go directly from a browser without a DNS lookup. This may be unexpected in environments that use DNS filtering. This is something that will become more common once Lets Encrypt fully rolls out IP address certificates, the differnce here is piggybacking on an existing IP address certificate.
This deliberately uses a low TTL (10 seconds) to avoid filling DNS recursor's caches with useless content. It would be possible to increase this and therefore get caching from the recursors, a bit like a free distributed CDN (although I suspect if someone actually did this they would adaptively limit TTLs, if something like that isn't already done).
Server side
The server is a custom Go DNS server. To be honest it was written by ChatGPT because it's not that clever, the idea is what matters. (Although ChatGPT did get some details like truncation wrong so I fixed the code myself.)
All the code is here. AI was only used for the server component, this blog post and the client HTML code is my own work.
20th September 2025