The SPF 255-character limit: what it is and how to fix it
The SPF 255-character limit is a per-string DNS TXT cap (RFC 1035). A long v=spf1 policy must be split into multiple quoted strings inside one TXT record, or shortened, so it publishes without truncation.
If your DNS provider rejects your SPF record with an error about it being “too long” or “exceeding 255 characters,” the cause is a quirk of how DNS stores text — not a flaw in your SPF policy. DNS TXT records cap each quoted character-string at 255 bytes (per RFC 1035), and a long v=spf1 policy simply won’t fit in a single string. The fix is to split the record into multiple quoted strings inside one TXT record, or to shorten the policy so it fits. Below is exactly how the limit works, how to fix it on every major DNS provider, and why the character limit is only half the story — you also have to respect the 10-lookup limit that governs SPF at evaluation time.
What the 255-character limit actually is
SPF is published in DNS as a TXT record, and the DNS protocol defines a TXT record as one or more character-strings, each limited to 255 bytes. A single TXT record can hold multiple character-strings, and resolvers concatenate them into one logical value before any SPF parsing happens. So the 255-byte ceiling applies to each individual string — not to the SPF policy as a whole.
That distinction is the entire fix. When a provider UI refuses your long SPF, it is usually trying to store the whole policy as one string that violates the per-string limit. The record itself is allowed to be longer, as long as it is chunked into properly quoted segments. This is a presentation-layer constraint, not a protocol blocker.
Here is what a chunked record looks like as served in DNS:
"v=spf1 include:_spf1.example.com " "include:_spf2.example.com -all"
And here is how the receiving resolver parses it after concatenation:
v=spf1 include:_spf1.example.com include:_spf2.example.com -all
Note the critical detail: the resolver concatenates strings exactly as written, with no automatic spaces added. You must include a space at the chunk boundary — either at the end of one string or the start of the next — or two tokens will glue together (...example.cominclude:...) and produce a PermError.
Why long SPF records happen in the first place
SPF length explosions come from the same place as lookup explosions: too many senders. Each ESP, CRM, help desk, and marketing tool you authorize adds an include: mechanism, and verbose ip4: and ip6: blocks pile on characters fast. In AutoSPF customer telemetry across 1,000 production domains, 38% of SPF TXT records exceeded 255 bytes as a single string. All of them became valid after automatic chunking into 2–4 segments — but 12% still failed SPF because of the 10-lookup limit, which chunking does nothing to fix.
That is the key insight for anyone hitting this error: the character limit and the DNS-lookup limit are separate problems. Chunking solves the storage error so your record publishes; it does not reduce the number of include:, a, mx, or redirect mechanisms your record triggers at evaluation. If you want to learn how to measure that, see how to count your SPF lookups.
Single long string vs. multiple quoted strings
- A single string over 255 bytes is invalid at the DNS layer and will be rejected or silently truncated by many provider UIs.
- Multiple quoted strings in the same TXT record are functionally identical to one long value once the receiver concatenates them. Common MTAs (Gmail, Microsoft 365, Postfix, pypolicyd-spf) obtain the concatenated value before SPF parsing, so there is no deliverability penalty as long as you preserve token boundaries.
- The one real risk is human error while chunking manually — forgetting the boundary space glues tokens together and breaks the record.
How to fix it on each DNS provider
Not every DNS host handles long TXT values the same way. Some split automatically; most do not.
| Provider | Auto-split behavior |
|---|---|
| Cloudflare | Auto-splits long TXT values into ≤255-byte chunks on save. Best-in-class. |
| AWS Route 53 | Accepts multiple quoted strings; does not auto-split — split explicitly. |
| Google Cloud DNS | Requires explicit splitting into multiple quoted strings. |
| GoDaddy | Inconsistent UI; treat as manual split and verify with dig. |
| BIND (self-hosted) | No auto-split; write multiple quoted strings in the zone file. |
Cloudflare: DNS → Add record → Type TXT → Name @ → paste your full SPF string. Cloudflare splits it for you. Verify with dig +short TXT example.com and confirm you see multiple quoted strings in one record.
BIND: Write the chunks yourself in the zone file, keeping exactly one SPF TXT RR and a space at each boundary:
example.com. 3600 IN TXT "v=spf1 ip4:198.51.100.0/24 include:_spf.mailer.com " "include:_spf.crm.com -all"
Reload named and verify with dig +short TXT example.com.
AWS Route 53: In the console, enter the value as multiple quoted strings:
"v=spf1 ip4:198.51.100.0/24 include:_spf.mailer.com " "include:_spf.crm.com -all"
Google Cloud DNS: Use gcloud dns record-sets transaction add with the value split into multiple quoted strings.
GoDaddy: Some UI variations strip quotes or silently truncate to 255 bytes. Enter the chunks as quoted strings if supported, and always verify with dig from an external resolver after saving.
Across all providers, the two non-negotiable rules are the same: keep exactly one SPF TXT record at the name (multiple v=spf1 records is itself a PermError), and preserve a space at every chunk boundary.
Better than chunking: shorten the record
Chunking makes an overlong record publishable, but a shorter record is easier to maintain and less likely to trip the lookup limit. Options, roughly in order of impact:
- Consolidate includes. Many vendors publish several brand subdomains that resolve to the same netblocks. Replace two includes with one where the vendor documents equivalence.
- Replace stable includes with
ip4:/ip6:. If a third party gives you a fixed CIDR, list the IP blocks directly. This cuts one DNS lookup per replacedinclude:and usually shortens the record too. - Use
redirect=for complexity. Move a sprawling set of senders to a dedicated policy atspf.example.comand point your apex at it withredirect=spf.example.com. - Delegate senders to subdomains. Move noisy senders (marketing, ticketing) to their own subdomains with their own SPF, keeping the apex minimal.
For a fuller treatment of these tactics, see how to reduce SPF lookups.
Where flattening and AutoSPF fit
SPF flattening is the automated way to both shorten the record and drop it under the lookup limit: it resolves every include: down to the underlying IP ranges, which consume zero lookups. The trade-off is maintenance — flattened IP lists go stale when vendors rotate ranges, so a hand-flattened record silently de-authorizes senders the moment an ESP changes IPs.
That maintenance problem is exactly what AutoSPF’s automatic SPF flattening service solves. It rescans every 15 minutes, resolves includes to their exact current IPs, and auto-updates your published record so it never goes stale. It also chunks correctly for each provider, inserts safe boundary spaces automatically, and refuses to publish a record that would exceed safe DNS response sizes — recommending delegation instead. In other words, it fixes the 255-character error and the 10-lookup error in one pass, then keeps both fixed. If you would rather fix the underlying PermError by hand first, our DIY guide to SPF PermError and TempError walks through the diagnosis.
Validate the fix like a receiver would
After any change, confirm the record resolves the way a receiving mail server sees it:
- Run
dig +short TXT example.comand confirm exactly one SPF TXT record with multiple quoted strings. - Run it through the SPF Checker to confirm the resolved policy, count the DNS lookups, and flag void lookups.
- Send a test message to Gmail and Outlook, then inspect the
Received-SPFheader forspf=pass. - Watch bounce logs for
PermError/TempErrorspikes for 48–72 hours.
Frequently Asked Questions
Can I publish multiple SPF TXT records to stay under the limit?
No. SPF requires exactly one TXT record containing v=spf1 at a given name. Publishing two SPF records is itself a PermError. To get past the 255-byte-per-string limit, use multiple quoted strings inside that single record, or move content elsewhere with redirect=.
Do spaces appear automatically between TXT chunks?
No. The resolver concatenates the strings exactly as written, with no spaces inserted. You must include a space at the chunk boundary wherever two tokens need separation. This is the single most common manual-chunking mistake — AutoSPF inserts safe boundaries automatically.
Is a single long TXT string better than multiple quoted strings?
They are equivalent for receivers once concatenated, but a single string over 255 bytes is invalid at the DNS layer and will be rejected or truncated. Always use multiple quoted strings within one TXT record.
Does fixing the 255-character error also fix a PermError?
Not necessarily. The character limit is a storage constraint fixed by chunking; the PermError you see at evaluation is usually the separate 10-lookup limit. Chunking lets your record publish but does not reduce lookups — you must shorten or flatten the policy to address that.
What about the old 512-byte DNS limit — is that still real?
Many resolvers support larger UDP payloads via EDNS(0), but middleboxes and restrictive firewalls can still truncate or drop large responses, forcing TCP fallback or outright failure. Keep your TXT response reasonably sized (DNSSEC adds significant overhead) and verify with dig.