SPF Over the 10-Lookup Limit: Find It and Fix It
Too many includes push SPF past 10 DNS lookups and the check returns permerror. Learn to count your lookups by hand, trim the record and publish it safely.
The short answer
RFC 7208 limits an SPF check to 10 terms that cause DNS lookups: include, a, mx, ptr, exists and redirect, counted across every nested include. If a record goes over 10, the check ends in permerror. Fix it by counting each lookup, removing stale includes, dropping a or mx entries that repeat a listed address, and using ip4 or ip6 ranges only where a provider publishes them. Keep exactly one v=spf1 record.
Reading options
On this page
- What the 10-lookup limit actually is
- Before you start
- Step 1: List every service that sends mail for your domain
- Step 2: Count the lookups
- Step 3: Trim the record
- Step 4: Publish the new record safely
- How to check it worked
- Troubleshooting
- Pro tips and when to ask for help
- The one message worth forwarding
- Reader questions
- Sources & further reading
The 10-lookup limit is a rule in RFC 7208, the SPF standard, that caps how many DNS lookups a receiving server may make while checking your SPF record. Go over 10 and the check stops with a permerror, which means the receiver cannot use your SPF record for that check, and genuine mail can be caught by it. You fix it by counting every lookup, nested ones too, and then trimming the record until it fits with a little room to spare.
Here is a made-up example I see versions of all the time. A small online shop adds a helpdesk tool on Monday and a review app on Wednesday, and by Friday order confirmations are failing SPF. Nothing in the record looks wrong. It quietly crossed the line at lookup eleven.
By the end of this guide you will be able to count the lookups in any SPF record by hand, trim it under the limit, and publish the fix without breaking mail on the way.
What the 10-lookup limit actually is
SPF (Sender Policy Framework) is a TXT record in your DNS that lists which servers may send email for your domain. When a message arrives, the receiving server reads that record and checks the sending server against it.
Some entries are self-contained, like ip4:192.0.2.10, an address written right there. Others are pointers: an include: entry says "go and read another domain's SPF record too", and that costs a fresh DNS query.
Think of a phone plan that allows 10 calls in total, where texts are free and only calls are counted. RFC 7208 Section 4.6.4 lists the calls: the include, a, mx, ptr and exists mechanisms, plus the redirect modifier. The ip4, ip6 and all mechanisms are the free texts, because they need no lookup at check time.
The section says SPF implementations MUST limit the total of those terms to 10, and if the limit is exceeded they MUST return permerror. There is no partial credit. Once the check needs an eleventh lookup, the result is permerror, not a pass with a warning.
Why this matters: the count is global. Section 4.1 of the RFC says the limit is tracked as a single total across the whole check, including every recursive evaluation. So if your record has five includes and each of those providers' records holds two more, you have used fifteen.
There is a second, smaller budget. Lookups that come back empty or with "no such domain" are called void lookups, and the RFC says implementations SHOULD limit those to two, with permerror beyond that. One dead include pointing at a provider you left years ago can eat into it.
Before you start
Gather these first. It turns a nervous hour into a calm fifteen minutes.
- Login access to wherever your DNS is hosted: your cPanel account, your registrar or a separate DNS provider.
- A list of every service that sends email using your domain. Step 1 helps you build it.
- A copy of your current SPF record in a text file, so you can roll back in seconds.
- A DNS lookup tool. This guide uses the
digcommand in a terminal. - A quiet hour or two outside your busiest sending time.
Quick tip: if you are not sure where your DNS lives, run dig example.com NS with your own domain. The nameservers it lists are the ones the rest of the internet actually reads from.
Step 1: List every service that sends mail for your domain
You cannot trim a list you have never written down. Most SPF records grow one include at a time over years, and nobody remembers why half of them are there.
Read your current record
Run this, replacing example.com with your domain:
dig example.com TXT +shortYou will get every TXT record on the domain. Find the one that starts with v=spf1, because that is your SPF record.
If you see two lines that start with v=spf1, stop here and read the troubleshooting section. Two SPF records break SPF all by themselves.
Write down every sender
Go through the entries and write next to each one which company or tool it belongs to. Then think about everything that actually sends mail as you today:
- Your mailbox host, the service your staff use for everyday email.
- Your website, if contact forms or order emails go out from the web server.
- Newsletter or marketing tools.
- Helpdesk, invoicing, booking or CRM apps that send notifications from your address.
Ask the people who own each tool. Whoever runs marketing knows which newsletter platform is live, and which one was cancelled last spring.
Mark each entry keep, remove or unsure
Keep what you can tie to a live service and mark cancelled services as remove. Anything nobody can explain goes in unsure, to check against the provider's own setup documentation before you delete it.
Why this matters: an include for a service you have left is pure cost, and Step 2 shows how it can break the record outright.
Step 2: Count the lookups
Now for the arithmetic. You need to count every term that triggers a DNS query, at every level of nesting.
The rules, from RFC 7208 Section 4.6.4:
- Each
include,a,mx,ptrandexistsmechanism counts as one. - A
redirect=modifier counts as one. ip4,ip6andallcount as zero.- Every lookup inside an included record counts too, because the limit is one total for the whole check.
- A total above 10 means
permerror.
Heads up on mx: the RFC also says the MX records queried while evaluating mx are included in the overall limit, and each MX host may not lead to more than 10 address lookups. If your domain has several MX hosts, treat your simple tally as the lowest possible figure.
A worked example (made up)
This record is invented for illustration. Every domain ending in .example is a placeholder, and so are the addresses.
example.com. TXT "v=spf1 a mx include:spf.newsletter-provider.example include:spf.helpdesk-provider.example include:spf.billing-app.example include:spf.crm-provider.example include:spf.office-suite.example include:spf.old-shop-platform.example ip4:192.0.2.10 ~all"Count the top level first:
ais lookup 1.mxis lookup 2.- The six includes are lookups 3 to 8.
ip4:192.0.2.10and~allcost nothing.
That is 8, which looks safe. Now follow each include by looking up that domain's TXT record the same way:
dig spf.newsletter-provider.example TXT +shortIn our made-up example, the six lookups come back like this:
spf.newsletter-provider.example "v=spf1 include:a.newsletter-provider.example include:b.newsletter-provider.example ~all"
spf.office-suite.example "v=spf1 include:mail1.office-suite.example include:mail2.office-suite.example -all"
spf.helpdesk-provider.example "v=spf1 ip4:192.0.2.10 -all"
spf.billing-app.example "v=spf1 ip6:2001:db8::10 -all"
spf.crm-provider.example "v=spf1 ip4:192.0.2.10 -all"
spf.old-shop-platform.example (no SPF record found)The newsletter record adds 2 lookups and the office suite record adds 2 more. Keep going down each branch until it ends in ip4, ip6 or all. In this example, say all four nested includes end there.
Running total: 8 at the top plus 4 nested makes 12. That is over the limit, so a receiver following the RFC returns permerror once the check needs the eleventh lookup.
There is a second problem hiding in there. The old shop platform include points at a domain with no SPF record. Section 5.2 says an include whose target returns none produces permerror, so whenever the check reaches that line it would produce permerror, even with a safe count.
Quick tip: write the tally as a tree in a text file, one indent per level, and reuse it next time someone adds a tool.
Step 3: Trim the record
Aim to get under 10 with some headroom, so the next tool somebody adds does not tip you straight back over. Work through these options cheapest first.
Remove stale includes
Delete every entry you marked remove in Step 1. In the example, include:spf.old-shop-platform.example goes, which saves one lookup and removes the broken include in one move. Running total: 11.
Drop a and mx when they repeat an address you already list
The a mechanism checks the address your domain name points to. The mx mechanism checks the addresses of your incoming mail servers. Both are handy shortcuts, and each one costs a lookup.
In the example, say example.com and its MX host both resolve to 192.0.2.10, the same server already listed as ip4:192.0.2.10. Then a and mx are paying twice for one address, so remove both. Running total: 9.
Heads up: confirm the addresses first with dig example.com A and dig example.com MX. If your website later moves server, an ip4 entry will not follow it.
Replace an include with ip4 or ip6 only when the provider publishes the ranges
Some providers document the exact IP ranges they send from. If yours does, you can list those ranges with ip4: or ip6: entries and remove the include. That saves the include's own lookup plus any nested ones behind it.
Only do this when the provider's own documentation publishes the ranges for this purpose. If they change servers while you list the old addresses, your mail fails with no warning. If their documentation says to use the include, keep it.
Consolidate where you can
Look for two tools doing one job, such as two newsletter platforms left over from a migration nobody finished. Retiring a tool is the cleanest lookup saving you will find.
Another route is sending one tool's mail from a subdomain such as news.example.com. A subdomain is checked against its own SPF record, so that check starts its own count of 10.
After trimming, the made-up record looks like this:
example.com. TXT "v=spf1 include:spf.newsletter-provider.example include:spf.helpdesk-provider.example include:spf.billing-app.example include:spf.crm-provider.example include:spf.office-suite.example ip4:192.0.2.10 ~all"Count it again: 5 includes at the top and 4 nested lookups make 9. One to spare.
If your host uses cPanel
cPanel has a dedicated interface for this. Its Zone Editor documentation says you can use the Email Deliverability interface to manage your server's SPF and DKIM records. At the time of writing (10 November 2026), the cPanel documentation describes these steps:
- Log in to cPanel and open Email Deliverability. The Zone Editor documentation gives the path as cPanel » Home » Email » Email Deliverability, though it calls it WHM's interface in the same sentence, so if you do not see it, your host may not have enabled the feature.
- Find your domain and click Manage.
- In the SPF section, click Customize. This opens the Customize an SPF Record interface.
- Review Additional Hosts and Additional MX Servers. Entries here are added as
aandmxitems, so each one costs a lookup. - In the IP address settings, add any address blocks you want listed directly. CIDR notation, such as
192.0.2.10/32, is accepted. - In Include List, remove includes you no longer need and keep the rest.
- Read the preview, count the lookups using Step 2, then click Install a Customized SPF Record.
Heads up: cPanel automatically includes your primary mail exchanger, any other servers you created MX records for, and your server's main IP addresses. That saves typing, but read the preview so you know which of those auto-added entries cost lookups.
By default the interface recommends ~all, which asks receivers to accept mail from unlisted servers but flag it as possibly unauthorized. The Exclude All Other Hosts setting adds -all instead, which makes unlisted servers fail.
Only turn that on when you are certain your sender list is complete, or the tool you forgot about is the first thing you block. Neither ending suits every domain.
If your DNS is hosted elsewhere, cPanel's documentation says your server must be the authoritative nameserver to install an SPF record correctly. If it is not, the record can be installed locally, but you must also contact your nameserver provider to update the authoritative nameserver. Build the record here, then add it at your real DNS provider.
Step 4: Publish the new record safely
The edit itself takes a minute. The care goes into the order you do things.
Lower the TTL first
TTL (time to live) is how long other servers may cache a DNS record before asking for it again. If your SPF record has a TTL of a day and you make a typo, the broken version can stick around for a day.
A few hours before the change, lower the TTL on the SPF record to something short, such as 300 seconds. Wait until the old TTL has run out. Then make the real edit, and any correction after that spreads quickly.
Edit the one existing record
RFC 7208 is strict about this. A domain must not publish records that would make a check select more than one SPF record, and if a receiver does find more than one, the result is permerror.
So edit your existing v=spf1 record in place. Do not add a fresh TXT record beside it, even for a moment.
In cPanel's Zone Editor, click Manage next to your domain, click Edit beside the TXT record, update the text, then click Save Record. The documentation warns that the record text box accepts invalid data, so paste carefully and read it back before saving.
Long records and the 255 limit
A single string inside a TXT record can hold at most 255 octets (bytes). The limit applies to each string, and a whole record can be longer. Longer SPF records are split into several quoted strings, and Section 3.3 says receivers join them together with no spaces added.
example.com. TXT "v=spf1 include:spf.newsletter-provider.example include:spf.helpdesk-provider.example " "include:spf.billing-app.example ip4:192.0.2.10 ~all"Notice the space before the closing quote of the first string. Without it, the receiver would join the two parts into one broken word, something like .exampleinclude: at the join.
Once saved, wait at least as long as the TTL you set, then run the checks below. Keep the copy of your old record until every check passes.
How to check it worked
These run from quickest to most convincing.
Read the published record
dig example.com TXT +shortExpected: exactly one line starting with "v=spf1, showing your new content. If you still see the old version, your resolver is serving a cached copy.
Wait out the TTL, or ask one of your nameservers directly. Replace ns1.example.com with a nameserver from your NS lookup:
dig @ns1.example.com example.com TXT +shortCount the lookups on the live record
Repeat the tree from Step 2 against what DNS is actually serving, using dig on each include, because the live record is what receivers read.
Expected: 10 or fewer lookups in total, and no include that comes back with an empty answer.
Send a test message and read the headers
Send an email from each service you kept to a mailbox you control at a different provider, then open its full headers.
Look for the Authentication-Results header. RFC 8601 defines it as the place where the receiving server records the checks it ran. A passing SPF check looks like this example from that RFC:
Authentication-Results: example.com;
spf=pass smtp.mailfrom=example.netExpected: spf=pass. The smtp.mailfrom part shows which domain was checked.
If you see spf=permerror, the record still cannot be evaluated. If you see spf=softfail or spf=fail, the record is readable, and that particular sender is missing from it.
Quick tip: test every sending tool you kept, since the forgotten invoicing app is usually the one that fails. For an ongoing view across all your mail, your DMARC reports show SPF results by source, and our guide to reading DMARC aggregate reports walks through them.
Troubleshooting
Mail shows permerror after a new tool was added
Symptom: spf=permerror in the Authentication-Results header for your mail, often including your everyday mailbox.
Cause: the new include pushed the total past 10, often through nested includes you never saw. Fix: redo the count from Step 2 and trim using Step 3.
permerror even though your count is under 10
Cause one: two SPF records. Run dig example.com TXT +short and look for two lines that start with v=spf1. Fix: merge their entries into a single record, then delete the other one.
Cause two: an include points at a domain with no SPF record, which Section 5.2 turns into permerror, or you have more than two void lookups. Fix: look up each include in turn and remove any that return nothing.
One real sender gets softfail or fail
Symptom: spf=softfail or spf=fail for mail from one tool, while everything else passes. With ~all at the end you see softfail, and with -all you see fail.
Cause: that tool's servers are not covered, usually because its include was removed during trimming or replaced with IP ranges that went out of date. Fix: check the tool's current setup documentation and add back exactly what it asks for.
Your redirect seems to be ignored
Symptom: you added redirect= to point at another domain's policy, and nothing changed.
Cause: RFC 7208 Section 6.1 says a redirect modifier MUST be ignored if the record contains an all mechanism anywhere. Fix: end the record with either redirect= or an all mechanism, and remove the other.
cPanel's Repair option is missing for your domain
Symptom: Email Deliverability flags a problem with SPF, but you cannot repair it from there.
Cause: cPanel says Repair is unavailable when the server does not control the domain's DNS records. Fix: make the change at the DNS provider that actually hosts your zone.
Pro tips and when to ask for help
- Leave one or two lookups spare. Providers can add nested includes to their own records, which raises your total without you touching anything.
- Sort out SPF before you tighten DMARC. If you are setting up all of your email records together, our SPF, DKIM and DMARC setup guide shows how they fit.
- If you run your own mail server, reverse DNS is a separate check worth getting right. See our guide to reverse DNS and PTR records.
Ask your host or a developer when:
- You still need more than 10 lookups after removing everything stale, and moving tools to a subdomain means changing each tool's settings.
- You cannot find where your DNS is hosted, or you do not have the login.
- A provider's documentation is unclear about whether to use its include or its IP ranges.
- You are moving from
~allto-alland want a second pair of eyes on the sender list.
The one message worth forwarding
Copy this, fill in the gaps, and send it to whoever manages your DNS.
Hi,
Our SPF record for example.com looks like it exceeds the RFC 7208 limit of 10 DNS lookups. Test messages show spf=permerror in the Authentication-Results header.
Could you please:
1. Count the lookups in the current record, including nested includes.
2. Remove includes for any service not on the list below.
3. Lower the TTL before the change and keep a single v=spf1 record.
4. Send me the final record and its lookup count, then confirm a test message shows spf=pass.
Current record (saved copy):
(paste here)
Services that send mail for us today:
(paste list here)
Thanks,
(your name)Count every lookup down to the last nested include, and keep a single record with room to spare.
Reader questions
Should I use the ptr mechanism in my SPF record?
No. RFC 7208 says ptr SHOULD NOT be published, and its note calls the mechanism slow and, in cases of DNS errors, not as reliable as other mechanisms. It also counts toward the 10-lookup limit.
Does the order of entries in an SPF record matter?
Yes. Receivers evaluate mechanisms left to right and stop at the first match, so the all mechanism belongs at the end of the record.
What happens if nothing in my SPF record matches and there is no all at the end?
RFC 7208 says the result is neutral, as if ?all were the last entry. Neutral is treated the same as having no SPF policy for that message.
Will going over the limit stop my email being delivered?
The standard says the check returns permerror. What each receiving server then does with that result depends on its own policy and on your DMARC setup, so the effect varies.
Can my lookup count change even if I never edit my record?
Yes. The records behind your includes belong to the providers, and if a provider adds nested includes to its record, your total rises with it.
Is RFC 4408 still the SPF standard?
No. RFC 7208, published in April 2014, obsoletes RFC 4408 and is the document that sets the 10-lookup limit.
Does v=spf1 have to be at the very start of the record?
Yes. When selecting records, receivers keep only TXT records that begin with v=spf1 and ignore the rest, so a record with text before it will not be read as SPF.
Was this guide helpful?
Help us make the next update better.
Sources & further reading
Originally published . About our editorial updates.



