Check a domain's SPF record: the 10-DNS-lookup limit, include tree, errors with fixes, test an IP, and generate a record.
Built & maintained by Pappu Venkata Subbi Reddy, founder of Clacify · Updated October 2026
SPF Checker reads a domain's SPF record from live DNS and evaluates it exactly as a receiving mail server would. SPF (Sender Policy Framework, RFC 7208) is a TXT record that lists the servers allowed to send email for a domain; when a message arrives, the receiver checks the connecting server's IP against that list. The record looks simple, but it hides a trap: every include of another service's record can pull in more includes, and the whole chain may use no more than 10 DNS lookups. Go over, and every message fails SPF with a permanent error, often without anyone noticing until mail starts going to spam. The checker follows the full chain, shows it as a tree with the lookups each part costs, counts the total against the limit, and lists every problem with the exact fix. Two extra tools sit underneath: an IP test that tells you whether mail from a given server would pass, and a generator that builds a correct record from the services you use.
The checker queries the domain's TXT records through DNS-over-HTTPS (Google Public DNS, with Cloudflare as the fallback) and keeps those starting with "v=spf1". Exactly one is allowed; two or more is a permanent error under RFC 7208 section 4.5. The record is split into terms and each term is validated: a qualifier (+, -, ~, ?), a mechanism (all, include, a, mx, ptr, ip4, ip6, exists) or a modifier (redirect, exp). The lookup count follows section 4.6.4. The terms that cost a DNS query are include, a, mx, ptr, exists and the redirect modifier; ip4, ip6 and all are free. The checker resolves every include and redirect recursively and adds up the cost across the whole tree, because receivers stop at the 11th lookup with "permerror". It also counts void lookups, queries that return no records or a nonexistent domain, which the standard limits to two, and checks that no single mx mechanism points to more than 10 mail servers. A recursion guard catches loops where two records include each other. The IP test runs the check_host() algorithm from section 4: terms are evaluated left to right, the first matching mechanism decides the result through its qualifier, include matches only if the included record passes, and the result is "neutral" if nothing matches and there is no all. IPv6 addresses, including IPv4-mapped ones, are compared bit by bit against the network prefixes.
| Term | Example | DNS lookups | Notes |
|---|---|---|---|
| ip4 / ip6 | ip4:203.0.113.0/24 | 0 | The cheapest way to list your own servers |
| include | include:_spf.google.com | 1 + whatever the included record uses | How most email services are added |
| a | a | 1 | The domain's own A/AAAA records |
| mx | mx | 1 (max 10 MX hosts) | Your inbound mail servers; often unnecessary |
| exists | exists:%{i}.example.com | 1 | Used by advanced setups |
| ptr | ptr | 1 or more | Deprecated by RFC 7208: do not use |
| redirect | redirect=_spf.example.com | 1 | Use another domain's record instead of this one |
| all | ~all or -all | 0 | Must be last; decides everything not matched |
When building the checker we ran it against well-known domains in October 2026. GitHub's SPF record used exactly 10 of the 10 allowed lookups: compliant, but one added service away from failing. That is typical. Large organizations add a CRM, a marketing platform, a helpdesk and a billing system over the years, each with its own include, and nobody counts the total. Gmail's own IP 209.85.220.41 passed for gmail.com, which is how a healthy record should behave. If your count is at 8 or 9, treat it as an early warning and plan which include to remove before the next service is added.
First, remove services you no longer use: old newsletter tools and trial platforms are the usual culprits. Second, drop "mx" and "a" unless your web or inbound mail servers actually send email; most domains on Google Workspace or Microsoft 365 do not need them. Third, check whether a provider offers a narrower include, for example a per-account include instead of a global one. Last, for services whose servers rarely change, you can replace the include with the ip4/ip6 ranges it resolves to (called flattening), which costs zero lookups. The catch is that the provider can change those ranges without telling you, so flattened records need monitoring. Moving some senders to a subdomain (marketing.example.com with its own SPF record) is the cleanest long-term fix, and it also keeps a marketing platform's reputation separate from your staff mail.
SPF checks the envelope sender (the Return-Path, used for bounces), not the From address people see. A spoofer can use their own domain in the envelope, pass SPF for it and still show your domain in From. DMARC closes that gap by requiring the domain that passed SPF or DKIM to match the From domain. Gmail and Yahoo require SPF or DKIM from all senders, and Gmail requires both plus DMARC from anyone sending more than 5,000 messages a day to personal accounts; Microsoft has applied the same rule to Outlook.com since May 2025. So after fixing SPF, check DMARC with the DMARC Checker.
SPF allows at most 10 mechanisms that need a DNS lookup (include, a, mx, ptr, exists and redirect), counted across every nested include. Above 10, receivers stop and return a permanent error, which counts as an SPF failure. Every email service you add usually brings its own includes, so records quietly drift over the limit. Remove services you no longer use, or replace some includes with the ip4/ip6 ranges they resolve to.
Both are acceptable. ~all (softfail) tells receivers that unlisted servers are suspicious; -all (fail) says they are not allowed. With DMARC set to quarantine or reject, the practical difference is small because DMARC decides the outcome. Start with ~all while you confirm every sender is listed. Never use +all, which authorises every server on the internet.
No. A domain must publish exactly one TXT record starting with v=spf1. Two records make SPF return a permanent error for every message. If two services each tell you to add a record, merge their include terms into a single record.
No. It only reads public DNS records through DNS-over-HTTPS, the same information any mail server sees, and nothing is stored.