Устранение неполадок

Срок действия токена Cloudflare Turnstile Cloudflare и условия гонки

Токен Cloudflare Turnstile, который работает при тестировании, терпит неудачу в производстве. Причина: истечение срока действия токена. токены Cloudflare Turnstile имеют ограниченный срок действия, и если ваш рабочий процесс занимает слишком много времени между получением токена и его отправкой, сайт отклоняет его. Вот как правильно обращаться с таймингом.

Срок действия токена

Срок действия токенов Cloudflare Turnstile истекает примерно через 300 секунд (5 минут) после создания. Это больше, чем ~120 секунд в reCAPTCHA, но в сложных рабочих процессах все равно возникают условия гонки.

Тип капчи Срок действия токена
reCAPTCHA v2/v3 ~120 секунд
Cloudflare Turnstile ~300 секунд
hCaptcha ~120 секунд

Таймер запускается, когда Cloudflare генерирует токен, а не тогда, когда CaptchaAI возвращает его вам, и не тогда, когда вы получаете его в своем коде.

Состояние гонки

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

Часы отсчитывают время 0:20. У вас есть время примерно до 5:20, чтобы отправить токен. Звучит щедро, но подумайте, что происходит в реальном рабочем процессе:

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

Распространенные сценарии гонок

1. Многошаговые формы

Формы, требующие несколько страниц перед окончательной отправкой:

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

Если CAPTCHA находится на шаге 3, а отправка происходит на шаге 5, задержка между решением и отправкой может превышать 5 минут.

2. Очереди пакетной обработки

предварительная QA-проверка токенов и их использование позже:

# 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. Циклы повторов со старыми токенами

Повторное использование токена после неудачной отправки:

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

Предотвращение истечения срока действия

Стратегия 1. Решение проблем «точно в срок»

Запрашивайте токен только тогда, когда вы готовы его отправить:

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

Стратегия 2: Отслеживание возраста токена

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)

Стратегия 3: Свежий токен при повторной попытке (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');
}

Обнаружение токенов с истекшим сроком действия

Сайт обычно не сообщает вам явно о том, что срок действия токена истек. Ищите эти сигналы:

Сигнал Индикация
HTTP 403 после отправки токена Токен недействителен или срок его действия истек.
Перенаправление обратно на страницу формы Проверка токена не удалась
Сообщение об ошибке: «Проверка не удалась». Общий сбой — возможно, истек срок действия
Страница испытания появляется снова Токен отклонен, Cloudflare повторно бросает вызов

Регистрация для диагностики

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)")

Поведение автоматического обновления Cloudflare Turnstile

В потоках на основе браузера виджеты Turnstile автоматически обновляют токены до истечения срока их действия. data-expired-callback срабатывает, когда истекает срок действия токена:

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

При автоматизации только с помощью API (без браузера) автоматическое обновление не дает преимуществ. Вы должны сами управлять свежестью токенов.

Поиск неисправностей

| Проблема | Причина | Исправить |


Следующие шаги

  • CaptchaAI Quickstart: ваше первое решение CAPTCHA за 5 минут
  • Как решить reCAPTCHA v2 через API: пошаговое руководство
  • Как решить Cloudflare Turnstile через API
  • Как решить GeeTest v3 с помощью API
Комментарии для этой статьи отключены.