The operator's IP list
Google, Microsoft, OpenAI and others publish the address ranges their machines fetch from. A request from outside the list isn't theirs, whatever it says.
Reverse, then forward DNS
Look up the name behind the address, check it ends in the operator's domain, then look that name up and confirm it returns the same address.
A worked example
A request says it's Googlebot and comes from 66.249.66.1.
1.66.249.66.in-addr.arpa domain name pointer crawl-66-249-66-1.googlebot.com.
$ host crawl-66-249-66-1.googlebot.com
crawl-66-249-66-1.googlebot.com has address 66.249.66.1
The name ends in googlebot.com and points back to the same address, so it's Googlebot. A fake fails at the first step: its address resolves to a hosting company, or to nothing.
When there's no check
Slack publishes no way to verify Slackbot. LinkedIn and Meta can only be matched to the networks they own, which proves less: other services share some of those networks. For these, treat the user agent as a claim and decide what you'd lose if it's false.
| Machine | Check | Source |
|---|---|---|
| Googlebot | IP list or reverse DNS | common-crawlers.json |
| Bingbot | IP list or reverse DNS (search.msn.com) | bingbot.json |
| GPTBot | IP list | gptbot.json |
| ClaudeBot | IP list | bots.json |
| PerplexityBot | IP list | perplexitybot.json |
| Applebot | Reverse DNS (applebot.apple.com) | Apple's Applebot page |
| LinkedInBot | Network only (weak) | LinkedIn's address ranges |
| Slackbot | None published | None |