Cloudflare Turnstile 是一种以隐私为核心的 CAPTCHA 替代方案,它在后台静默运行。与传统 CAPTCHA 不同,它很少显示可见的挑战,而是收集浏览器信号并签发一个 token,由站点后端验证。
本指南演示如何通过 CaptchaAI API 程序化地解决 Turnstile 挑战。如果你还没有读过 CaptchaAI 快速入门,建议先了解整体的 4 步流程。
前置条件
| 项目 | 值 |
|---|---|
| CaptchaAI API key | 在 captchaai.com 仪表盘获取 |
| Turnstile sitekey | 从目标页面提取(以 0x 开头) |
| 页面 URL | Turnstile 出现的完整 URL |
| 编程语言 | Python 3.7+ 或 Node.js 14+ |
第 1 步:找到 Turnstile sitekey
sitekey 通常出现在页面 HTML 中,位于 div 或 script 标签内:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQFLr1GavNl"></div>
或者由 JavaScript 动态渲染:
turnstile.render('#widget', {
sitekey: '0x4AAAAAAAC3DHQFLr1GavNl',
callback: function(token) { /* ... */ }
});
三种提取方式:
- 浏览器开发者工具:打开 DevTools → Elements,搜索
data-sitekey或cf-turnstile。 - 源代码搜索:
Ctrl+U查看页面源代码,搜索0x前缀字符串。 - 网络面板:在 Network 中过滤
challenges.cloudflare.com,请求参数中含 sitekey。
Turnstile sitekey 始终以
0x开头,长度通常为 22 个字符。这是与 reCAPTCHA6L...前缀区分的关键。
第 2 步:提交解题请求
向 https://ocr.captchaai.com/in.php 发送 POST 请求,method 为 turnstile:
import requests
API_KEY = "YOUR_CAPTCHAAI_KEY"
SITEKEY = "0x4AAAAAAAC3DHQFLr1GavNl"
PAGEURL = "https://staging.example.com/qa-login"
r = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": SITEKEY,
"pageurl": PAGEURL,
"json": 1,
})
data = r.json()
if data["status"] != 1:
raise RuntimeError(f"submit failed: {data}")
task_id = data["request"]
print("task id:", task_id)
Node.js 等价写法:
const axios = require("axios");
const { data } = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: process.env.CAPTCHAAI_KEY,
method: "turnstile",
sitekey: "0x4AAAAAAAC3DHQFLr1GavNl",
pageurl: "https://staging.example.com/qa-login",
json: 1,
},
});
if (data.status !== 1) throw new Error(`submit failed: ${JSON.stringify(data)}`);
const taskId = data.request;
成功响应:{"status": 1, "request": "<task_id>"}。保存 task_id 用于轮询。
第 3 步:轮询结果
Turnstile 通常在 10–25 秒内完成。先等 10 秒,然后每 5 秒轮询一次,最多 40 次(约 200 秒上限):
import time
time.sleep(10)
for _ in range(40):
r = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
res = r.json()
if res["status"] == 1:
token = res["request"]
break
if res["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(f"solver error: {res}")
time.sleep(5)
else:
raise TimeoutError("turnstile solving timed out")
print("token (前 60 字符):", token[:60])
返回的 token 是一段 Base64 字符串,通常以 0. 开头,长度约 400–600 字符。
第 4 步:将 token 注入页面
获取 token 后,需要把它放进 Turnstile 表单的隐藏字段 cf-turnstile-response 中,然后提交表单。
Selenium 示例:
driver.execute_script(
"document.querySelector('[name=cf-turnstile-response]').value = arguments[0];",
token,
)
driver.find_element("css selector", "form").submit()
Playwright 示例:
page.evaluate(
"(t) => document.querySelector('[name=cf-turnstile-response]').value = t",
token,
)
page.click("button[type=submit]")
纯 HTTP 提交: 把 token 作为 cf-turnstile-response 字段加入 application/x-www-form-urlencoded 请求体。
Turnstile token 默认有效期约 120–300 秒,必须在拿到 token 后立即使用,否则后端会返回
timeout-or-duplicate错误。
完整 Python 示例
import os, time, requests
API = "https://ocr.captchaai.com"
KEY = os.environ["CAPTCHAAI_KEY"]
def solve_turnstile(sitekey: str, pageurl: str) -> str:
r = requests.post(f"{API}/in.php", data={
"key": KEY, "method": "turnstile",
"sitekey": sitekey, "pageurl": pageurl, "json": 1,
}, timeout=30)
j = r.json()
if j["status"] != 1:
raise RuntimeError(f"submit: {j}")
tid = j["request"]
time.sleep(10)
for _ in range(40):
r = requests.get(f"{API}/res.php", params={
"key": KEY, "action": "get", "id": tid, "json": 1,
}, timeout=30)
j = r.json()
if j["status"] == 1:
return j["request"]
if j["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(f"poll: {j}")
time.sleep(5)
raise TimeoutError("timeout")
if __name__ == "__main__":
print(solve_turnstile("0x4AAAAAAAC3DHQFLr1GavNl", "https://staging.example.com/qa-login"))
常见错误
| 错误码 | 含义 | 处理建议 |
|---|---|---|
ERROR_WRONG_USER_KEY |
API key 格式错误 | 检查 CAPTCHAAI_KEY 是否完整 |
ERROR_KEY_DOES_NOT_EXIST |
API key 不存在 | 确认从仪表盘复制的 key |
ERROR_ZERO_BALANCE |
账户余额为零 | 充值后重试 |
ERROR_PAGEURL |
缺少 pageurl 参数 | 确保传入完整 URL(含 https://) |
ERROR_CAPTCHA_UNSOLVABLE |
多次尝试均失败 | 验证 sitekey 与 pageurl 配对正确,重试一次 |
更多错误码与排查思路见 reCAPTCHA v2 教程 中的错误表。
它不工作时
- 检查 sitekey 是否动态变化:部分 Cloudflare 站点每次访问会签发新 sitekey,需要先抓取页面再提取。
- 核对 pageurl:Turnstile 后端校验严格,pageurl 必须精确匹配实际页面(包含路径,不含 query)。
- TLS 特征:Cloudflare 可能根据客户端 TLS 特征拒绝请求。建议从真实浏览器或
curl_cffi、Playwright 发起后续请求。 - token 过期:拿到 token 后 2 分钟内必须使用,否则需要重新求解。
- 代理 IP 质量:低质量数据中心 IP 容易触发额外挑战,建议使用住宅或自有服务器基础设施。
下一步
- 阅读 CaptchaAI 快速入门 了解通用 4 步流程
- 查看 reCAPTCHA v2 解决方案 学习另一个高频场景
- 注册 captchaai.com 获取 API key 并开始解决 Turnstile
立即注册 CaptchaAI 开始解决 Turnstile。