Explainers

Cookie qa_validation_cookie в Cloudflare Challenge: как получить и переиспользовать

Cookie qa_validation_cookie появляется в браузере сразу после того, как пройдена промежуточная проверка Cloudflare Challenge — и без него каждый следующий запрос к защищённой странице снова упрётся в тот же интерстициал. В этом руководстве разбираем, как устроена сама проверка, от чего зависит срок жизни cookie и как получать его автоматически через API CaptchaAI в QA-сценариях и пайплайнах автоматизации.


Как срабатывает проверка Cloudflare Challenge

  1. Браузер запрашивает страницу, защищённую Cloudflare.
  2. Cloudflare оценивает сигналы риска: репутацию IP-адреса, заголовки запроса, параметры TLS-подключения.
  3. Если сигналы вызывают подозрение, Cloudflare отвечает кодом 403 или 503 и отдаёт страницу с JavaScript-проверкой.
  4. На этой странице выполняется проверка браузера, а в части случаев дополнительно показывается виджет Cloudflare Turnstile.
  5. После успешного прохождения Cloudflare выставляет cookie qa_validation_cookie и перенаправляет обратно на исходный URL.
  6. Все последующие запросы с этим cookie проходят без повторной проверки — до истечения срока его действия.

Три уровня сложности Cloudflare Challenge

Cloudflare выбирает один из трёх сценариев в зависимости от оценки риска, и от выбранного уровня зависит, придётся ли решать видимую задачу или проверка пройдёт фоном.

JS Challenge (503)

Самый лёгкий уровень: браузеру достаточно выполнить JavaScript, взаимодействие пользователя не требуется. Проверка занимает одну-две секунды и не показывает никакого виджета.

Managed Challenge (403)

Cloudflare сам решает, что показать: иногда — виджет Turnstile, иногда пропускает запрос молча после фоновой оценки риска. Заранее предсказать поведение нельзя.

Interactive Challenge (403)

Самый строгий уровень: виджет Cloudflare Turnstile отображается всегда, и без его решения запрос дальше не пройдёт.

CaptchaAI решает все три уровня через один и тот же решатель Cloudflare Challenge — определять тип вручную не нужно, достаточно отправить задачу с методом turnstile.


Ключевые свойства cookie qa_validation_cookie:

  • Имяqa_validation_cookie
  • Домен — домен целевого сайта (например, .example.com)
  • Путь/
  • Срок жизни — обычно от 30 минут до 24 часов
  • HttpOnly — да
  • Secure — да (только HTTPS)
  • SameSite — None

Cookie привязан сразу к нескольким параметрам сессии, и это критично для автоматизации:

  • IP-адрес — запрос с cookie, полученным на другом IP, обычно отклоняется.
  • User-Agent — строка агента при последующих запросах должна совпадать с той, что использовалась при решении задачи.
  • TLS-отпечаток соединения — в части конфигураций Cloudflare дополнительно сверяет параметры TLS ClientHello.

Практический пример. Команда, которая гоняет QA-тесты staging-окружения из дата-центра во Франкфурте или Алматы, часто получает qa_validation_cookie через один прокси, а следующий запрос отправляет уже с другого выходного IP — и проверка проваливается снова, хотя cookie формально ещё не истёк. Правило простое: прокси, через который решалась задача, и прокси, с которого идут последующие запросы в рамках одной сессии, должны совпадать. Если вы логируете cookie или сопутствующие данные сессии для отладки пайплайна, храните только то, что действительно нужно для теста, — это касается и требований 152-ФЗ для российских проектов, и GDPR-подхода для трансграничных команд.


Как CaptchaAI решает Cloudflare Challenge

Ниже — минимальный рабочий пример отправки задачи и опроса результата на Python и JavaScript. Метод тот же, что и для Cloudflare Turnstile: turnstile, эндпоинты in.php и res.php.

Python

import requests
import time

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/protected-page"

# Submit страница Cloudflare-защиты в staging task
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile",
    "sitekey": "0x0000000000000000000000",  # may be generic for CF challenge
    "pageurl": TARGET_URL,
    "json": "1",
}).json()

if resp["status"] != 1:
    raise Exception(f"Submit error: {resp['request']}")

task_id = resp["request"]
print(f"Task ID: {task_id}")

# Poll for result
for _ in range(30):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY, "action": "get", "id": task_id, "json": "1"
    }).json()

    if result["status"] == 1:
        token = result["request"]
        print(f"Token received: {token[:50]}...")
        break
    if result["request"] != "CAPCHA_NOT_READY":
        raise Exception(f"Error: {result['request']}")

JavaScript

const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const TARGET_URL = 'https://example.com/protected-page';

const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: {
    key: API_KEY,
    method: 'turnstile',
    sitekey: '0x0000000000000000000000',
    pageurl: TARGET_URL,
    json: 1,
  }
});
const taskId = submit.data.request;

// Poll
let token = null;
for (let i = 0; i < 30; i++) {
  await new Promise(r => setTimeout(r, 5000));
  const poll = await axios.get('https://ocr.captchaai.com/res.php', {
    params: { key: API_KEY, action: 'get', id: taskId, json: 1 }
  });
  if (poll.data.status === 1) {
    token = poll.data.request;
    break;
  }
}
console.log(`Token: ${token.substring(0, 50)}...`);

Как применить решённый токен

Полученный токен нужно подставить в поле формы на странице проверки, чтобы Cloudflare выдал qa_validation_cookie:

# With Selenium
from selenium import webdriver

driver = webdriver.Chrome()
driver.get(TARGET_URL)  # Load the challenge page

# Inject token into Turnstile response field
driver.execute_script("""
    const input = document.querySelector('input[name="cf-turnstile-response"]');
    if (input) input.value = arguments[0];

    // Trigger form submit or callback
    const form = document.querySelector('form');
    if (form) form.submit();
""", token)

# Wait for redirect and extract cookies
import time
time.sleep(3)
cookies = driver.get_cookies()
qa_validation_cookie = next(
    (c for c in cookies if c['name'] == 'qa_validation_cookie'), None
)
if qa_validation_cookie:
    print(f"qa_validation_cookie: {qa_validation_cookie['value'][:30]}...")

Дальше cookie можно передать в обычную HTTP-сессию и обращаться к защищённым эндпоинтам напрямую, без браузера:

session = requests.Session()
session.cookies.set("qa_validation_cookie", qa_validation_cookie["value"], domain=".example.com")
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})

# Now access protected pages
resp = session.get("https://example.com/api/data")
print(resp.status_code)  # 200

Cookie рано или поздно истекает, и пайплайн должен решать задачу заново до этого момента, а не после первого же отказа:

import datetime

def is_cookie_valid(cookie):
    if not cookie:
        return False
    expiry = cookie.get("expiry", 0)
    return datetime.datetime.now().timestamp() < expiry - 60  # 60s buffer

def get_or_refresh_clearance(driver, target_url, solve_func):
    cookies = driver.get_cookies()
    cf = next((c for c in cookies if c["name"] == "qa_validation_cookie"), None)
    if is_cookie_valid(cf):
        return cf["value"]

    # Re-solve
    token = solve_func(target_url)
    # ... inject and extract new cookie

Типичные проблемы и как их решить

Причина — несовпадение IP-адресов. Используйте один и тот же прокси для решения задачи и для последующих запросов в рамках сессии.

Причина — сайт выставил короткий TTL. Решайте задачу заново заранее и проверяйте поле expiry перед каждым запросом, а не после первого отказа.

Причина — User-Agent не совпадает между сессиями. Сверьте строку User-Agent, использованную при решении задачи, с той, что уходит в последующих запросах.

Страница проверки не загружается

Причина — отключён JavaScript. Используйте полноценный браузер (Selenium, Puppeteer) вместо простого HTTP-клиента, который JavaScript не выполняет.


Часто задаваемые вопросы

Только если у машин совпадает исходящий IP-адрес и одинаковая строка User-Agent. Cloudflare привязывает cookie к параметрам того запроса, на котором проверка была пройдена, поэтому «расшарить» его между разными окружениями почти никогда не получается.

Обычно от 30 минут до 24 часов — конкретное значение задаёт владелец сайта в настройках Cloudflare. Полагаться на фиксированное число не стоит: проверяйте поле expiry в самом cookie и решайте задачу заново заблаговременно.

Нужен ли прокси при повторном решении Cloudflare Challenge?

Не обязательно, но если запросы к защищённой странице и так идут через прокси (например, чтобы имитировать региональный трафик), решать задачу нужно через тот же самый прокси — иначе IP-адрес, к которому привязан cookie, не совпадёт с IP последующих запросов.

Как понять, с каким уровнем Challenge я столкнулся?

По коду ответа и наличию виджета: 503 без взаимодействия — это JS Challenge, 403 с видимым Turnstile — Interactive Challenge, а 403 без видимого виджета обычно означает, что сработал Managed Challenge и Cloudflare пропустил запрос молча либо потребовал решение фоново.

Сама отправка задачи и получение токена через API CaptchaAI не требует браузера. А вот подстановка токена в форму и извлечение итогового cookie обычно всё же выполняются через Selenium или Puppeteer, потому что финальный редирект и установка cookie происходят на стороне страницы.


Решайте страницы Cloudflare Challenge через CaptchaAI

Получите API-ключ на captchaai.com и подключите решатель Cloudflare Challenge к своему QA-пайплайну за несколько минут.


Связанные руководства

Комментарии для этой статьи отключены.