Siftsmith Run on Apify
← Email Security Signals

SPF too many DNS lookups: count yours against the 10-lookup limit

An SPF record may trigger at most 10 DNS-querying terms, counted across every record it includes. Go over and receivers return permerror, so SPF can fail even for mail from servers you authorised. Count your domain’s lookups free below, see which include costs the most, then read what counts, how to get back under the limit, and how to check a whole list of domains in one run.

Free SPF lookup counter

Enter a domain. The counter runs in your browser against public DNS: it reads the SPF record, follows every include and redirect as a receiver would, and counts each DNS-querying term, including any past the limit. You get the total against the limit of 10, the void lookups against the limit of 2, and what each term in your own record costs with everything nested under it.

This reads what your DNS publishes right now through Cloudflare’s public resolver, or Google’s when Cloudflare’s fails. A receiver whose DNS cache still holds older records can count differently until those expire. A lookup that fails (server error or timeout) is never treated as fine: the count becomes a minimum and the result reads unknown. The lookup of your own SPF record isn’t one of the counted terms. Include or redirect targets built from macros (%{i} and the like) depend on the sending server, so their own lookup is counted but what’s behind them isn’t. To find every other kind of SPF PermError, use the SPF PermError checker.

What the 10-lookup limit is

RFC 7208, the SPF standard, says in section 4.6.4: “SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation” and “If this limit is exceeded, the implementation MUST return ‘permerror’.”

Counts toward the 10include, a, mx, ptr, exists (mechanisms) and redirect (modifier)
Doesn’t countip4, ip6, all, and the exp modifier
Void lookupsImplementations SHOULD limit “void lookups” (terms whose lookup returns no records or a non-existent domain) to two; exceeding that limit is also a permerror. Find and fix void lookups
Per mx / ptrEach MX or PTR record may lead to at most 10 A/AAAA lookups, on top of the overall limit (over that, mx is a permerror; for ptr the extra records are ignored)

Other SPF PermError causes: more than one SPF record, a syntax error, or an include whose target has no SPF record. Check which one applies to your domain.

Two more rules matter when counting. An include runs a full SPF check against the included domain (section 5.2), so every term in the included record counts too, and so on down the tree. And a redirect= is ignored when the record also has an all mechanism (section 6.1), so it doesn’t count in that case.

What happens when you go over

Microsoft’s SPF documentation says that if the lookup count “is greater than 10, the message fails SPF with a permanent error (also known as a permerror)”, and that the receiving system may bounce it with an NDR such as “The message required too many lookups.” Google’s troubleshooting page says exceeding the limit causes “your SPF record validation to fail”, and warns that error messages “might include warnings that you don’t have an SPF record (even if you do have one).”

The failure can be intermittent. Receivers evaluate the record left to right and stop at the first match, so, as Microsoft notes, mail from a sender listed early may pass while mail from a sender further along fails. A record that “mostly works” can still be over the limit.

For bulk senders this is more than a warning: Gmail, Yahoo and Outlook.com all require SPF, and Microsoft says it must pass. See what the bulk sender rules require.

Sources: RFC 7208 sections 4.6.4, 5.2 and 6.1; Microsoft Learn, Set up SPF to identify valid email sources for your Microsoft 365 domain; Google Workspace Help, Troubleshoot SPF issues (all checked September 2026).

How to count lookups

  1. Start at the domain’s own SPF record. Count one for each include, a, mx, ptr, exists and redirect. Skip ip4, ip6 and all.
  2. For each include: and redirect= target, fetch that domain’s SPF record and count its terms the same way.
  3. Keep going until no includes are left. The total across the whole tree is the number that must stay at 10 or below.

The number of include: terms you can see is not the lookup count. Microsoft’s example: an include that points to a record with three more includes costs four lookups. Real records from our run on 27 September 2026:

DomainIncludes in its own recordTotal lookups
posthog.com610
github.com810
atlassian.com66
hubspot.com0 (one redirect=)4

posthog.com and github.com both sit exactly at the limit, so adding one more sending service would push either over.

How to fix it

A caution on SPF flattening

Flattening replaces includes with the IP addresses they currently resolve to. It fixes the count today, but the IPs are a snapshot: when a provider adds a range, your flattened record doesn’t follow and mail from the new range fails SPF. Microsoft says not to flatten its own include (spf.protection.outlook.com) or any service with changing IPs, and if you do flatten, to document what you replaced and review it at least quarterly. Try the options above first.

After any change, allow time for it to spread: Google says 24–48 hours.

Check the SPF lookup count for a list of domains

Email Security Signals reads each domain’s SPF record from public DNS, follows its includes and redirects, and returns the total lookup count with the rest of its email-authentication checks. It suits auditing client domains, a prospect list or a vendor list, where checking one domain at a time in a web tool doesn’t scale.

Input: paste domains, URLs or email addresses into Domains on the Apify Store page, or send JSON through the API:

{
  "domains": ["posthog.com", "https://www.github.com", "jane@atlassian.com"],
  "maxConcurrency": 5
}

SPF fields in each result row:

spf.lookupCountTotal DNS-querying terms across the whole include/redirect tree
spf.lookupCountIsMinimumtrue when the tree couldn’t be walked fully (an include or redirect lookup failed, or the tree was more than 10 levels deep or needed more than 40 record fetches), so the count is a lower bound
spf.validtrue when there is exactly one SPF record, it needs 10 or fewer lookups, and nothing else in it is a permerror (more than 2 void lookups, an mx name with more than 10 MX hosts, an unknown or misspelled mechanism, or an include or redirect target with no SPF record)
spf.voidLookupsa, mx and exists names in the include/redirect tree that return no records (RFC 7208 allows 2); spf.voidLookupsIsMinimum is true when one of those lookups failed or the 30-name cap was reached, so the count is a lower bound
spf.record, spf.recordCountThe record itself, and how many SPF records the domain publishes (more than one is also a permerror)
spf.allQualifierThe effective all: -all, ~all, ?all or +all, following redirect=; null when there is none or it can’t be determined
sendingVendors, spfIncludesServices named in the domain’s own includes (SendGrid, Mailchimp, Amazon SES, …), and any includes not in the vendor table, listed raw: a starting point for deciding what to remove
issuesspf_too_many_lookups (over 10, high severity), spf_near_lookup_limit (9 or 10, low), spf_multiple_records, spf_permerror (high: more than 2 void lookups, an mx name with more than 10 MX hosts, an unknown mechanism, or an include or redirect target with no SPF record or more than one), spf_void_lookups (1 or 2 on an otherwise valid record, low), spf_lookup_count_truncated
bulkSenderCompliantfalse whenever SPF is over 10 lookups or otherwise a permerror

For a domain over the limit, the issue reads, for example, “SPF needs 14 DNS lookups (limit is 10); receivers return permerror.” Export to CSV and sort by the spf/lookupCount column, or filter issues for spf_too_many_lookups.

Void lookups are checked for a, mx and exists names (up to 30 per domain), and an mx name with more than 10 MX hosts is a permerror. What the check doesn’t cover: ptr is counted but can’t be resolved without a sending IP, the address lookups of each MX host aren’t made, and %{…} macros are counted but not expanded. DNS is read through Cloudflare’s public resolver at run time.

FAQ

How much does it cost to check SPF lookups for a list of domains?

$0.02 per graded domain ($20 per 1,000), with no subscription. Domains that don’t exist, IP addresses, unparseable inputs, DNS lookup failures and duplicates come back as free rows. Set a max charge per run and the run never costs more than that.

Does ~all versus -all change the lookup count?

No. all never causes a DNS query. The qualifier only decides what happens to mail from servers the record doesn’t list.

My record has only five includes. How can it be over 10?

Nested includes. A provider’s include often includes further records of its own, and every one of those terms counts. posthog.com’s six includes add up to ten lookups.

Can I check domains I don’t own?

Yes. SPF records are public DNS records that every receiving mail server reads. No email is sent and no login is used.

Check your list on the Apify Store →

Or have us grade your list free: send up to 100 domains to hello@siftsmith.com, and we’ll run them through Email Security Signals and email you a CSV file with each domain’s grade, the issues found and whether it meets the bulk-sender rules, or the reason a domain couldn’t be graded.

Related: every SPF PermError cause (find which one applies, with a checker), fixing SPF “too many void lookups” (find every term that returns nothing, with a checker), fixing an SPF record over 255 characters (check how a long record is split into strings), fixing “multiple SPF records” (merge two SPF records into one and see the merged lookup count) and fixing “multiple DMARC records found”.