Writing

SPF record syntax

Published 17 September 2026

Every mechanism and modifier, with the column other guides leave out: what each one costs. An SPF record is allowed ten DNS lookups to evaluate, and going over does not produce an error you will see: it makes the record invalid and your mail starts failing while it still reads perfectly.

The shape of a record

v=spf1 ip4:192.0.2.0/24 include:_spf.google.com ~all

A single DNS TXT record at the domain root. It starts with v=spf1, then a list of mechanisms describing who may send, evaluated left to right, and ends with a catch-all saying what to do with everyone else. The first mechanism that matches decides the result; nothing after it is read.

One record per domain. Publishing two is a permanent error: receivers do not merge them, they give up.

Mechanisms, and what they cost

MechanismMatchesDNS lookups
ip4:192.0.2.0/24An IPv4 address or range0
ip6:2001:db8::/32An IPv6 address or range0
include:example.comWhatever that domain's SPF allows1 + its chain
a / a:example.comThe domain's own A/AAAA records1
mx / mx:example.comThe domain's mail servers1
exists:%{i}.example.comWhether a constructed name resolves1
ptrReverse DNS of the sender. Deprecated.1
allEverything. Always last.0

ip4 and ip6 are free. Everything else costs, and include costs whatever the included record costs as well, which is where budgets disappear without anyone editing anything.

Qualifiers

Any mechanism can be prefixed. Omit it and you get +.

In practice qualifiers matter on all and almost nowhere else.

Ending the record: ~all or -all

~all asks receivers to accept unlisted senders and mark them. -all asks them to reject. Start with ~all while you are still discovering which services send on your behalf, including invoicing, ticketing and the marketing platform somebody signed up for. Tighten to -all once a few weeks of DMARC reports show nothing legitimate failing.

+all authorises the entire internet. It appears in the wild surprisingly often, usually from someone debugging a delivery problem who never took it out. It is worse than publishing no SPF at all, because it looks deliberate.

Modifiers

The ten-lookup limit

This is the part worth reading twice, because it is how working SPF setups break without being touched.

Evaluating a record may cost at most ten DNS lookups, and that budget spans the whole chain: your includes, their includes, and so on. Add one provider to a record already at nine and you cross the line.

Past ten, the result is PermError. Receivers treat a PermError as though the domain published no SPF at all. Your record is still there, still reads correctly, still shows as "found" by most checkers, and is doing nothing. Mail that passed last week now fails, and nothing in the record changed. Somebody else's include grew.

Common culprits, with typical costs:

IncludeRoughly costs
include:_spf.google.com3–4
include:spf.protection.outlook.com1–2
include:sendgrid.net2
include:_spf.salesforce.com2
include:servers.mcsv.net1

Four providers and you are over half the budget. These numbers change without notice, which is the point: the cost is not yours to control.

Count yours. The SPF, DKIM and DMARC checker walks the full include chain and shows what each step costs, so you can see which include spent the budget rather than only that it was spent. It runs in your browser and sends nothing anywhere.

Check a domain

Getting back under the limit

Mistakes worth knowing