Guide

2026 年如何爬取 Cloudflare 保护的网站 — 完整指南

10 分钟阅读

Cloudflare 保护了互联网上超过 20% 的网站。如果你在 2026 年构建网页爬虫,你不可避免地会遇到 Cloudflare 保护 — 无论是登录表单上的 Turnstile 小组件、JS Challenge 中间页,还是 WAF 级别的全面 Bot Management。本指南详细介绍每种保护类型,解释最常见的绕过方法,并提供可直接运行的代码示例。

Cloudflare 保护类型

Cloudflare 提供三种主要保护层,你在爬取时会遇到这些保护。了解你面对的是哪种保护是绕过它的第一步。

Turnstile(验证码组件)
嵌入在表单中的验证码组件。生成服务器验证的 Token。常见于登录、注册和结账页面。
JS Challenge(浏览器检查)
全页面中间页,在浏览器中运行 JavaScript 检查。成功后设置 cf_clearance Cookie。阻止非浏览器客户端。
Bot Management(WAF 规则)
服务器端指纹识别和行为分析。检查 TLS 指纹、IP 信誉、请求模式。甚至可以阻止真实浏览器。

如何识别保护类型

在选择绕过方法之前,先确定你面对的是什么:

  • Turnstile:查找带有 cf-turnstile 类名的 «div» 或加载 challenges.cloudflare.com/turnstile 的脚本。HTML 源码中会包含 data-sitekey 属性。
  • JS Challenge:你会看到全页面的 "正在检查您的浏览器..." 界面。响应状态码为 403 并设置 __cf_bm Cookie。通过后获得 cf_clearance。
  • Bot Management / WAF:你会立即收到 403 Forbidden,没有挑战页面。或者看到 Cloudflare 的 "拒绝访问" 错误页面。通常基于 IP 信誉或 TLS 指纹。

常见绕过方法对比

有三种主流方法可以绕过 Cloudflare。每种在速度、可靠性和成本方面都有不同的权衡。

方法速度可靠性检测风险费用/千次
无头浏览器5-30秒60-80%$2-5
隐身插件5-20秒70-85%中等$1-3
Solver API推荐
0.25-5秒95%+$0.80-1.00

何时使用什么方法

不同的保护类型需要不同的方法。以下是快速决策指南:

Turnstile 验证码 — 使用 Solver API 获取 Token

将 siteKey 和页面 URL 发送到 Solver API。获取有效的 Token 后与表单数据一起提交。无需浏览器 — 仅需普通 HTTP 请求。NSLSolver 在约 250ms 内解决 Turnstile。

JS Challenge — 使用 Solver API 获取 Cookie + UA

Solver 运行 JavaScript 挑战并返回 cf_clearance Cookie 和匹配的 User-Agent 字符串。在后续请求中使用相同的 IP/代理。NSLSolver 在 2-5 秒内返回结果。

Bot Management / WAF — 住宅代理 + Solver API

WAF 规则检查你的 IP 信誉和 TLS 指纹。使用住宅代理通过 IP 检查,使用 Solver API 处理挑战页面。始终使用 solve 响应中返回的 User-Agent。

使用 NSLSolver 解决 Turnstile

对于 Turnstile 保护的表单,你只需要 siteKey 和页面 URL。API 返回一个你与表单一起提交的 Token:

Python
import requests

API_KEY = "nsl_YOUR_API_KEY"

# 1. Solve the Turnstile widget
solve = requests.post(
    "https://api.nslsolver.com/solve",
    headers={"X-API-Key": API_KEY},
    json={
        "type": "turnstile",
        "siteKey": "0x4XXXXXXXXXXXXXXXXX",
        "url": "https://target-site.com/login"
    }
)
token = solve.json()["token"]

# 2. Submit the form with the solved token
result = requests.post(
    "https://target-site.com/login",
    data={
        "username": "[email protected]",
        "password": "your_password",
        "cf-turnstile-response": token
    }
)
print(result.status_code)  # 200

使用 NSLSolver 解决 CF Challenge

对于 JS Challenge 页面,API 运行浏览器检查并返回 clearance Cookie 和 User-Agent。你必须在同一 IP 上同时使用这些:

Python
import requests

API_KEY = "nsl_YOUR_API_KEY"

# 1. Solve the CF Challenge — returns cookies + user agent
solve = requests.post(
    "https://api.nslsolver.com/solve",
    headers={"X-API-Key": API_KEY},
    json={
        "type": "challenge",
        "url": "https://target-site.com/protected-page"
    }
)
data = solve.json()

# 2. Use the returned cookies and user agent
session = requests.Session()
session.headers["User-Agent"] = data["userAgent"]
for cookie in data["cookies"]:
    session.cookies.set(cookie["name"], cookie["value"])

# 3. Access the protected page
page = session.get("https://target-site.com/protected-page")
print(page.status_code)  # 200
print(page.text[:500])

处理 Bot Management / WAF

当网站使用高级 Bot Management 时,你需要将住宅代理与 Solver API 结合使用。将代理传递给 solve 请求,以便 Cookie 绑定到该 IP:

Python
import requests

API_KEY = "nsl_YOUR_API_KEY"
PROXY = "http://user:[email protected]:8080"

# 1. Solve the challenge through a residential proxy
solve = requests.post(
    "https://api.nslsolver.com/solve",
    headers={"X-API-Key": API_KEY},
    json={
        "type": "challenge",
        "url": "https://target-site.com/data",
        "proxy": PROXY
    }
)
data = solve.json()

# 2. Use the same proxy + cookies for subsequent requests
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = data["userAgent"]
for cookie in data["cookies"]:
    session.cookies.set(cookie["name"], cookie["value"])

page = session.get("https://target-site.com/data")
print(page.json())

性能对比:无头浏览器 vs Solver API

运行自己的无头浏览器看起来像是 DIY 方案,但数据说明了不同的故事:

指标无头浏览器NSLSolver API
Turnstile 解决时间5-15s~250ms
Challenge 解决时间10-30s2-5s
成功率60-80%95%+
月成本(1万次解决)$50-200$8-10
维护高 — 需要持续更新

基于 2026 年 4 月的内部基准测试。无头浏览器成本包括服务器、代理和浏览器维护。

成本分析:自建 vs 购买

让我们来分析运行自己的无头浏览器爬虫基础设施与使用 Solver API 的真实成本:

自托管无头浏览器
$50-200/mo
  • 4+ GB RAM 的 VPS/云服务器
  • 住宅代理带宽
  • 浏览器补丁和反检测更新
  • 运维人员的维护时间
NSLSolver API
$0.80-1.00/1K solves
  • 按解决次数付费 — 无固定成本
  • 无需维护服务器
  • 无需管理代理(Turnstile 类型)
  • 注册即送 100 次免费解决

Cloudflare 爬取最佳实践

无论你使用哪种方法,遵循以下做法可以最大化成功率并避免被封:

  • 轮换代理:不要通过同一个 IP 发送所有请求。使用住宅代理池,按会话或请求批次轮换。
  • 匹配 User-Agent:始终使用 Solver 返回的确切 User-Agent 字符串。Cloudflare 将 cf_clearance Cookie 绑定到解决挑战时使用的 User-Agent。
  • 处理速率限制:尊重 429 响应。实现指数退避(1秒、2秒、4秒、8秒)。不要轰炸目标网站 — 将请求分散在一段时间内。
  • 添加重试逻辑:瞬态故障是存在的。在放弃之前重试 2-3 次失败的解决请求。上面的生产示例展示了这种模式。
  • 重用会话:获取有效 Cookie 后,重复使用它们进行多次请求。cf_clearance Cookie 通常有效期为 15-30 分钟。不要为每个请求都重新解决。
  • 注意 TLS 指纹:如果使用自己的 HTTP 客户端,确保其 TLS 指纹与真实浏览器匹配。curl_cffi (Python) 或 got-scraping (Node.js) 等库可以帮助解决这个问题。

生产级爬虫示例

以下是一个完整的 Python 爬虫,支持代理轮换、重试逻辑和会话重用来处理 Cloudflare Challenge 页面:

scraper.py
import requests
import time
import random

API_KEY = "nsl_YOUR_API_KEY"
BASE_URL = "https://api.nslsolver.com/solve"

PROXIES = [
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
]

def solve_cloudflare(url, solve_type="challenge", retries=3):
    """Solve Cloudflare protection with retry logic."""
    for attempt in range(retries):
        try:
            proxy = random.choice(PROXIES)
            resp = requests.post(
                BASE_URL,
                headers={"X-API-Key": API_KEY},
                json={
                    "type": solve_type,
                    "url": url,
                    "proxy": proxy,
                },
                timeout=30,
            )
            resp.raise_for_status()
            data = resp.json()

            if data.get("success"):
                return data, proxy

        except requests.RequestException as e:
            print(f"Attempt {attempt + 1} failed: {e}")

        if attempt < retries - 1:
            time.sleep(2 ** attempt)  # Exponential backoff

    return None, None

def scrape_page(url):
    """Scrape a Cloudflare-protected page."""
    data, proxy = solve_cloudflare(url)
    if not data:
        raise Exception("Failed to solve Cloudflare challenge")

    session = requests.Session()
    session.headers["User-Agent"] = data["userAgent"]
    session.proxies = {"http": proxy, "https": proxy}

    for cookie in data["cookies"]:
        session.cookies.set(cookie["name"], cookie["value"])

    response = session.get(url)
    response.raise_for_status()
    return response.text

# Usage
html = scrape_page("https://target-site.com/data")
print(f"Got {len(html)} bytes")

小贴士:cf_clearance Cookie 有效期为 15-30 分钟。在同一域名的请求中缓存并重复使用它们,以避免不必要的解决调用并节省费用。

今天就开始爬取 Cloudflare 网站

注册即送 100 次免费解决。无需信用卡。Turnstile 约 250ms,Challenge 2-5 秒。