一个 AI 代理刚刚访问了你的网站,你怎么确认它是真的?
写着 GPTBot 的 User-Agent 什么也证明不了。本文说明如何真正验证 AI 代理:官方公布的 IP 段、反向 DNS 与 ASN 核对,以及如何为验证不通过的流量分类。
一个 AI 代理刚刚请求了一个页面,日志里写着 GPTBot/1.2。这串文字并不是证据。User-Agent 由客户端
自行写入,任何人都能发送,因此验证 AI 代理唯一可靠的途径,是核对它发起连接所用的地址。真正起作用的
检查只有三种:把来源 IP 与运营方公布的 IP 段文件比对、执行正向确认的反向 DNS 查询,或确认该 IP 由运
营方自己的 ASN 通告。
究竟适用哪一种,完全取决于运营方,而这正是麻烦所在。OpenAI 按 bot 分别公布 JSON 格式的 IP 段文件; Anthropic 只公布一个前缀文件,同时覆盖 ClaudeBot、Claude-User 与 Claude-SearchBot;Apple 既支持反向 DNS,也提供 IP 段文件;Meta 两者都不提供,默认由你自行核对 AS32934。还有相当一部分爬虫什么都不公布, 此时请求头里的名字只是装饰,你只能依据来源与行为做判断。
声称不花钱,核验才花钱
不妨想想「User-Agent 含有 GPTBot 就跳过机器人规则」这样一条放行规则究竟意味着什么。它等于宣布:任何 愿意敲下九个字符的客户端,都能获得你原本只留给可信爬虫的待遇。爬虫会读你的 robots.txt,看清楚你欢迎 哪些代理,然后照着打扮。这种冒充谈不上高明,只是成本极低,而且对任何从不看请求头以外信息的站点都有效。
核验的代价则要高得多。你需要运营方当前的 IP 段、一个 DNS 解析器或路由数据,逐家维护,并在对方变更时 同步更新。已经有研究者报告过自称 PerplexityBot、却来自 Perplexity 公布范围之外地址的流量。这正是典型 的失效场景:名字是借来的,网络不是。
查询某个代理请求实际来自哪个网络
每一家运营方的文档都不一样
这件事没有统一标准,验证只能逐家查。以下是AI 爬虫目录中的一部分,该目录收录了 150 个代理:
| 代理 | 运营方 | 公布内容 | 验证方式 |
|---|---|---|---|
| GPTBot | OpenAI | openai.com/gptbot.json | 比对 IP 段,无反向 DNS 约定 |
| ClaudeBot | Anthropic | claude.com/crawling/bots.json | 比对 IP 前缀,一个文件覆盖 Anthropic 全部 bot |
| PerplexityBot | Perplexity | perplexitybot.json | 比对 IP 段,已出现冒充案例 |
| Applebot | Apple | IP 段文件与 rDNS | 反向 DNS 解析至 applebot.apple.com,并正向确认 |
| Amazonbot | Amazon | 反向 DNS 约定 | 正向确认的反向 DNS,无 IP 段文件 |
| Meta-ExternalAgent | Meta | 未按 bot 公布 | 确认该 IP 由 AS32934 通告 |
| Bytespider | ByteDance | 无 | 无法验证,且无视 robots.txt |
| CCBot | Common Crawl | 无可用信息 | 无法验证,运行在租用的云资源上 |
| Google-Extended | 仅 robots 令牌 | 无从验证,它从不作为 User-Agent 出现 |
Google-Extended 值得多看一眼,因为它打破了常见的认知模型。它是一条用于退出 Gemini 训练的 robots.txt 指令,而不是爬虫。如果收到自称 Google-Extended 的请求,那按定义就是伪造的,因为根本不存在真实版本。
目录收录的 150 个代理中,有 33 个提供了可用的核验方式,即公布的 IP 段、反向 DNS 或 ASN;有 9 个被明 确记录为无视 robots.txt。其余则处于中间地带:只有一个名字,没有任何东西为它背书。
冒充在日志里长什么样
两条请求,请求头完全相同,相隔几分钟:
198.51.100.7 "Mozilla/5.0 ...; compatible; GPTBot/1.2; +https://openai.com/gptbot"
203.0.113.44 "Mozilla/5.0 ...; compatible; GPTBot/1.2; +https://openai.com/gptbot"
单看日志行毫无差别。把地址解析出来,差别立刻显现:一个落在 OpenAI 公布的出口 IP 段内,另一个由一家按 小时出租服务器的主机商通告。后者还在九十秒内请求了 400 个商品页,且从未加载任何样式表,而遵守自身公布 抓取配额的爬虫不会这样做。
同样的模式在各家运营方身上反复出现:来自 VPS 网段的假 ClaudeBot;PTR 记录指向主机商域名、甚至根本没有 PTR 记录的假 Applebot;PTR 看起来合理、但正向解析却返回另一个地址的假 Amazonbot,而正向确认这一步存在 的意义正在于此。每一次,请求头都完全吻合,网络却对不上。
已验证、无法验证与恶意,是三种不同的答案
一旦不再把请求头当作证据,流量就会分成几类需要区别对待的群体,而一个二元的机器人标记无法表达这种差异。
已验证的 AI 爬虫属于策略选择:放行、计费,或按名称拦截,因为你不希望内容进入那份语料。声称某个身份却 未通过 IP 核验的请求则不是策略问题,而是伪造,绝不应继承真实代理所享有的访问权限。完全没有公布任何信息 的爬虫无法验证,需要的是限速而不是判定。至于来自数据中心网段、 根本不声称任何 bot 名称的无头浏览器,恰恰是你的放行名单从未关注过的那一类。
正因如此,Agentscan 返回的是类别而非布尔值。每个请求都会得到 human、known_bot、
ai_agent 或 malicious_automation 之一,并附带置信度以及形成该判定的各项信号。
伪造 User-Agent 也骗不过的信号
IP 来源能回答大部分问题,但不是全部。代理可以运行在住宅地址上,爬虫也可以租一个没有历史记录的干净 IP。 当请求头说谎时,还有三类信号站得住脚:
JA4 TLS 指纹。 客户端在发送第一个请求头之前,就已经暴露了自己如何进行 TLS 交握:加密套件顺序、扩展、 ALPN、版本。一个自称 Chrome 124 的 Python 脚本,产生的握手特征是任何 Chrome 版本都不会产生的。请求头是 声称,握手是行为。
无头浏览器痕迹。 webdriver 标记、缺失的浏览器接口,以及 Playwright、Puppeteer 或原生 HeadlessChrome
留下的自动化标记。单独看每一项都很弱,但与数据中心来源叠加,画面就不再含糊。
请求头一致性。 真实浏览器会成组发送 Accept、Accept-Language 与 Accept-Encoding,顺序稳定,并与所声称 的版本相符。手工构造的请求对象往往只发送其中一部分,而这些缺口足够规律,可以作为信号使用。
任何一项信号都不足以单独定案,这正是关键所在。只有把它们融合起来,才能把已验证的爬虫与技术娴熟的冒充者 区分开,并把两者与普通访客区分开。同样的叠加逻辑也适用于更早的爬虫,详见 如何验证 Googlebot。
一套经得起真实流量考验的策略
验证只有在之后产生动作时才有意义。一个可行的默认方案:
- 在任何放行规则生效之前,先按该运营方的方法核验身份。 IP 段文件、反向 DNS 还是 ASN,取决于对方公布 了什么。
- 核验失败不是模糊信号。 自称 ClaudeBot 却来自 Anthropic 前缀之外的请求就是冒充。按未知爬虫处理, 而不是当作有待商榷的情况。
- 按用途拆分放行决策。 训练爬虫、AI 搜索爬虫与助手取页请求应各有规则。拦截搜索爬虫会让你从该引擎 引用的答案中消失,这是流量决策,不是安全决策。
- 对无法验证的流量限速。 对 Bytespider、CCBot 以及其他未公布核验方式的代理,名字说明不了任何问题, 但请求频率、路径模式与来源能说明很多。
- 记录类别,而不只是拦截数。 知道 AI 代理流量上个月增长了两倍,比一个拦截计数器有价值得多,尤其是 在你还要决定把哪部分变现的时候。
Agentscan 通过一次 POST /v1/agentscan/check 完成上述工作:经反向 DNS 验证的放行名单、公布 IP 段比对、
IP 来源、无头标记与 JA4 全部在一次调用中处理,并带缓存,重复查询在 50 毫秒内返回。这个速度足以放进中间件,
而不必留给夜间的日志复盘。
总结
你无法凭一个代理的自称来验证它。把来源 IP 与运营方真正公布的信息比对,把核验失败视为伪造,再用 JA4、 无头痕迹与 IP 来源去判断放行名单无法担保的其余流量。问题从来不是「这是不是机器人」,而是刚刚到达的属于 四类流量中的哪一类,以及你打算如何对待每一类。