SPF flattener
Get an SPF record under the 10-lookup limit by replacing includes with the IP addresses they publish today. Only exact replacements, kept in place and split into records that fit one DNS packet.
By using these tools you accept the Terms and the Privacy page.
How the SPF flattener builds your records
The SPF flattener reads your SPF record and every record it includes, works out which lookup terms can be swapped for the networks behind them without changing any SPF result, and writes the records to publish. It is for domains over the 10-lookup limit that have run out of other fixes.
Choosing what to replace
Below the current record, a table lists every term that costs lookups (each include, a, mx, exists, ptr and redirect=) with its lookups and the number of networks behind it. Includes and redirects that can be copied exactly are ticked. Your own a and mx terms show Exact, optional when their addresses can be looked up, and stay unticked: you run those servers, so flatten them only if their addresses rarely change. A term marked Keep can’t be copied. A redirect= that can be copied in brings its target’s terms in after your own, and their lookup terms get rows of their own. The records are rebuilt as you tick and untick.
How the new records stay exact
- Your own terms keep their order and qualifiers. Copied networks take the place of the terms they replace and never move past a term that is kept, such as an include with macros or
exists, because that term can end the check for some senders. - Duplicate networks, and networks already covered by a larger one, are dropped. Merging joins two halves of a larger block only when the result covers exactly the same addresses, and you can turn it off.
- Terms after
all, and aredirect=next toall, are left out, because receivers ignore them. - Names built with macros, including the
%%,%_and%-escapes, are never copied, and aredirect=target that uses%{d}or%{p}isn’t copied in, because those would mean your domain once moved. - Each record is sized the way RFC 7208 §3.4 counts it: the name, the text and a length octet per 255-character string, under 450 octets. When your main record would be longer, the longest runs of networks move to
_spfrecords first. The page also warns when your other TXT records at the domain, such as verification codes, push the answer over. - The new records are re-counted the way receivers count, with live DNS for every other name. The page warns when an
_spfname already holds a different SPF record.
When flattening won’t help
If the record needs no lookups at all, there is nothing to flatten. If the extra records cost as many lookups as they save, the summary says flattening wouldn’t lower the count. If the record is still over 10 after every exact replacement, it says that too: remove includes you no longer use, or move a sender to a subdomain. A record with a syntax error, no SPF record or more than one has to be fixed first; the SPF checker marks the broken term.
Saving the result
Copy report gives the counts before and after, the reason each term was kept and every zone-file line, ready for a change ticket. Copy all zone lines copies just the records, and JSON saves the details. After you publish, send a message to the email test to see SPF checked on real mail.
Updated · Maintained by Liviu Tanase
Questions
When should I flatten, and when not?
Flatten only when the record needs more than 10 DNS lookups and you can’t get under the limit another way. First remove includes for services you no longer use, and move bulk or marketing mail to a subdomain (such as news.example.com) with its own SPF record. Those fixes don’t go stale. If the record already uses 8 or fewer lookups, don’t flatten: you gain nothing and take on upkeep.
How do I fix “SPF permerror: too many DNS lookups”?
Receivers return permerror when checking your record needs more than 10 DNS lookups, nested includes counted. Enter your domain here or in the SPF checker to see the count and what each term costs. Then, in this order: remove includes for services you no longer use, replace a and mx for your own servers with ip4/ip6, move a bulk sender to a subdomain with its own record, and only then flatten the includes this page marks Exact. The new records are re-counted the way receivers count before you publish; afterwards the email test shows SPF checked on real mail.
Will flattening change which senders pass SPF?
Not for the terms it replaces. An include is copied only when its pass result is a fixed list of networks, copied networks stay where the include was (they never move past a term that is kept), and a network already covered by an earlier one is dropped because it can never match first. What changes is the cost: the copied includes no longer use lookups or void lookups, so senders that got permerror for going over a limit get your record’s real answer. The risk is time: when a provider adds addresses, your copy doesn’t have them.
Why is there a 10-lookup limit?
Each include, a, mx, ptr, exists and redirect makes the receiving server query DNS while your message waits. RFC 7208 §4.6.4 caps them at 10 per check, nested includes counted, so one record can’t be used to flood DNS servers or stall mail. A check that needs an 11th lookup ends in permerror, which DMARC treats as an SPF fail. ip4 and ip6 cost nothing, which is why flattening works.
Which includes can’t be flattened?
An include matches only when the included record returns pass (RFC 7208 §5.2), so only the addresses it passes can be copied: ip4 and ip6 terms with a pass qualifier, and a and mx resolved to their addresses. An include is kept when it uses exists, ptr or macros such as %{i}, which are worked out per message, when a -, ~ or ? term comes before a pass term it could overlap, when part of it is broken (a missing record, a loop or a failed lookup), or when it passes more than 1,000 networks, more than 10 extra records could hold. The table says why for each one.
What breaks when a provider changes its IP addresses?
Mail from the new addresses fails SPF, because your copy still lists the old ones. If the message is DKIM-signed with your domain, DMARC can still pass on DKIM; if not, receivers may reject or junk it. Nothing warns you: the first sign is usually bounces or lower inbox placement. Keep your original record so you can roll back in minutes.
How often should I re-check?
At least once a week, and whenever a provider tells you about new addresses. Open this page with your domain (the link keeps it), compare the records with what you published, and publish again if they differ. Providers change their ranges without asking you first, so a flattened record needs a calendar reminder.
How do the _spf1 and _spf2 records work?
RFC 7208 §3.4 asks that a name plus its TXT records stay under 450 octets, so the DNS answer fits one 512-byte UDP packet; this page counts the name, the record and one length octet per 255-character string. When the networks don’t fit your main record, the longest runs of them go into extra records named _spf1.example.com, _spf2.example.com and so on, and your main record includes them. Each holds only ip4 and ip6 terms and no all, so including it matches exactly when the sender is in one of its networks. Each costs one lookup. Publish them first, then replace the main record. Most DNS dashboards want only the part before your domain, such as _spf1.
Is anything sent to zerobounce.ai?
No. The page works in your browser: DNS questions go from your browser to Cloudflare’s public DNS-over-HTTPS resolver, or to Google’s if Cloudflare doesn’t answer, and the records are built on the page. The domain isn’t sent to zerobounce.ai unless it is in a link you open (a shared result, for example), which appears in the request logs described on the privacy page.