Troubleshooting

Снижение успешности решения CAPTCHA: блок-схема диагностики

Показатель решения CAPTCHA просел? Обычно дело в одной из четырёх причин: устаревший sitekey, просроченный токен, несовпадение домена в pageurl или сайт сменил тип CAPTCHA. Три шага ниже находят причину без гадания.


Схема диагностики: откуда начинать поиск

Читайте дерево сверху вниз: сначала проверяете сам факт генерации токена, затем — почему сайт его отклонил на своей стороне. Каждая ветка указывает на конкретный шаг диагностики ниже.

Success rate dropped
│
├── Are tokens being generated?
│   ├── NO → Check API errors
│   │   ├── ERROR_WRONG_GOOGLEKEY → Sitekey changed. Re-extract.
│   │   ├── ERROR_BAD_PARAMETERS → Check required params
│   │   ├── ERROR_NO_SLOT → Retry with backoff
│   │   └── Other errors → See error decision tree
│   │
│   └── YES → Tokens generated but rejected by target site
│       │
│       ├── Token expired before use?
│       │   └── YES → Submit token faster (< 60-120s)
│       │
│       ├── Token used for wrong domain?
│       │   └── YES → Check pageurl matches submission domain
│       │
│       ├── reCAPTCHA v3 score too low?
│       │   └── YES → Check action parameter, attach cookies/UA/proxy
│       │
│       ├── Site changed CAPTCHA type?
│       │   └── YES → Re-detect CAPTCHA type
│       │
│       └── Site added additional checks?
│           └── YES → Check for сигналы браузераing, cookies, headers

Шаг 1: измерьте текущий показатель успешных решений

Без базовой линии вы будете гадать. Трекер на Python считает попытки, успехи и коды ошибок по каждому методу:

import requests
import time
from collections import defaultdict

class SuccessTracker:
    """Track solve success rates over time."""

    def __init__(self):
        self.stats = defaultdict(lambda: {"attempts": 0, "success": 0, "errors": defaultdict(int)})

    def record(self, method, success, error_code=None):
        self.stats[method]["attempts"] += 1
        if success:
            self.stats[method]["success"] += 1
        elif error_code:
            self.stats[method]["errors"][error_code] += 1

    def report(self):
        for method, data in self.stats.items():
            rate = data["success"] / data["attempts"] * 100 if data["attempts"] > 0 else 0
            print(f"\n{method}:")
            print(f"  Attempts: {data['attempts']}")
            print(f"  Success: {data['success']} ({rate:.1f}%)")
            if data["errors"]:
                print("  Errors:")
                for err, count in sorted(data["errors"].items(), key=lambda x: -x[1]):
                    print(f"    {err}: {count}")

tracker = SuccessTracker()

Шаг 2: определите категорию сбоя

Причины делятся на две категории: сбой API (токен не получен) и отклонение токена сайтом.

Категория A: ошибка на уровне API CaptchaAI

API возвращает код ошибки вместо токена. Прогоните тестовые решения и соберите статистику по кодам — обычно доминирует один:

def diagnose_api_failures(api_key, method, params, attempts=10):
    """Run test solves and collect error patterns."""
    errors = defaultdict(int)
    successes = 0

    for i in range(attempts):
        try:
            resp = requests.post("https://ocr.captchaai.com/in.php", data={
                "key": api_key, "method": method, "json": 1, **params,
            }, timeout=30)
            result = resp.json()

            if result.get("status") != 1:
                errors[result.get("request", "UNKNOWN")] += 1
                continue

            task_id = result["request"]
            # Quick poll
            time.sleep(15)
            resp = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": api_key, "action": "get",
                "id": task_id, "json": 1,
            }, timeout=15)
            data = resp.json()

            if data.get("status") == 1:
                successes += 1
            else:
                errors[data.get("request", "POLL_ERROR")] += 1

        except Exception as e:
            errors[f"EXCEPTION:{type(e).__name__}"] += 1

        time.sleep(2)

    print(f"\nResults: {successes}/{attempts} success")
    for err, count in sorted(errors.items(), key=lambda x: -x[1]):
        print(f"  {err}: {count}")

Если в выборке из 10–20 тестовых решений один код ошибки повторяется чаще остальных, чините сначала его — точечное исправление обычно закрывает большую часть отказов.

Категория B: сайт отклоняет валидный токен

CaptchaAI вернул токен, но целевой сайт его не принял:

Причина Что проверить
Срок токена истёк Использован позже 120 секунд после генерации
Несовпадение домена pageurl ≠ домен отправки формы
Низкий score v3 Сайт требует 0,7+, решатель отдаёт 0,3
Не передан action Action не совпадает с тем, что у сайта
Параметры сайта изменились Sitekey или структура страницы обновились

Пример: команда переключает staging-домен QA-теста чек-аута с test.example.com на staging.example.com и получает волну отказов — pageurl больше не совпадает с доменом формы. Домен стоит проверять первым после деплоя.


Шаг 3: устраните конкретную причину

Токен истекает раньше, чем вы успеваете его использовать

Не храните токен — используйте сразу после получения, опрашивая res.php агрессивно:

def solve_and_use_immediately(api_key, sitekey, pageurl):
    """Solve and use token as fast as possible."""
    # Submit
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": api_key,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1,
    }, timeout=30)
    task_id = resp.json()["request"]

    # Poll aggressively
    for _ in range(24):
        time.sleep(5)
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key, "action": "get",
            "id": task_id, "json": 1,
        }, timeout=15)
        data = resp.json()
        if data.get("status") == 1:
            token = data["request"]
            # USE IMMEDIATELY — don't store for later
            submit_form(token)
            return True

    return False

Sitekey устарел или страница изменилась

Если сайт периодически перевыпускает sitekey, извлекайте его заново перед каждым решением:

def solve_with_fresh_params(api_key, pageurl):
    """Re-extract sitekey before each solve."""
    import re

    resp = requests.get(pageurl, timeout=15)
    match = re.search(r'data-sitekey="([^"]+)"', resp.text)
    if not match:
        raise RuntimeError("Could not find sitekey")

    sitekey = match.group(1)
    # Now solve with fresh sitekey
    # ...

Параметр action не совпадает для reCAPTCHA v3

v3 привязывает score к action. Если вы отправляете submit, а страница ждёт login, доверие занижается. Сверьте значение в коде страницы:

# Check what action the site uses
# Look for: grecaptcha.execute('sitekey', {action: 'submit'})

data = {
    "key": api_key,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": pageurl,
    "version": "v3",
    "action": "submit",  # Must match site's action
    "json": 1,
}

Решение не сработало на сайте — сообщите через reportbad: CaptchaAI использует отчёты, чтобы дообучать решатель.

Сайт добавил проверку поведения, а не сменил тип CAPTCHA

Если токен пришёл вовремя, домен и action совпадают, а форма всё равно возвращает отказ — не в API CaptchaAI, а именно на сайте, — причина обычно не в самом CAPTCHA-виджете. Целевой сайт мог включить дополнительную проверку поверх него: анализ куки сессии, заголовков запроса или последовательности действий перед отправкой формы. Начните с полного воспроизведения пути пользователя — открытие страницы, естественная задержка перед сабмитом, реалистичные заголовки запроса — вместо прямого POST с готовым токеном. Совпадение отказов по времени с релизом на стороне сайта подтверждает: дело не в решателе, а в изменении проверки на стороне сайта.


Нормальные показатели по типам CAPTCHA

Точный процент CaptchaAI не публикует — только ориентир «высокий». Скорость нормирована точнее:

Тип CAPTCHA Скорость решения Успех
reCAPTCHA v2 <60 с Высокий
reCAPTCHA v3 <4 с Высокий
Cloudflare Turnstile <10 с Высокий
GeeTest v3 <12 с Высокий
BLS <1 с Высокий
Изображение/OCR <0,5 с Высокий

Порог тревоги — не абсолютный процент, а просадка от вашей базовой линии из шага 1: 5–10 пунктов от привычного значения — повод перейти к шагу 2. Сравнивайте показатель в рамках одного типа CAPTCHA: reCAPTCHA v2 и Turnstile решаются по-разному, и прямое сравнение их долей между собой не покажет ничего полезного.


Частые причины и быстрые исправления

Симптом Причина Что сделать
Показатель упал с 98% до 70% за день Изменился sitekey или страница Извлечь параметры заново
Все токены v3 отклонены Неверный action Сверить action со страницей
Токены не успевают примениться Медленная передача в форму Отправлять в течение 60 секунд
Показатель «плавает» по времени суток Rate limiting у сайта Добавить задержки между отправками

Вопросы, которые чаще всего задают

Почему показатель успеха мог упасть без изменений в коде?

Причина обычно внешняя: сайт обновил sitekey, изменил action v3 или добавил проверку — куки, заголовки, поведенческие сигналы.

Как понять, ошибка на стороне API или токен отклонён сайтом?

Код ошибки вместо токена — Категория A. Токен получен (status: 1), но не принят — Категория B: домен, срок или action.

Какой показатель успеха считается нормальным для CaptchaAI?

Точного процента CaptchaAI не публикует — только ориентир «высокий». Смотрите на свою базовую линию: отклонение на 5–10 пунктов — повод для диагностики.

Сколько времени есть на использование токена, прежде чем он истечёт?

Токены reCAPTCHA живут около 120 секунд, Turnstile — около 300. Передавайте токен в форму в течение 60 секунд.

Что делать, если сайт добавил проверку поведения, а не сменил CAPTCHA?

Если отказы совпали по времени с изменением на сайте — воспроизведите полный путь пользователя (куки, заголовки запроса, естественная задержка перед отправкой) и повторите тестовую выборку из шага 1, прежде чем менять параметры запроса к API.


Похожие материалы


Найдите причину быстрее, чем истечёт следующий токен — подключите CaptchaAI.

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