Khắc Phục Sự Cố

Thời gian hết hạn mã thông báo quay vòng của Cloudflare và điều kiện cuộc đua

Mã thông báo Turnstile hoạt động trong quá trình thử nghiệm không thành công trong quá trình sản xuất. Nguyên nhân: hết hạn token. Mã thông báo quay vòng có thời gian tồn tại giới hạn và nếu quy trình làm việc của bạn mất quá nhiều thời gian từ lúc nhận mã thông báo đến khi gửi mã thông báo thì trang web sẽ từ chối mã thông báo đó. Đây là cách xử lý thời gian một cách chính xác.

Tuổi thọ của mã thông báo

Mã thông báo quay vòng hết hạn khoảng 300 giây (5 phút) sau khi tạo. Con số này cao hơn ~120 giây của reCAPTCHA, nhưng điều kiện chạy đua vẫn phát sinh trong quy trình làm việc phức tạp.

loại CAPTCHA Tuổi thọ của mã thông báo
reCAPTCHA v2/v3 ~120 giây
Cloudflare Turnstile *300 giây
hCaptcha ~120 giây

Đồng hồ tính giờ bắt đầu khi Cloudflare tạo mã thông báo - không phải khi CaptchaAI trả lại mã thông báo đó cho bạn và không phải khi bạn nhận được mã thông báo đó trong mã của mình.

Điều kiện cuộc đua

Time 0:00  — You submit a Turnstile task to CaptchaAI
Time 0:15  — CaptchaAI begins solving
Time 0:20  — Token is generated (timer starts here)
Time 0:25  — CaptchaAI returns token to you
Time 0:25+ — Your code processes the token
Time ???   — Your code submits the token to the site

Đồng hồ đang điểm từ lúc 0:20. Bạn có thời gian đến khoảng 5:20 để gửi mã thông báo. Điều đó nghe có vẻ hào phóng nhưng hãy xem xét điều gì xảy ra trong quy trình làm việc thực tế:

Time 0:20  — Token generated
Time 0:25  — Received by your code
Time 0:30  — Fill form fields
Time 0:35  — Navigate to next page
Time 1:00  — Handle additional dialogs
Time 2:00  — Wait for page load
Time 4:00  — Network latency spike
Time 5:30  — Submit token → EXPIRED

Các kịch bản tình trạng cuộc đua phổ biến

1. Biểu mẫu nhiều bước

Các biểu mẫu yêu cầu nhiều trang trước khi gửi lần cuối:

Step 1: Fill personal info → Step 2: Fill address → 
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit

Nếu CAPTCHA ở Bước 3 nhưng việc gửi diễn ra ở Bước 5 thì độ trễ giữa việc giải và gửi có thể vượt quá 5 phút.

2. Hàng đợi xử lý hàng loạt

Giải quyết các mã thông báo trước và sử dụng chúng sau:

# DON'T: Solve all tokens first, then use them
tokens = []
for url in urls:
    tokens.append(solve_turnstile(url))  # Tokens age while waiting

for url, token in zip(urls, tokens):
    submit_form(url, token)  # Early tokens may be expired

3. Thử lại vòng lặp với mã thông báo cũ

Sử dụng lại mã thông báo sau khi gửi không thành công:

token = solve_turnstile(site_key, page_url)

for attempt in range(3):
    result = submit_form(page_url, token)
    if result.ok:
        break
    # BUG: Retrying with the same token — it may be expired OR already consumed

Ngăn chặn hết hạn

Chiến lược 1: Giải quyết đúng lúc

Chỉ yêu cầu mã thông báo khi bạn sẵn sàng gửi:

import requests
import time

def solve_turnstile(site_key, page_url):
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": "YOUR_API_KEY",
        "method": "turnstile",
        "sitekey": site_key,
        "pageurl": page_url,
        "json": 1
    })
    task_id = resp.json()["request"]

    for _ in range(60):
        time.sleep(3)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": "YOUR_API_KEY",
            "action": "get",
            "id": task_id,
            "json": 1
        })
        data = result.json()
        if data["status"] == 1:
            return data["request"]
    raise TimeoutError("Solve timed out")

# Complete all form steps FIRST
fill_personal_info()
fill_address()
navigate_to_review()

# THEN solve and submit immediately
token = solve_turnstile(site_key, page_url)
submit_form(token)  # Submit within seconds of receiving the token

Chiến lược 2: Theo dõi tuổi token

import time

class TimedToken:
    def __init__(self, token, created_at=None):
        self.token = token
        self.created_at = created_at or time.time()
        self.max_age = 270  # 4.5 min — safety margin from 5 min limit

    @property
    def is_valid(self):
        return (time.time() - self.created_at) < self.max_age

    @property
    def remaining_seconds(self):
        return max(0, self.max_age - (time.time() - self.created_at))

# Usage
timed_token = TimedToken(solve_turnstile(site_key, page_url))

# Check before using
if timed_token.is_valid:
    submit_form(timed_token.token)
else:
    # Solve a fresh token
    timed_token = TimedToken(solve_turnstile(site_key, page_url))
    submit_form(timed_token.token)

Chiến lược 3: Mã thông báo mới khi thử lại (JavaScript)

async function submitWithFreshToken(siteKey, pageUrl, formData) {
  const maxRetries = 3;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    // Always solve a fresh token for each attempt
    const token = await solveTurnstile(siteKey, pageUrl);

    const response = await fetch(pageUrl, {
      method: 'POST',
      body: JSON.stringify({ ...formData, 'cf-turnstile-response': token }),
      headers: { 'Content-Type': 'application/json' }
    });

    if (response.ok) return await response.json();

    console.log(`Attempt ${attempt + 1} failed, solving fresh token...`);
  }

  throw new Error('All attempts failed');
}

Phát hiện mã thông báo đã hết hạn

Trang web thường không cho bạn biết rõ ràng "mã thông báo đã hết hạn". Hãy tìm những tín hiệu sau:

tín hiệu chỉ định
HTTP 403 sau khi gửi mã thông báo Mã thông báo không hợp lệ hoặc đã hết hạn
Chuyển hướng trở lại trang biểu mẫu Xác minh mã thông báo không thành công
Thông báo lỗi: "xác minh không thành công" Lỗi chung - có thể hết hạn
Trang thử thách xuất hiện lại Mã thông báo bị từ chối, Cloudflare thử thách lại

Ghi nhật ký để chẩn đoán

import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("turnstile")

token_received_at = time.time()
token = solve_turnstile(site_key, page_url)
logger.info(f"Token received, length: {len(token)}")

# ... workflow steps ...

submit_time = time.time()
age = submit_time - token_received_at
logger.info(f"Submitting token, age: {age:.1f}s")

if age > 270:
    logger.warning(f"Token may be expired (age: {age:.1f}s > 270s safety limit)")

Hành vi tự động làm mới của Turnstile

Trong các luồng dựa trên trình duyệt, tiện ích Turnstile tự động làm mới mã thông báo trước khi chúng hết hạn. data-expired-callback kích hoạt khi mã thông báo hết hạn:

turnstile.render('#captcha', {
  sitekey: '0x4AAAA...',
  callback: (token) => {
    console.log('New token:', token);
  },
  'expired-callback': () => {
    console.log('Token expired — widget will auto-refresh');
  }
});

Trong tự động hóa chỉ API (không có trình duyệt), bạn không được hưởng lợi từ tính năng tự động làm mới. Bạn phải tự mình quản lý việc làm mới mã thông báo.

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Mã thông báo hoạt động trong thử nghiệm nhưng không hoạt động trong sản xuất Quy trình sản xuất chậm hơn Giải quyết kịp thời, không cần giải quyết trước
Lần gửi đầu tiên thành công, lần thử lại không thành công Tái sử dụng mã thông báo đã tiêu thụ Giải quyết một mã thông báo mới cho mỗi lần thử
Thất bại liên tục trên các biểu mẫu dài Mã thông báo hết hạn trong quy trình nhiều bước Chuyển việc giải CAPTCHA sang bước cuối cùng
Công việc hàng loạt có tỷ lệ thất bại cao Mã thông báo được giải quyết hàng loạt sẽ hết hạn trước khi sử dụng Giải quyết mã thông báo theo yêu cầu, không phải theo đợt

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

Tôi có thể kéo dài thời gian tồn tại của mã thông báo Turnstile không?

Không. Thời hạn hết hạn do Cloudflare đặt ra và không thể sửa đổi. Lựa chọn duy nhất của bạn là giải quyết một mã thông báo mới.

Giới hạn 300 giây chính xác đến mức nào?

Nó gần đúng. Cloudflare có thể điều chỉnh thời gian dựa trên cấu hình. Sử dụng 270 giây (4,5 phút) làm mức tối đa thực tế của bạn để có giới hạn an toàn.

Tôi có nên giải token sớm để tiết kiệm thời gian không?

Chỉ khi quy trình kiểm thử của bạn có thể tiêu thụ token trong vòng vài phút. Đối với batch QA, hãy giải token theo yêu cầu (just-in-time) thay vì lưu sẵn để tránh hết hạn.

bài viết liên quan

Các bước tiếp theo

Ngăn chặn hết hạn mã thông báo Turnstile —lấy khóa API CaptchaAI của bạnvà thực hiện giải quyết kịp thời với tỷ lệ thành công 100%.

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