Why does my Spamhaus check say “not listed” for every IP?

Because the check probably never reached Spamhaus. Spamhaus’s free blocklists refuse lookups that come through big public DNS services such as Google’s 8.8.8.8 and Cloudflare’s 1.1.1.1, and through many hosting companies’ own DNS. Through Google, the refusal looks exactly like a clean result, so a script, a security plugin or a mail server reads it as “not listed” for every address you give it. Through Cloudflare and many hosts, it comes back as an error code, which software either skips or misreads as a listing. Meanwhile the mail servers that receive your mail and use Spamhaus query it properly. That is how a server can be “clean” by your check and still have its mail bounced with Spamhaus named in the error.

The 10-second test

Spamhaus keeps one address listed on purpose so you can test the path: 127.0.0.2. Blocklist lookups write the IP address backwards and add the list’s name, here zen, Spamhaus’s combined list. So the query is 2.0.0.127.zen.spamhaus.org. Run it from the machine that does the checking, through the DNS it normally uses:

dig +short 2.0.0.127.zen.spamhaus.org

A working path returns 127.0.0.2, 127.0.0.4 and 127.0.0.10, the codes for the three Spamhaus lists the test address sits on. An empty answer, or an address starting 127.255.255., means every result from that machine is meaningless.

Without SSH, run the lookup through PHP, which uses the same host DNS a WordPress plugin does. With WP-CLI:

wp eval 'var_dump(gethostbynamel("2.0.0.127.zen.spamhaus.org"));'

Without WP-CLI, put the var_dump() line in a code-snippets plugin and remove it afterwards. A working path prints the three 127.0.0.x codes; false or a 127.255.255.x code means the same failure as above.

We ran the dig test on 27 October 2026 from a Hetzner Cloud VPS, with dig 9.18, through five resolvers:

Resolver Answer for the test address
Google, 8.8.8.8 NXDOMAIN (no such name), the same answer a clean IP gets
Cloudflare, 1.1.1.1 127.255.255.254, with the text record Error: open resolver
Hetzner’s own resolver 127.255.255.254
Quad9, 9.9.9.9 127.0.0.2, 127.0.0.4, 127.0.0.10
Spamhaus’s nameserver a.gns.spamhaus.org, asked directly 127.0.0.2, 127.0.0.4, 127.0.0.10

PHP’s gethostbynamel() on the same server, through Hetzner’s resolver, got 127.255.255.254 both for the test address and for 127.0.0.1, which Spamhaus does not list. The refusal applies to the resolver, whatever address it asks about.

Google’s answer is the dangerous one. NXDOMAIN is what Spamhaus says about an address it does not list, so software has no way to tell a refusal from a clean bill of health. Every lookup passes, and nothing logs an error.

Quad9 returned the real codes in our test, but Spamhaus’s own service page names Quad9, alongside Google and Cloudflare, as a resolver outside its fair-use policy. Don’t build on it.

When a refusal reads as a listing (127.255.255.x)

Since March 2021, Spamhaus has answered with three refusal codes, all in the 127.255.255.x range: .252 for a typo in the list name, .254 for a query through a public or open resolver, and .255 for too many queries. None of them is reputation data. Spamhaus’s notice about the codes warns that software that doesn’t parse them may treat every answer as listed, or every answer as not listed.

Software that counts any answer starting 127. as a hit gets the first outcome: through Cloudflare, it calls every address on the internet listed. A mail server configured that way rejects all its incoming mail.

Where this shows up on a WordPress site

Checking your own server’s IP. A dig or a script on a VPS uses whatever DNS the server is set to use, often 8.8.8.8, 1.1.1.1 or the provider’s resolver. All three failed the test above.

Security and anti-spam plugins. A plugin that looks up an IP on Spamhaus from PHP goes through the server’s resolver like everything else. Vigilant, a security plugin with 3,000+ active installs that checks the site’s own IP with PHP’s gethostbynamel(), has had both failure directions. Until version 3.0.8, it read an empty answer as clean; a comment in its source says the bug was measured on a SiteGround server, where Spamhaus answers nothing at all. Another comment in the same file says reading 127.255.255.x codes as a listing “told sites they were on Spamhaus when they were not”, a bug fixed in 2.9.8. Since 3.0.8, an empty answer makes it ask for the test address too, and it reports “not answering” instead of “clean” when that fails. Any other plugin that queries a blocklist can be checked the same way: look in its source for the list name, and for what it does with an empty answer.

Shared and managed hosting. The host runs the resolver your plugins use, and the mail server. Neither is yours to change, so the resolver fix below is for VPS owners; on shared hosting, the free-account route works only if the plugin lets you enter a Spamhaus key or change the list’s hostname.

Check which IP, and which list, the bounce names

Sometimes “not listed” is the right answer for the address you checked. A WordPress site that sends through an SMTP service sends from that service’s IP, not the web server’s, and a bounce names the IP that actually connected. And a rejection that names the Spamhaus DBL is about a domain, not an IP: the sender’s domain, a domain linked in the message, or the sending server’s hostname. No IP lookup will show it. Look the domain up in the checker below.

How to get a real answer

For your own sending IP or domain, use Spamhaus’s IP and Domain Reputation Checker. It is the authoritative one, and the place to start a removal request.

For software that does lookups on every request or every message, there are two options:

  • A free Spamhaus account. Spamhaus gives a free Blocklists via DNS Query account (formerly the Data Query Service, DQS) to non-commercial small organisations and individuals; its terms cap use at 100,000 queries a day. A shop or an agency is likely to fall outside that, and commercial use needs the paid subscription. The account’s key goes into the hostname (2.0.0.127.<key>.zen.dq.spamhaus.net), so Spamhaus knows who is asking, and the lookup keeps working whichever resolver the query passes through.
  • A resolver of your own. A recursive resolver on the server, such as Unbound, asks Spamhaus’s nameservers directly, as the last row of the table did. Spamhaus’s fair-use terms still exclude queries from large shared hosting environments, so on some networks this returns .254 too; run the test once it is set up.

On a Postfix mail server you run, accept only real listing codes:

reject_rbl_client zen.spamhaus.org=127.0.0.[2..11]

That stops refusal codes being read as listings. It does nothing about Google’s NXDOMAIN, which still passes everything: only a resolver change or the Spamhaus key fixes that.

If the real answer is “listed”

For a server’s own IP, the usual cause on a WordPress site is malware sending through it, and a removal holds only once that has stopped: how to tell whether a hacked site is sending spam. Once the IP is clean, an inbox placement test shows where your mail lands.