Cloudflare Turnstile là một giải pháp thay thế CAPTCHA tập trung vào quyền riêng tư, chạy ngầm trong nền. Khác với CAPTCHA truyền thống, nó hiếm khi hiển thị thử thách trực quan; thay vào đó, nó thu thập tín hiệu trình duyệt và phát hành một token để backend của trang web xác minh.
Hướng dẫn này trình bày cách giải Turnstile theo lập trình bằng API CaptchaAI. Nếu bạn chưa đọc CaptchaAI Quickstart, hãy bắt đầu từ đó để nắm luồng 4 bước chung.
Yêu cầu
| Mục | Giá trị |
|---|---|
| API key CaptchaAI | Từ bảng điều khiển tại captchaai.com |
| Sitekey Turnstile | Lấy từ trang đích (bắt đầu bằng 0x) |
| URL trang | URL đầy đủ nơi Turnstile xuất hiện |
| Ngôn ngữ | Python 3.7+ hoặc Node.js 14+ |
Bước 1: Tìm sitekey Turnstile
Sitekey thường nằm trong HTML của trang, bên trong thẻ div hoặc script:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQFLr1GavNl"></div>
Hoặc do JavaScript render:
turnstile.render('#widget', {
sitekey: '0x4AAAAAAAC3DHQFLr1GavNl',
callback: function(token) { /* ... */ }
});
Ba cách trích xuất:
- DevTools trình duyệt — tab Elements, tìm
data-sitekeyhoặccf-turnstile. - Mã nguồn —
Ctrl+U, tìm chuỗi bắt đầu bằng0x. - Tab Network — lọc
challenges.cloudflare.com; sitekey nằm trong tham số request.
Sitekey Turnstile luôn bắt đầu bằng
0xvà thường dài 22 ký tự. Đó là điểm phân biệt với khoá reCAPTCHA bắt đầu bằng6L.
Bước 2: Gửi task
POST tới https://ocr.captchaai.com/in.php với 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)
Tương đương 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;
Phản hồi thành công: {"status": 1, "request": "<task_id>"}. Lưu task_id để polling.
Bước 3: Polling kết quả
Turnstile thường được giải trong 10–25 giây. Đợi 10 giây, sau đó polling mỗi 5 giây, tối đa 40 vòng:
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 ký tự đầu):", token[:60])
Token trả về là chuỗi Base64, thường bắt đầu bằng 0. và dài 400–600 ký tự.
Bước 4: Chèn token vào trang
Sau khi có token, đặt nó vào trường ẩn cf-turnstile-response trong form Turnstile rồi submit form.
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 thuần: thêm cf-turnstile-response=<token> vào body application/x-www-form-urlencoded.
Token Turnstile có hiệu lực khoảng 120–300 giây. Hãy dùng ngay sau khi nhận, nếu không backend sẽ trả
timeout-or-duplicate.
Ví dụ Python đầy đủ
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"))
Lỗi thường gặp
| Mã | Ý nghĩa | Hành động |
|---|---|---|
ERROR_WRONG_USER_KEY |
Định dạng API key sai | Kiểm tra CAPTCHAAI_KEY đầy đủ |
ERROR_KEY_DOES_NOT_EXIST |
Không tìm thấy key | Sao chép lại key từ bảng điều khiển |
ERROR_ZERO_BALANCE |
Số dư bằng 0 | Nạp tiền rồi thử lại |
ERROR_PAGEURL |
Thiếu pageurl | Gửi URL đầy đủ kèm https:// |
ERROR_CAPTCHA_UNSOLVABLE |
Giải thất bại | Đảm bảo sitekey và pageurl khớp; thử lại 1 lần |
Bảng lỗi đầy đủ trong hướng dẫn reCAPTCHA v2.
Khi không hoạt động
- Sitekey động. Một số trang Cloudflare phát hành sitekey mới mỗi lượt truy cập; scrape lại trang trước mỗi task.
- pageurl chính xác. Backend Turnstile so URL nghiêm ngặt; gửi đúng path, bỏ query string.
- Vân tay TLS. Cloudflare có thể chặn client dựa vào chữ ký TLS. Dùng
curl_cffi, Playwright hoặc trình duyệt thật. - Token hết hạn. Dùng trong vòng 2 phút, nếu không phải solve lại.
- Chất lượng proxy. IP datacenter giá rẻ thường kích hoạt thử thách bổ sung. Ưu tiên proxy residential hoặc mobile.