Khắc Phục Sự Cố

Token Turnstile không hợp lệ sau khi giải: chẩn đoán và khắc phục

Token Turnstile bị từ chối gần như luôn là lỗi tích hợp, không phải lỗi lời giải. CaptchaAI trả về chuỗi hợp lệ; Cloudflare loại nó vì bạn gửi muộn, sai sitekey, sai tên trường hoặc lệch session.

Vì vậy, thứ tự chẩn đoán mới là điều quan trọng. Sáu nguyên nhân dưới đây xếp từ dễ loại trừ nhất tới tốn công nhất.


Kiểm tra nhanh trong 60 giây

  1. Token gửi sau khi nhận bao lâu? Quá 5 phút là hỏng.
  2. sitekey có đúng của form bạn submit không?
  3. Tên trường có phải cf-turnstile-response không?
  4. Load trang và submit cùng session chứ?
  5. Widget có data-action hoặc data-cdata không?

Đối chiếu triệu chứng với nguyên nhân

Khớp hiện tượng với cột bên phải trước khi sửa code.

Triệu chứng Nguyên nhân
403 khi gửi token Token hết hạn
Submit không phản hồi Sai tên trường
Nhận token nhưng vẫn bị chặn Sai sitekey
Lần đầu được, sau hỏng Token dùng lại
Trình duyệt được, script không Thiếu cookie phiên

Nguyên nhân 1: token hết hạn trước khi kịp gửi

Token Turnstile thường sống 300 giây (5 phút), có nơi ngắn hơn. Rủi ro nằm ở code chạy sau khi nhận token.

  • Worker nhận token rồi mới lấy CSRF token.
  • Job chờ trong hàng đợi vì rate limit.
  • Retry bên ngoài chạy lại cả hàm.

Chuẩn bị sẵn cookie, header và payload, rồi mới gọi giải.

import requests
import time

API_KEY = "YOUR_API_KEY"

# Submit Turnstile task
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile",
    "sitekey": "0x4AAAAAAADnPIDROz1234",
    "pageurl": "https://staging.example.com/qa-login",
    "json": 1
}).json()

task_id = submit["request"]
time.sleep(10)

# Poll for result
for _ in range(24):
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY, "action": "get", "id": task_id, "json": 1
    }).json()
    if result.get("status") == 1:
        token = result["request"]
        # USE TOKEN IMMEDIATELY — do not delay
        response = requests.post("https://staging.example.com/qa-login", data={
            "username": "user",
            "password": "pass",
            "cf-turnstile-response": token
        })
        break
    time.sleep(5)

Nếu vòng polling thường xuyên chạm tới lần lặp thứ 24, xem lại thiết lập timeout theo loại CAPTCHA.

Nguyên nhân 2: sai sitekey

Mỗi widget có sitekey riêng, và một trang thường có nhiều hơn một widget. Lấy đúng cái gắn với form bạn gửi:

// In browser console on the target page
document.querySelectorAll('[data-sitekey]').forEach(el => {
    console.log('Sitekey:', el.getAttribute('data-sitekey'));
    console.log('Element:', el);
});

Nếu trang chặn bằng màn hình chờ toàn trang thì đó là Cloudflare Challenge, và method tương ứng là cloudflare_challenge.

Nguyên nhân 3: sai tên trường chứa token

Turnstile đọc token ở cf-turnstile-response. Giữ lại g-recaptcha-response từ script reCAPTCHA cũ là lỗi copy-paste phổ biến nhất.

# WRONG — this is for reCAPTCHA
data = {"g-recaptcha-response": token}

# CORRECT — this is for Turnstile
data = {"cf-turnstile-response": token}

Nếu trang đổi tên trường, kiểm tra thẳng trên DOM:

// Check what field the Turnstile widget populates
document.querySelector('[name*="turnstile"], [name*="cf-"]')
  • null: form dùng tên tùy biến, đọc handler submit.
  • Form JSON: token nằm trong request body.

Nguyên nhân 4: token đã dùng một lần

Token Turnstile dùng một lần. Retry với cùng chuỗi đó chắc chắn hỏng, kể cả khi còn hạn.

  • Đặt retry ra ngoài hàm giải để mỗi lần thử có token mới.
  • Timeout ở tầng mạng vẫn tính là token đã tiêu.

Cloudflare đối chiếu token với ngữ cảnh phiên: giải ở session này rồi gửi ở session khác thường bị loại.

# Use the SAME session for page load and token submission
session = requests.Session()

# Load the page first to establish cookies
session.get("https://staging.example.com/qa-login")

# Then solve and submit using the same session
token = solve_turnstile(sitekey, pageurl)
session.post("https://staging.example.com/qa-login", data={
    "cf-turnstile-response": token
})

Pipeline nhiều tiến trình nên gắn session vào từng tác vụ, không dùng chung client.

Nguyên nhân 6: thiếu action hoặc cData

Một số triển khai gắn actioncData vào token; thiếu chúng trong request giải thì token sẽ lệch.

submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile",
    "sitekey": "0x4AAAAAAADnPIDROz1234",
    "pageurl": "https://staging.example.com/qa-login",
    "action": "login",           # If required by the site
    "data": "custom_cdata_value", # If required by the site
    "json": 1
}).json()

Đọc data-actiondata-cdata ngay trên thẻ chứa widget.


Cây quyết định khi token bị từ chối

Đi từ trên xuống, dừng ở nhánh đầu tiên trả lời "không".

Token solved but rejected
    ↓
Used within 5 minutes? → No → Solve again, submit immediately
    ↓ Yes
Correct sitekey? → No → Find the correct sitekey from the page
    ↓ Yes
Using cf-turnstile-response field? → No → Change field name
    ↓ Yes  
Same session for page load + submit? → No → Use session persistence
    ↓ Yes
Token used only once? → No → Solve a new token per submission
    ↓ Yes
Site requires action/cData? → Check page source, add to API call

Ví dụ: team QA thuê ngoài tại TP.HCM

Một team QA outsourcing chạy regression ban đêm trên staging có Turnstile. Chạy tay thì qua, chạy trên CI thì hỏng khoảng một nửa số lần.

Lý do là thứ tự bước trong runner: hàm giải chạy sớm, còn submit đợi job seed database 4–6 phút. Đưa nó xuống sát submit là hết lỗi.

  • Ghi mốc nhận token và mốc gửi request — chênh lệch là số liệu chính.
  • Log độ dài token thay vì cả chuỗi, theo tinh thần Nghị định 13/2023/NĐ-CP.
  • Cần mốc so sánh thì chạy lại luồng giải Turnstile qua API.

Câu hỏi thường gặp

Token Turnstile sống được bao lâu?

Thường 300 giây (5 phút), có trang đặt ngắn hơn. Gửi ngay trong vài giây sau khi nhận.

Giải token mới cho mỗi lần thử có tốn thêm tiền không?

Không. CaptchaAI tính theo thread chứ không theo lượt giải: gói BASIC ($15/tháng, 5 thread) có số lượt giải không giới hạn trong tháng.

Có nên cache token Turnstile không?

Không nên. Token dùng một lần và hết hạn nhanh, cache chỉ sinh lỗi khó tái hiện.

Trang chuyển sang hCaptcha thì sao?

CaptchaAI không hỗ trợ hCaptcha và FunCaptcha (Arkose Labs); GeeTest v4 mới sắp ra mắt. Các loại dùng được: reCAPTCHA v2/v3, Turnstile, Cloudflare Challenge, GeeTest v3, image/OCR, grid, BLS.

Lỗi nằm ở token hay ở phần còn lại của request?

Gửi đúng request đó với token lấy tay từ trình duyệt. Vẫn 403 là do header hoặc cookie; qua được thì xem token hết hạn trước khi gửi.


Giải Turnstile bằng CaptchaAI

Lấy API key tại captchaai.com, gửi task turnstile tới in.php và dùng token ngay.


Bài viết liên quan

Os comentários estão desativados para este artigo.