SPF Record Analyzer And Spoofability Check

Paste a domain's SPF TXT record. This tool parses every term the way an RFC 7208 evaluator does, counts the mechanisms that trigger DNS lookups against the hard limit of ten, and tells you whether the policy actually stops anyone from spoofing the domain. Everything runs locally, nothing is sent anywhere.

How the analysis works

SPF (Sender Policy Framework, standardised in RFC 7208) is a single DNS TXT record that lists which hosts are allowed to send mail using your domain in the SMTP MAIL FROM envelope. A receiving server fetches that record, walks the terms left to right, and returns the result of the first mechanism that matches the connecting IP. Everything this page reports is derived from four mechanical rules in that specification.

1. The record must be selected correctly

A valid record starts with the version token v=spf1 followed by a space or the end of the string. If a domain publishes more than one TXT record beginning with v=spf1, RFC 7208 section 4.5 requires the evaluator to return permerror — the policy is not "merged", it simply stops working. That is why the tool treats two pasted records as a hard failure rather than a warning. Separately, a single TXT record is transmitted as one or more character-strings of at most 255 bytes each (RFC 1035), which are concatenated with no separator on retrieval. Records longer than 255 characters are legal but must be published as a split string, and a badly split record silently loses or gains characters.

2. The ten DNS lookup limit

This is the single most common cause of a broken SPF policy. Section 4.6.4 puts a hard cap on how much work one evaluation may cost:

lookups = count(a) + count(mx) + count(include) + count(exists) + count(ptr) + count(redirect) must satisfy: lookups ≤ 10 otherwise the result is permerror

Only those six terms count. ip4, ip6 and all resolve nothing and are free, and the exp modifier is explicitly excluded from the limit. Crucially the count is recursive: every include spends one lookup for itself and then the entire nested record's own lookups are added to the same budget. This page can only count the terms you paste, so the number shown is the floor of the real cost — a record showing 6 direct lookups can still blow the limit once four large providers are expanded. Two related sub-limits also apply: an mx mechanism must not resolve more than 10 address records, and no more than 2 DNS queries in the whole evaluation may be "void" (returning NXDOMAIN or an empty answer).

3. Qualifiers decide what happens on a match

Each mechanism carries an optional qualifier, defaulting to +:

The final all mechanism matches every IP that got that far, so its qualifier is the whole point of the policy. -all is the only variant that actually asserts "nobody else may send as me". If a record ends without all and without a redirect, section 4.7 says the evaluation returns neutral — a fail-open default that gives an attacker exactly the same freedom as +all. Anything written after all is unreachable and silently ignored, and a redirect modifier is ignored entirely whenever an all mechanism is present (section 6.1).

4. Spoofability weighting

The resistance score starts at 100 and subtracts fixed penalties, so you can reproduce it by hand: +all or an ip4:0.0.0.0/0 style catch-all removes 100; a missing all removes 60; ?all removes 55; a syntax permerror or exceeding the lookup limit removes 50; ~all removes 25; a lookup count of 9 or 10 removes 10 as headroom warning; each broad IPv4 range shorter than /16 removes 10 up to a cap of 20; and a ptr mechanism removes 10. The result is clamped to the range 0 to 100. The verdict itself is not the score: it is fail if any finding is fail-level, warn if any is warn-level, otherwise pass.

One honesty note for bug bounty work. A weak SPF record on its own is very often not a payable finding — most programs consider it informational unless you can demonstrate deliverable spoofed mail. What makes it reportable is the combination: SPF that fails open and a missing or p=none DMARC policy, because DMARC is what receivers actually enforce on the visible From header. Check the _dmarc TXT record before you write anything up, and include a real delivered test message in the report.