API Tutorials

Пользовательские типы CAPTCHA: отправка необычных задач в CaptchaAI

Любую нестандартную CAPTCHA — слайдер, поворот изображения, пазл или самописный виджет — в CaptchaAI решают одним универсальным приёмом: вы делаете скриншот задачи и отправляете его в метод image/OCR вместе с короткой текстовой инструкцией, что именно нужно сделать с картинкой. Отдельного эндпоинта «для слайдеров» или «для поворота» не существует, и это скорее плюс: вся гибкость сосредоточена в том, как вы формулируете инструкцию и как разбираете ответ на своей стороне.

Такой путь нужен, когда на странице стоит не типовая reCAPTCHA и не обычная текстовая картинка, а что-то самодельное: перетаскивание ползунка, выбор элементов в правильном порядке, аудиозадача. Ниже — рабочий каркас на Python: одна функция отправки и несколько адаптеров под конкретные виды задач. Токены и эндпоинты (in.php, res.php) остаются стандартными, меняются только инструкция и постобработка ответа на вашей стороне.


Что считать «пользовательской» CAPTCHA

Прежде чем писать код, определитесь с видом задачи. Стандартные типы (reCAPTCHA v2/v3, Cloudflare Turnstile) решаются профильными методами; всё остальное разумно свести к паре «скриншот + инструкция».

Тип задачи Что видит пользователь Как решать через CaptchaAI
Слайдер (slider) Перетащить ползунок в нужную точку Скриншот + инструкция вернуть смещение по X
Пазл (jigsaw) Вставить фрагмент на место Логика, близкая к GeeTest v3
Аудио-CAPTCHA Прослушать и набрать символы Отправить аудио как base64
Поворот изображения Довернуть картинку до верной ориентации Скриншот + инструкция вернуть градусы
Порядок кликов Нажать элементы в нужной последовательности Подход как для сетки изображений
Арифметика Решить пример Параметр calc=1
Интерактивный виджет JS-виджет под конкретный сайт Скриншот + текстовая инструкция

Главная развилка простая: если задачу можно понять по одному изображению, её решает метод image/OCR. Если для ответа нужно взаимодействие в браузере (перетащить, кликнуть, довернуть), CaptchaAI возвращает вам число или строку, а само действие вы выполняете через Selenium или Playwright.


Универсальный приём: скриншот плюс текстовая инструкция

Базовая функция отправляет base64-скриншот в метод image/OCR и опрашивает res.php до готовности ответа. Именно её вызывают все адаптеры ниже.

import requests
import base64
import time
import os

API_KEY = os.environ["CAPTCHAAI_API_KEY"]


def solve_custom_captcha(image_b64, instructions):
    """Solve any visual CAPTCHA using image + text instructions."""
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "textinstructions": instructions,
        "json": 1,
    }, timeout=30)

    result = resp.json()
    if result.get("status") != 1:
        raise RuntimeError(result.get("request"))

    task_id = result["request"]

    time.sleep(10)
    for _ in range(30):
        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:
            return data["request"]
        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(5)

    raise TimeoutError("Solve timeout")

Ключевой параметр здесь — textinstructions. От его формулировки напрямую зависит, получите ли вы пригодный ответ. Просите ровно то значение, которое сможете использовать в коде: «верните только число», «верните координату X», «верните строку через запятую». Расплывчатое «решите капчу» приведёт к тому, что решатель вернёт описание, а не значение. Опрос устроен щадяще: первые 10 секунд ожидания плюс до 30 попыток с шагом 5 секунд дают запас под задачи, которые считаются дольше типовых. Пока приходит CAPCHA_NOT_READY, цикл продолжается; любой другой текст — это код ошибки, и его стоит залогировать.


Слайдер: получаем смещение по X

Слайдер просит перетащить ползунок в нужную позицию. CaptchaAI вычисляет смещение по картинке, а перетаскивание вы выполняете сами через ActionChains.

# slider_captcha.py
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains


def solve_slider_captcha(driver, captcha_selector):
    """Screenshot slider CAPTCHA and solve via CaptchaAI."""
    captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
    image_b64 = captcha.screenshot_as_base64

    result = solve_custom_captcha(
        image_b64,
        "What pixel position should the slider be dragged to? "
        "Return only the X offset number."
    )

    try:
        offset = int(result)
    except ValueError:
        return False

    # Drag slider to position
    slider = driver.find_element(By.CSS_SELECTOR, ".slider-handle")
    ActionChains(driver).click_and_hold(slider).move_by_offset(offset, 0).release().perform()

    return True

Обратите внимание на разделение труда: сервис отвечает за распознавание («на сколько пикселей сдвинуть»), а траекторию и скорость перетаскивания задаёте вы. Селекторы .slider-handle — заглушки; подставьте реальные для своего сайта.


Поворот: доводим изображение до нужного угла

CAPTCHA с поворотом просит выровнять картинку. Инструкция должна возвращать число градусов по часовой стрелке, а вы переводите его в количество нажатий кнопки.

# rotation_captcha.py


def solve_rotation_captcha(driver, captcha_selector):
    """Solve rotation CAPTCHA."""
    captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
    image_b64 = captcha.screenshot_as_base64

    result = solve_custom_captcha(
        image_b64,
        "How many degrees should this image be rotated clockwise "
        "to be in the correct upright orientation? Return only the number."
    )

    try:
        degrees = int(result)
    except ValueError:
        return False

    # Click rotation button the correct number of times
    rotate_btn = driver.find_element(By.CSS_SELECTOR, ".rotate-button")
    clicks = degrees // 90  # Each click rotates 90 degrees

    for _ in range(clicks):
        rotate_btn.click()
        time.sleep(0.3)

    return True

Здесь важно, чтобы шаг поворота на сайте (90 градусов за клик) совпадал с делителем в коде. Если виджет доворачивает по 45 градусов, поменяйте // 90 на // 45.


Клик в правильном порядке

Задачи «нажмите элементы по порядку» удобно свести к списку индексов. Просите ответ через запятую и кликаете элементы в полученной последовательности.

# order_captcha.py


def solve_order_captcha(driver, captcha_selector, item_selector):
    """Solve click-in-order CAPTCHA."""
    captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
    image_b64 = captcha.screenshot_as_base64

    result = solve_custom_captcha(
        image_b64,
        "What is the correct order? Return as comma-separated "
        "numbers (1-indexed) representing positions left-to-right, top-to-bottom."
    )

    # Parse order
    try:
        order = [int(x.strip()) for x in result.split(",")]
    except ValueError:
        return False

    # Click items in order
    items = driver.find_elements(By.CSS_SELECTOR, item_selector)
    for idx in order:
        if 1 <= idx <= len(items):
            items[idx - 1].click()
            time.sleep(0.5)

    return True

Нумерация в инструкции с единицы (1-indexed), а в Python — с нуля, поэтому в коде стоит items[idx - 1]. Проверка 1 <= idx <= len(items) защищает от выхода за границы, если решатель вернул лишний номер.


Аудио-CAPTCHA как запасной путь

Когда сайт предлагает аудиоальтернативу, её можно скачать и отправить тем же base64-методом с инструкцией на транскрибацию.

# audio_captcha.py
import requests


def solve_audio_captcha(audio_url):
    """Download and solve an audio CAPTCHA."""
    # Download audio
    resp = requests.get(audio_url, timeout=30)
    audio_b64 = base64.b64encode(resp.content).decode("ascii")

    # Submit as image with instructions
    # CaptchaAI may support audio via the base64 method
    result = solve_custom_captcha(
        audio_b64,
        "This is an audio CAPTCHA. Transcribe the spoken characters."
    )
    return result

Аудио — не основной сценарий, и это честно: комментарий в коде так и говорит — метод base64 может принять аудио. Если у задачи есть визуальный вариант, обычно надёжнее решать именно его, а аудио оставить как запасной путь.


Неизвестный виджет: универсальный обработчик

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

# custom_widget.py
from selenium import webdriver
from selenium.webdriver.common.by import By


def handle_custom_widget(driver, widget_selector):
    """Handle an unknown custom CAPTCHA widget."""

    # Step 1: Screenshot the entire widget
    widget = driver.find_element(By.CSS_SELECTOR, widget_selector)
    image_b64 = widget.screenshot_as_base64

    # Step 2: Get any visible instructions
    try:
        instructions_el = widget.find_element(By.CSS_SELECTOR, ".instructions, .prompt, p")
        visible_instructions = instructions_el.text
    except Exception:
        visible_instructions = "Solve this CAPTCHA"

    # Step 3: Submit with descriptive instructions
    result = solve_custom_captcha(
        image_b64,
        f"CAPTCHA instructions: {visible_instructions}. "
        f"Return the answer text."
    )

    # Step 4: Try to submit result
    try:
        input_el = widget.find_element(By.CSS_SELECTOR, "input")
        input_el.clear()
        input_el.send_keys(result)
    except Exception:
        # No input — try clicking based on result
        driver.execute_script("""
            var input = document.querySelector('input[name*="captcha"]');
            if (input) input.value = arguments[0];
        """, result)

    return result

Приём с чтением видимой подсказки (.instructions, .prompt, p) экономит время: вместо того чтобы вручную описывать каждый новый виджет, вы передаёте решателю ту же формулировку, которую видит человек. Если поля ввода нет, фолбэк на execute_script пытается положить ответ в скрытый input.


Сначала определите тип: маршрутизация задач

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

# detector.py
import re


def detect_captcha_type(page_html):
    """Detect which CAPTCHA type is on a page."""
    checks = {
        "recaptcha_v2": r'data-sitekey.*g-recaptcha',
        "recaptcha_v3": r'recaptcha/api\.js\?render=',
        "turnstile": r'cf-turnstile|challenges\.cloudflare\.com/turnstile',
        "geetest": r'gt\b.*challenge|geetest',
        "bls": r'method.*bls|bls-captcha',
        "image_text": r'captcha.*\.(png|jpg|gif|jpeg)',
        "slider": r'slider.*captcha|slide.*verify',
        "audio": r'audio.*captcha|captcha.*audio',
    }

    detected = []
    for captcha_type, pattern in checks.items():
        if re.search(pattern, page_html, re.IGNORECASE):
            detected.append(captcha_type)

    return detected if detected else ["unknown"]

Это эвристика на регулярных выражениях по HTML, а не строгая классификация: она подсказывает вероятный тип, а не гарантирует его. Если функция вернула ["unknown"], разумный дефолт — универсальный обработчик виджета из предыдущего раздела.


Диагностика: что делать при типичных ошибках

Проблема Причина Что сделать
ERROR_CAPTCHA_UNSOLVABLE Картинка нечёткая или инструкция расплывчата Улучшите качество скриншота и уточните инструкцию
Ответ в неверном формате Решатель вернул описание вместо значения Формулируйте жёстко: «верните только число»
Виджет не попал в кадр Элемент вне области просмотра Прокрутите к элементу перед скриншотом
Взаимодействие не срабатывает Неверные координаты клика Аккуратно сопоставьте ответ с реальными элементами UI

Когда это нужно на практике

Типичный сценарий — QA- или дата-команда, которая гоняет автотесты по staging-порталу и внезапно упирается в самописный слайдер, которого нет в стандартном наборе типов. Вместо того чтобы писать распознавание с нуля, задачу сводят к скриншоту и инструкции, а перетаскивание оставляют существующему Selenium-коду. Так же поступают команды в Алматы, Минске или Тбилиси, которым важна предсказуемая стоимость: тарификация CaptchaAI идёт по потокам, а не за каждое решение, поэтому всплеск нестандартных задач не превращается в непредсказуемый счёт.

Отдельно про сбор данных: если вы автоматизируете прохождение CAPTCHA в рамках парсинга, собирайте только те данные, которые вправе обрабатывать. Для аудитории в РФ это ориентир на 152-ФЗ «О персональных данных», для трансграничных проектов — привычная GDPR-осмотрительность. Это не юридический совет, а обычная гигиена: она избавляет от лишних вопросов задолго до продакшена.


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

Как сформулировать текстовую инструкцию, чтобы ответ был пригоден?

Просите ровно то значение, которое используете в коде, и запрещайте лишнее словами вроде «верните только число» или «верните строку через запятую». Чем конкретнее инструкция, тем реже приходит описание вместо готового ответа.

CaptchaAI сам перетаскивает слайдер или это делает мой код?

Сервис возвращает распознанное значение — смещение, угол, порядок. Само действие в браузере (перетаскивание, клик, доворот) выполняет ваш Selenium- или Playwright-код. Такое разделение и делает подход универсальным.

Сколько потоков нужно, если нестандартных CAPTCHA много?

Тариф считается по числу одновременных потоков, решения внутри тарифа не ограничены. Для начала обычно хватает BASIC ($15/мес, 5 потоков); при заметном объёме берут STANDARD ($30/мес, 15 потоков) или ADVANCE ($90/мес, 50 потоков).

Законно ли автоматизировать прохождение таких CAPTCHA?

Автоматизация проверок для QA, тестирования и парсинга — легитимный сценарий. Ответственность лежит на стороне данных: обрабатывайте только то, на что у вас есть право, и учитывайте применимое законодательство (152-ФЗ, GDPR).


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


Нужно решить необычную капчу — начните с CaptchaAI.

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