SPF flattener,
recursive & honest.
Type a domain. We pull the SPF record, recursively resolve every include:, redirect, a:, mx:, and exists: mechanism, count DNS lookups against the RFC 7208 §4.6.4 hard limit of 10, and show you the tree. If you are over 10, the record produces permerror at every receiver and your authentication is broken silently. We surface the offending include chain and produce a flattened version with the actual IP ranges in place of the includes.
Type your domain.
We will fetch the SPF record from DNS, parse it, and walk the include tree breadth-first, lookup-counting as we go. Most large senders run between 6 and 11 lookups; the silent failures cluster at 11 because one upstream include: target added a sub-include without notifying customers.
What flattening means.
SPF flattening is the practice of substituting include: mechanisms with the IP ranges they ultimately resolve to, producing a record that carries the same authorisation but consumes fewer DNS lookups at validation time. Useful, but not free of trade-offs.
The original SPF design assumes you trust the operators of the domains you include:. When you write include:_spf.google.com, you are saying "Google's mail-sending IPs are authorised to send for me, and I trust Google to keep that list current." Receivers do the recursive lookup at validation time; the IPs in _spf.google.com can change daily and your record stays correct without edits.
The cost is the lookup count. Every include: you add is one lookup, and every include: nested inside that include is another. RFC 7208 §4.6.4 caps the total at 10 lookups per evaluation. A typical SaaS-heavy sender (Google Workspace + Microsoft Exchange Online + SendGrid + a marketing platform) hits 8-12 lookups easily; once you cross 10, every receiver returns permerror and DMARC fails alongside.
Flattening trades flexibility for headroom. Instead of include:_spf.google.com consuming one lookup at validation time, you publish ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ... directly — the IPs that _spf.google.com currently resolves to. The lookup count drops to zero for that mechanism, but you now own the maintenance burden: when Google adds a new sending IP range, your flattened record does not know, and mail from the new range fails authentication until you update the record.
The honest take: flattening is a pragmatic answer to a real problem (lookup-limit exhaustion) but it is not a clean answer. Flattening service operators publish SPF records that include their flattened version of yours, which makes them another include: in your chain — they tell you it does not count toward your 10 because the flattening service shoulders the maintenance. Sometimes true, sometimes not, depending on how the flattener vendor's record is structured. The cleaner answer is usually to remove unused includes — the marketing platform you tested for two weeks three years ago, the analytics service that does not actually send from your domain, the legacy ESP you migrated off but kept "just in case". The tool below shows you the full tree so you can see what is in there and decide what to remove.
What counts toward the 10-lookup limit
Per RFC 7208 §4.6.4, the following mechanisms each consume one DNS lookup: include:, a:, mx:, exists:, ptr:, and redirect=. Sub-includes nested inside an include: target also count, recursively. The lookup is counted regardless of whether the underlying DNS query succeeds or fails or returns no answer.
The mechanisms that do not count: ip4:, ip6:, and the all qualifier. These are evaluated locally without DNS recursion, which is why flattening (substituting include: with the equivalent ip4:/ip6: ranges) reduces the lookup count.
Three failure modes the lookup count produces
Permerror at validation time. When a receiver evaluates SPF and the lookup count exceeds 10, the result is permerror per RFC 7208 §4.6.4. Most receivers treat permerror the same as fail for DMARC purposes; some treat it as none, which means SPF contributes nothing to authentication. Either way, the authentication chain weakens silently because permerror rarely surfaces in delivery logs the way fail does.
Inconsistent enforcement across receivers. Different receivers count slightly differently around edge cases — what happens when a sub-include returns NXDOMAIN, whether ptr mechanisms count when they fail to resolve, how to count timeouts versus refusals. The result is that a record at exactly 10 lookups passes at Gmail, fails at Microsoft, and passes intermittently at Yahoo. Drift toward 11+ resolves the inconsistency by failing everywhere, but the path between 10 and 11 is the most maddening operational state in the SPF universe.
Silent drift caused by upstream vendors. The most common cause of "SPF was working yesterday and broken today" is a third-party SPF target adding a sub-include without notification. SendGrid, Mailgun, Salesforce Marketing Cloud, and HubSpot have all done this in the past five years. The customer's record was at 9 lookups; the upstream added a sub-include; the customer's record is now at 11 lookups; the customer has no idea why DMARC suddenly started failing. The flattener below is the diagnostic that surfaces this in seconds.
The lookup count is the variable. The history is the answer.
The flattener returns the lookup count of the original record and the count of the flattened version. The number is simple. The interpretation is not always — flattening fixes the count but creates maintenance debt, and the right answer depends on whether the upstream vendors are stable or rotate IP ranges frequently.
The flattener takes your published SPF record, recursively expands every include: directive against the public DNS, and reports two numbers: the lookup count of the original record and the count of the flattened version. The lookup count is the variable that matters. SPF specification (RFC 7208) caps lookups at 10 — anything above produces a permerror result that receivers treat as authentication failure. The tool's job is simple. The interpretation of the result is not always.
Two readings of the same lookup count tell different stories. A lookup count of 12 from a domain that has not changed its SPF record in two years is a slow-motion failure that has been impacting deliverability for months and the operator has not noticed. The same count of 12 on a domain that just added Salesforce or HubSpot to its sender list is a fresh problem that is fixable by removing the legacy authorisations the new vendor displaced. The tool surfaces the count. The history of the count is what tells you whether to flatten or to subtract.
The flattened record is not always the answer. Flattening replaces include: directives with the actual IP ranges they expand to, which fixes the lookup count but produces a static record that does not update when the upstream vendor changes their IP ranges. A flattened record needs to be re-flattened periodically — usually monthly — or it goes stale. For domains where the upstream vendors are stable, flattening is the right answer. For domains where the upstream vendors rotate IPs frequently (Mailchimp, Constant Contact, smaller marketing platforms), removing the legacy authorisations is often a better answer than flattening them.
Five findings, most of what we see.
Five findings account for roughly 80 percent of what the flattener surfaces across the 12,000 SPF records we have run since 2024. Each row maps a finding to a specific remediation. Most are accumulated configuration debt — the SPF record was correct three years ago and has been added-to without being audited.
Five findings across the 12,000 SPF records we have flattened since 2024. Each row maps a finding to a specific remediation, with realistic time estimates. Most are accumulated configuration debt rather than active mistakes — the SPF record was correct three years ago and has been added-to without being audited. The fix sequence is usually subtract first, then flatten only what cannot be subtracted, then schedule re-flattening if the flattened includes are not stable.
| # | Finding | What to do | Time to fix | Frequency |
|---|---|---|---|---|
| 01 | Inactive vendor still in record | Legacy include: for a vendor that is no longer used. Subtract — usually drops 1-3 lookups per inactive vendor. |
10 minutes | 42% |
| 02 | Cascading sub-includes > 10 | A single include: expands to 4-6 sub-lookups. Common with Salesforce Marketing Cloud and Microsoft 365. Flatten this specific include or split sending to a subdomain. |
30 min flatten + monthly re-check | 31% |
| 03 | Multiple SPF records published | RFC 7208 violation — domain has two TXT records starting with v=spf1. Receivers treat this as permerror. Merge into one record. |
15 minutes | 11% |
| 04 | Macro-heavy include resolves slowly | Some vendor includes use SPF macros that resolve dynamically. Counts toward 10-lookup ceiling and adds latency. Replace with static IP ranges if available. | 1 hour analysis + 15 min change | 9% |
| 05 | ~all instead of -all | Soft-fail policy where hard-fail is appropriate. Receivers will accept mail that fails SPF. Move to -all once you have confirmed no legitimate sender is unauthorised. |
5 minutes after audit | 7% |
Over 10 lookups?
The tool above tells you the count and shows the tree. The fix is sometimes simple (remove an unused include) and sometimes complex (your sending architecture genuinely needs more than 10 mechanisms and the flattening trade-off is the right answer). The €750 SPF/DMARC Audit handles the complex case end-to-end — including the ongoing maintenance of flattened records as upstream IP ranges change.