将一个普通的 requests 脚本对准受 Cloudflare 保护的站点,通常在真正的内容加载之前,你就已经得到一个 403 或验证页面了。这不是你代码的 bug。Cloudflare 的机器人管理部署在数百万个站点面前,它正在做它被设计来做的事:区分浏览器和脚本,并丢弃脚本。你的 HTTP 客户端发起的握手、它发送的请求头,以及它出口的 IP,都被读取为自动化行为,你在第一轮往返中就被标记了。

本文讲的是如何可靠地访问公开页面而不触发这些防御措施,而不是关于如何突破安全控制来获取你无权访问的数据。Cloudflare 的机器人防护是针对 DDoS、凭据滥用和激进爬取的合法防御手段,它拦截的大量流量确实该被拦截。这里的目标更窄、也更诚实:让一个对公开内容进行合法爬取的爬虫,看起来像它本来就是的那种普通浏览器流量,从而不再被这张为滥用而设的网捕获。明确了这一范围后,下面逐层解析 Cloudflare 如何判定你是机器人、为何简单的爬虫会即刻失败,以及什么方式真正能通过检测。

Cloudflare 如何判定你是机器人

Cloudflare 不只运行一项检查,而是堆叠多项检查,每一项观察的是不同的信号。将它们分为两组会很有帮助:被动检查读取你的请求本身而无需你做任何事,主动检查则让你的客户端去完成真实浏览器能做而脚本通常不能做的事情。

被动检测:你的请求已经暴露的信息

被动检查发生在任何页面渲染之前,在请求到达时就对其进行检查。

  • IP 信誉与频率限制。Cloudflare 对你的流量出口 IP 进行评分。已知托管和云计算 ASN(数据中心网段)中的地址默认可信度较低,任何单个 IP 快速发出重复请求都会很快触发频率限制。一个来自云服务器的干净脚本,还没发出第一个请求头就已经处于不利地位了。
  • TLS 与 JA3 指纹。你的客户端做的第一件事就是发起 TLS 握手,而该握手的形状(密码套件列表、扩展项及其在 Client Hello 中的顺序)构成一个指纹,通常以 JA3 哈希值来概括。真实的 Chrome 和 Firefox 产生广为人知的指纹。Python 或 Go HTTP 客户端产生的指纹与任何浏览器都不同,Cloudflare 在连接完成之前就能标记它。
  • 请求头与 User-Agent 一致性。浏览器发送一组特定的、有序的请求头,且 User-Agent 与其余部分匹配。脚本往往发送较少的请求头集合,遗漏浏览器总会包含的那些字段,或者声称是 Chrome 却携带着没有任何真实 Chrome 会发出的请求头配置。Cloudflare 会直接检查这种不连贯性。

主动检测:你的客户端被要求证明什么

如果被动信号存在歧义,Cloudflare 会升级并让客户端完成一些工作。

  • JavaScript 挑战。Cloudflare 返回一个包含混淆 JavaScript 的中间页面,客户端必须执行该脚本才能获得通行令牌。真实浏览器运行后自动继续。不执行 JavaScript 的 HTTP 客户端只是收到该挑战页面后就停在那里了。
  • Turnstile 与 CAPTCHA。当怀疑程度更高时,Cloudflare 会呈现 Turnstile(其 CAPTCHA 替代品)或完整的验证挑战。这些都是专门为让自动化难以独立通过而构建的。
  • 行为分析。在初始页面之后,Cloudflare 观察请求的模式:时序、导航顺序,以及在交互式挑战中,类似指针移动等信号。以完美均匀、机器节奏、无任何变化的节律到来的流量,看起来完全不像真人,会被升级处理。
两个层级,两种失败模式

一个请求可能在被动层失败(错误的 IP 或 TLS 签名,在页面加载之前就被标记),也可能在主动层失败(收到一个无法执行的 JavaScript 挑战)。知道是哪一层捕获了你,才能知道该修什么。更好的 IP 对未执行的挑战毫无帮助,而无头浏览器对在握手阶段就被拒绝的数据中心 IP 也毫无帮助。

为何简单的爬虫会即刻失败

一个裸的 requests.get()httpx 调用的失败,与你的解析逻辑毫无关系。它发起的是一个非浏览器签名的 TLS 握手,发送稀薄的请求头集合,并且无法执行 JavaScript。因此它在指纹和请求头层面被被动层捕获,如果侥幸通过了,也会在主动层因没有引擎运行挑战而停滞。你想要的页面从不渲染,你看到的是 403 或挑战中间页,而不是内容。

换入单个数据中心代理并不能解决这个问题。它把出口 IP 换成另一个低信任的托管地址,对 TLS 指纹、请求头,或缺失的 JavaScript 引擎毫无影响。你改变了四个信号中的一个,而且还不是最可能出错的那个。这就是"我加了代理却还是被封"如此普遍的原因。该代理对一个层级是必要的,对其他层级则无关紧要。关于这一问题在众多反爬系统中更广泛的版本,请参阅如何在不被封锁的情况下抓取网站

真正能通过的方法(按优先级排序)

要在公开页面上通过 Cloudflare 检测,你必须大致按照以下顺序满足各个层级的要求。下面的每一项都通过一个特定的检测层,跳过任何一项都会留下一个漏洞供对应的检查发现。

  1. 以低单 IP 频率轮换住宅 IP。这能通过 IP 信誉和频率限制检测。住宅代理从真实消费者 ISP 连接出口,因此 Cloudflare 将其读取为普通访客而非托管流量。在一个池中轮换能使任意单个地址上的请求频率保持在低位,即便总量很高,也不会触发频率限制。参见数据中心代理与住宅代理的对比了解 IP 来源为何如此重要,以及轮换住宅代理了解轮换模式。
  2. 能执行挑战的真实浏览器引擎。这能通过 JavaScript 挑战层。Puppeteer、Playwright 或无头 Chrome 确实能运行混淆的挑战脚本并获取通行令牌,而普通 HTTP 客户端做不到。隐身插件能减少无头浏览器特有的特征(那些出卖受控浏览器身份的自动化标志和环境怪癖),让引擎看起来像一个普通浏览器。
  3. 连贯的请求头与匹配的 TLS 指纹。这能通过指纹识别和请求头一致性检查。TLS 握手和请求头必须与你所声称的浏览器相匹配:如果你的 User-Agent 写的是 Chrome,那么 JA3 指纹和请求头集合也应该是 Chrome 的。真实浏览器引擎天然能做到这一点,这部分是它们能通过而手工构建的请求头字典做不到的原因。更深入的机制请参阅浏览器指纹识别
  4. 符合人类节奏的行为。这能通过行为分析。变化请求时序,避免在紧密循环中轰炸请求,以合理的顺序导航。目标不是伪装成一个四处点击的真人;而是避免那种本身就会标记一次运行的完美均匀、机器式节奏。将变化的状态码视为此处的信号:一个开始返回 403 或挑战页面的运行,正在告诉你某个层级已不再满足。代理状态错误码一文介绍如何读取它们。

有一项技术值得点名,这样你就可以跳过它:直接访问源站 IP 以绕过 Cloudflare。它出现在一些旧指南中,称为"源站 IP 发现",但这既不可靠也不可取。大多数源站都被配置为拒绝未经 Cloudflare 转发的流量,发现的 IP 会过期,整个思路读起来像是在对抗而非合法访问公开页面。坚持以访客方式加载页面的路径。

Cloudflare 信号与通过方法对照

检测信号 简单脚本的行为 通过方法
IP 信誉 从数据中心 ASN 出口 轮换住宅 IP,被识别为真实用户
频率限制 单个 IP 发出大量请求 低单 IP 频率,分散到整个 IP 池
TLS / JA3 指纹 非浏览器握手签名 真实浏览器引擎的原生握手
请求头一致性 稀薄或不匹配的请求头 与所声称浏览器匹配的连贯请求头
JavaScript 挑战 无法执行脚本 Puppeteer / Playwright / 无头 Chrome
行为分析 均匀的机器节奏循环 多样化的、符合人类节奏的请求时序

逐行看这张表,失败模式一目了然:简单爬虫在每一行都失败,而单个代理只修复了前两行。你需要同时覆盖所有层,这正是工程成本所在。

自行构建的成本

你可以在内部组装完整的技术栈。搭建一个轮换住宅 IP 池,运行一个带有隐身插件的无头 Chrome 集群以通过挑战,保持 TLS 和请求头配置与你所模拟的浏览器版本一致,并控制流量节奏。它能奏效。但这也是一项持续的维护负担:隐身插件随浏览器版本更新而滞后,挑战脚本会变化,指纹会被重新分类,无头集群必须随你的请求量扩容。对于一次性抓取,这可能还行。对于一个必须持续运行的数据管道,你现在维护的是反爬基础设施,而非真正使用数据的那个东西。

另一种选择是将所有四个层面折叠在单一端点后面,让你的代码保持为一个普通的 HTTP 请求。这正是 Crawlbase Smart AI Proxy 所做的。

Crawlbase Smart AI Proxy

Cloudflare 同时需要受信任的 IP、真实的浏览器握手、已执行的挑战以及符合人类节奏的流量。Smart AI Proxy 将住宅轮换、JavaScript 渲染、指纹一致性和挑战处理整合进一个反向连接端点,让你只需将普通 HTTP 客户端指向单一主机,而无需运行代理池和无头浏览器集群。先在免费套餐上对一个受保护的公开页面进行测试。

使用 Smart AI Proxy 的工作示例

Smart AI Proxy 是一个反向连接网关:一个主机和端口,你将普通 HTTP 客户端指向它,轮换、渲染、指纹一致性和挑战处理均在服务端完成。你以访问令牌作为代理用户名传入。从你的代码角度来看,这只是一个代理,所以下面的请求看起来和其他任何 requests.get() 一样。

首先,安装唯一的依赖项。

bash
pip install requests

然后通过网关将一个请求路由到受 Cloudflare 保护的公开页面。令牌放在代理 URL 中,同一个代理用于 HTTP 和 HTTPS 流量。

python
import requests

# Backconnect gateway: token as the username, rotation and rendering server-side.
proxy_url = "http://[email protected]:8012"
proxies = {"http": proxy_url, "https": proxy_url}

url = "https://example.com/protected-page"
resp = requests.get(url, proxies=proxies, verify=False)

print(resp.status_code)
print(resp.text[:500])

YOUR_CRAWLBASE_TOKEN 替换为你在控制台中的令牌。网关会像真实浏览器一样解析页面:住宅 IP、浏览器形状的握手、出现挑战时执行它,并将渲染后的 HTML 交给你的脚本。你的代码从不碰代理池或无头浏览器;它只发出一个普通的 GET 请求并读取结果。verify=False 标志跳过代理连接的本地证书验证,这对于此类网关来说是预期行为。

如果你想在不使用代理式接口的情况下获得同等覆盖,轮换代理模式和 Crawling API 通过请求 URL 而非代理接口暴露相同的引擎,某些数据管道会更倾向于这种方式。

诚实的部分:服务条款与合法性

你是否可以爬取某个特定站点,取决于该站点的服务条款以及你和该站点所在的司法管辖区,这是真实的约束,而非注脚。Cloudflare 存在于某个站点前面并不能本身决定这个问题,但该站点自身的规则决定了它。几条值得坚守的原则:只收集公开数据,遵守站点的 robots.txt 和频率预期,绝不获取认证后的内容或你没有依据收集的个人数据。用于分析的公开页面是一回事;收集登录墙后的或个人信息是另一回事,后者是法律和伦理风险所在。如果一个项目需要的不仅仅是公开数据,正确答案是官方 API 或与站点达成协议,而非更激进的爬虫。如果在合法访问的过程中遇到交互式挑战,如何在网络爬取中绕过 CAPTCHA 在同样负责任的框架内涵盖了这一环节。

回顾

核心要点

  • Cloudflare 堆叠多项检查。IP 信誉和频率限制、TLS 与请求头指纹识别、JavaScript 挑战以及行为分析,每项都读取不同的信号,分为被动和主动两个层级。
  • 简单爬虫在每一层都失败。普通 HTTP 客户端发送非浏览器握手、稀薄的请求头,且无法执行挑战,因此在页面加载之前就被标记了。
  • 每层一种修复方法。轮换住宅 IP 通过信誉和频率检测,真实浏览器引擎通过挑战,连贯的请求头与 TLS 通过指纹识别,人类节奏通过行为检测。
  • 跳过源站 IP 技巧。直接访问源站是脆弱且对抗性的;坚持以访客方式加载公开页面的路径。
  • 坚守公开数据。合法性取决于服务条款和司法管辖区;遵守 robots.txt 和频率限制,绝不触碰认证墙后或个人数据。

常见问题

为什么我的爬虫即使加了代理,仍然从 Cloudflare 得到 403?

代理只改变了 IP,而 IP 只是 Cloudflare 检查的四个信号之一。如果你使用的是数据中心代理,IP 仍然是低信任的;无论如何,你的 TLS 指纹、请求头和缺失的 JavaScript 引擎都未发生变化。要通过 403,通常需要轮换住宅 IP 加上能执行挑战的真实浏览器引擎,而不仅仅是换一个出口地址。

什么是 JA3 或 TLS 指纹,为什么它会标记我的脚本?

你的 TLS 握手具有可识别的形状(密码套件、扩展项及其顺序),可以被哈希成通常称为 JA3 的指纹。真实浏览器产生广为人知的指纹,而 Python 和 Go HTTP 客户端产生的指纹没有任何浏览器会产生。Cloudflare 可以在握手过程中就标记这种不匹配,在你的请求到达页面之前,这就是为什么即使请求头完美,脚本也可能失败。

我需要无头浏览器才能绕过 Cloudflare 吗?

你需要某种能执行 JavaScript 挑战的东西,而普通 HTTP 客户端做不到。这可以是你自己的无头 Chrome、Puppeteer 或 Playwright(最好配合隐身插件),或者一个在服务端渲染的网关。一个在一次请求中同时处理渲染和 IP 的托管端点,可以避免自行运行和扩展浏览器集群。

仅凭轮换住宅代理就能通过 Cloudflare 吗?

它们能通过 IP 信誉和频率限制检测,但不能通过 JavaScript 挑战或指纹识别层。如果一个站点只进行被动 IP 检查,住宅轮换可能就足够了;如果它提供主动挑战,你仍然需要浏览器引擎来执行它。将 IP 视为必要但并非总是充分的条件,并将技术栈的其余部分匹配到你实际遇到的挑战级别。

为了网络爬取而绕过 Cloudflare 合法吗?

这取决于站点的服务条款和你所在的司法管辖区,而不取决于 Cloudflare 是否在场。遵守 robots.txt 和合理频率限制来访问公开数据,通常比收集认证墙后或个人数据更具可辩护性,后者承担着真实的法律和伦理风险。如有疑问,坚守公开内容,对于超出此范围的需求,寻求官方 API 或协议。

我应该找到源站 IP 来完全绕过 Cloudflare 吗?

不应该。所谓的源站 IP 发现既脆弱又具对抗性:大多数源站拒绝未经 Cloudflare 转发的流量,IP 会过期,而且整个方式是为了规避保护而非访问公开页面。用受信任的 IP 和真实浏览器引擎以访客方式加载页面即可。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量