Verification Methods
Four checks carry most of the weight in the free tools: forward-confirmed reverse DNS, crawler verification, RDAP prefix matching and blacklist queries. Each of them has a shortcut that looks correct in testing and produces wrong answers in production. This page states what the tools do instead, in enough detail to reproduce it.
Forward-confirmed reverse DNS
A PTR record proves nothing on its own. Whoever controls an address block decides what name it
carries, and nothing stops that name being mail.yourbank.com. The check that carries
weight is forward confirmation: resolve the PTR name back and see whether the original address is
among the results.
Compare the whole address set, not the first record
The common error is to compare against the first A record returned. Addresses behind a round-robin name break that immediately:
8.8.8.8 -> PTR dns.google
-> A 8.8.8.8, 8.8.4.4
-> AAAA 2001:4860:4860::8888, 2001:4860:4860::8844
8.8.4.4 -> PTR dns.google
-> same four addresses
A tool that stops at the first answer reports 8.8.4.4 as unconfirmed, because DNS
returned 8.8.8.8 first. Roughly every second query against a round-robin name comes
out wrong that way. Both the A and the AAAA set have to be resolved and searched.
Compare addresses in binary form
The second error is comparing addresses as strings. 2001:db8::1 and
2001:0db8:0000:0000:0000:0000:0000:0001 are the same address and share no
characters; ::ffff:192.0.2.1 and 192.0.2.1 are the same address in two
families. Both comparisons belong on the packed form that inet_pton() returns, never
on the text.
What a failure means
| Result | What it says |
|---|---|
| Confirmed | The PTR name resolves back to this address. The operator of the name and the operator of the address agree. |
| No PTR record | Nothing to check. Common on cloud instances, and the usual reason a mail server is refused before the message body is sent. |
| Not confirmed | A PTR name exists but does not resolve back. Either a stale record or a name someone set without controlling the forward zone. |
Try it on Reverse DNS.
Verifying a crawler
A User-Agent header is free text that any client can send, which is why every large operator publishes a verification method. For two decades that method was forward-confirmed reverse DNS. That is no longer true for half of the crawlers worth checking.
| Crawler | Operator | Method |
|---|---|---|
| Googlebot | Forward-confirmed reverse DNS | |
| Bingbot | Microsoft | Forward-confirmed reverse DNS |
| Applebot | Apple | Forward-confirmed reverse DNS |
| YandexBot | Yandex | Forward-confirmed reverse DNS |
| Baiduspider | Baidu | Forward-confirmed reverse DNS |
| DuckDuckBot | DuckDuckGo | Published address ranges |
| GPTBot | OpenAI | Published address ranges |
| OAI-SearchBot | OpenAI | Published address ranges |
| PerplexityBot | Perplexity | Published address ranges |
| ClaudeBot | Anthropic | Published address ranges |
The split runs along the line between classic search engines and the generation of AI crawlers. The newer operators document JSON files of address ranges and do not make PTR names part of their method, so an address inside the range OpenAI publishes for GPTBot carries no reverse record at all. A verifier that only knows the DNS method marks every one of them as unconfirmed, which is the same verdict it gives a forgery.
Three verdicts are therefore kept apart:
- Confirmed. The name belongs to a known crawler and the method that applies to that operator agrees.
- Not confirmed. There is no PTR record, the forward check failed, or the User-Agent claims a crawler that the evidence does not support. This is the case to act on.
- Not attributable. Everything resolves cleanly, but the address belongs to no crawler this tool knows. The normal result for an ordinary visitor.
Try it on Bot Verification.
Finding the responsible registry over RDAP
An abuse report sent to the wrong block is the same as no report. A single address usually sits inside a hosting provider's allocation, which sits inside a transit provider's allocation, which belongs to a regional registry. Only the innermost operator can take the machine off the network.
The bootstrap file, not a redirector
There is no central directory of address space. IANA publishes a bootstrap file that maps every
allocated prefix to the registry responsible for it, and it is far smaller than most estimates
suggest: measured on 2026-09-20, ipv4.json was 5,629 bytes and
ipv6.json 1,476 bytes. A cached copy per day serves every visitor, so the lookup
talks to the registry directly instead of routing every query through a public redirector.
Longest prefix, not first match
Prefixes overlap. A small range inside an old, large allocation frequently belongs to a different registry than its parent, so the first matching prefix is regularly the wrong one. The match has to be the longest one.
The contact with the abuse role
An RDAP response carries several contact entities, and the first one is usually administrative
rather than operational. The address the tool returns comes from the entity that carries the
abuse role. If a network publishes none, the result says so rather than falling back
to an unrelated contact: the registry and the holder of the block are then the next places to go.
Try it on Abuse Contact, and see IP Delisting for the other direction.
Blacklist queries
The query format
A DNSBL is queried by reversing the address and appending the zone. For IPv4 that is the octets in reverse order; for IPv6, RFC 5782 specifies the nibble format, every hex digit separately and in reverse:
192.0.2.1 -> 1.2.0.192.<zone>
2001:db8::1 -> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.<zone>
Not every list answers for IPv6
Nine of the twelve curated lists publish an IPv6 zone; three do not. Querying an IPv4-only zone for an IPv6 address returns NXDOMAIN, which is indistinguishable from a clean result. Those three are therefore not queried at all for IPv6 and are reported as not applicable, so an empty answer is never presented as a pass.
Which lists answer is verified rather than assumed: every zone in the set replies to the RFC 5782 test entry from this server's resolver. Lists that structurally cannot be queried from a shared resolver are excluded, among them Spamhaus ZEN, which answers a public resolver with a block code instead of a result.
Reading the return code
A hit is signalled by an A record in 127.0.0.0/8, and the exact value carries the
reason. One range is not a listing at all: codes in 127.255.255.0/24 are reserved
for query errors, a blocked public resolver, an exceeded rate limit or a malformed query. Reading
those as a hit turns an infrastructure problem into a false accusation.
| Answer | Reading |
|---|---|
| A record in 127.0.0.0/8 | Listed, the code says why |
| A record in 127.255.255.0/24 | Query error, not a listing |
| NXDOMAIN or NOERROR without an answer | Not listed |
| Timeout, SERVFAIL, REFUSED | List unreachable, no statement either way |
Try it on DNSBL Blacklist Check. Our own zone is documented under DNSBL / RBL Zone.
Fetching a page safely
The header check is the only tool that fetches a URL the visitor names, which makes it a server-side request forgery surface. The fetch is restricted accordingly:
- Only
httpandhttps, only ports 80 and 443. - The hostname is resolved and every returned address is checked against the private, loopback, link-local, CGNAT and multicast ranges, in both address families.
- Addresses that carry an IPv4 address inside an IPv6 one are unwrapped before the check: v4-mapped, v4-compatible, NAT64 and 6to4. Missing 6to4 is a documented way around filters of this kind, since
2002:7f00:1::is loopback and2002:c0a8:101::is 192.168.1.1. - Redirects are followed manually, at most three times, with the full check repeated on each hop.
- A hard timeout, and only the first few kilobytes of the body are read.
- The request uses GET rather than HEAD, because a number of servers answer HEAD with a different header set.
Try it on Security Headers. How the findings turn into a number is described under Tool Scoring.
Last updated: · Maintained by the ReportedIP team