SPF record syntax: structure, rules, and examples
An SPF record is one TXT record with a strict grammar: version tag, qualified mechanisms, optional modifiers. The rules, the common shapes, and worked examples.
An SPF record is a single DNS TXT record published at the domain name it protects, beginning with the version tag v=spf1 and followed by a space-separated sequence of mechanisms and modifiers. The grammar is small and strict: receivers evaluate the terms left to right, stop at the first match, and treat malformed records as permanent errors. This entry covers the structural rules; the individual matching directives have their own entries.
The anatomy of a record
Each term is a mechanism (a test against the connecting IP), optionally prefixed by a qualifier that sets the result if that mechanism matches. Omitting the qualifier means +, a pass. Evaluation is strictly first-match-wins: once a mechanism matches, its qualifier decides the outcome and nothing further is evaluated, which makes ordering meaningful.
The rules that break records when ignored
One record per domain
A domain must publish exactly one TXT record starting with v=spf1. Two SPF records is not a merged policy; it is a permerror, and receivers treat the domain as having no valid SPF at all. This happens constantly in practice when a second team or vendor adds their record instead of editing the existing one. Multiple sending services belong inside one record as multiple mechanisms.
Length and string splitting
A single TXT string is limited to 255 characters. Longer records are legal but must be split into multiple quoted strings inside the same record, which resolvers concatenate. Records long enough to need splitting are usually records with too many mechanisms, which points at a deeper problem: the 10 DNS lookup budget, covered in its own entry, is typically exhausted before the length limit becomes relevant.
Placement and scope
The record lives at the exact name being evaluated: SPF for mail.example.com lives at mail.example.com, and the record at example.com does not cover its subdomains. Every subdomain used in an envelope sender needs its own record, and every HELO hostname benefits from one too, since receivers may evaluate SPF against the HELO identity when the envelope sender is empty (bounces). The record type is TXT; the dedicated SPF record type (type 99) was deprecated years ago and should not be used.
Modifiers: redirect and exp
Besides mechanisms, the grammar allows modifiers, name=value pairs that may appear once each. redirect=domain.com replaces the entire evaluation with another domain's record and only takes effect if nothing else matched; it is occasionally useful for centralizing policy across many domains. exp=domain returns a custom explanation string on failure and is rarely worth its complexity. In practice, most records need neither, and a redirect combined with an all mechanism is a common contradiction: the all always matches first, so the redirect is dead code.
Worked examples
After any edit, validate before and after publication: syntax checkers catch malformed grammar, and the testing and troubleshooting entry covers the tools and the failure vocabulary. DNS consoles that silently mangle quotes or split strings are a recurring source of records that look right in the editor and fail in resolution.
Frequently asked questions
Does the order of mechanisms matter?
Can I put comments in an SPF record?
Is v=spf1 case sensitive?
What happens if my record has a typo?
Key takeaways
- One TXT record per domain, starting with v=spf1; a second SPF record produces permerror, not a merged policy
- Terms evaluate left to right, first match wins, so all belongs at the end and ordering is meaningful
- Records cover only the exact DNS name; every sending subdomain needs its own record
- Strings over 255 characters must be split into quoted segments, but oversized records usually signal a lookup-budget problem
- Modifiers redirect and exp exist and are rarely needed; a redirect after all is dead code