Use Cases

Решение CAPTCHA кириллического текста с помощью CaptchaAI

Скрипт возвращает правильный на вид текст, а форма всё равно пишет «неверный код»? Причина почти всегда одна: буква «А» на кириллической CAPTCHA и латинская «A» в выводе стандартного OCR — это два разных символа Unicode, хотя на экране они неотличимы. Модели, обученные на латинице, регулярно возвращают латинский вариант там, где сайт ждёт кириллический, — и форма отклоняет вроде бы верный ответ. Ниже — почему так происходит и как решать такие CAPTCHA через CaptchaAI, не переписывая парсер под каждый сайт заново.

Кириллица и «похожие» латинские буквы: в чём разница

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

Символ Латиница Кириллица Что это на самом деле
A A (U+0041) А (U+0410) разные кодовые точки при одинаковом начертании
B B (U+0042) В (U+0412) кириллическая «Вэ»
C C (U+0043) С (U+0421) кириллическая «Эс»
E E (U+0045) Е (U+0415) кириллическая «Е»
H H (U+0048) Н (U+041D) кириллическая «Эн»
O O (U+004F) О (U+041E) кириллическая «О»
P P (U+0050) Р (U+0420) кириллическая «Эр»

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

Какие кириллические CAPTCHA встречаются на практике

Кроме путаницы с похожими буквами, кириллические CAPTCHA на практике сводятся к нескольким типовым шаблонам:

Шаблон Описание Пример
Обычное русское слово случайный набор кириллических букв ШКАФ, ПИРОГ
Смешение латиницы и кириллицы часть символов латинские, часть кириллические ABСDе (A, B, D — латиница; С, е — кириллица)
Числа прописью цифра записана словом ПЯТЬ, ТРИ
Арифметика словами пример записан текстом, а не цифрами два плюс три = ?
Искажённая кириллица текст с наклоном, шумом или растяжением обычная OCR-задача, только на кириллице

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

Пример: проверка формы регистрации в staging

Логистическая компания, работающая с маркетплейсами в России и Казахстане, перед каждым релизом прогоняет автоматические QA-тесты формы регистрации курьеров на staging-окружении. Форма использует кириллическую image-CAPTCHA собственной разработки — стандартный английский OCR её не распознаёт, а решать вручную сотни задач при каждом прогоне тестов нерационально. Интеграция CaptchaAI с параметром language=2 в тестовый пайплайн (Selenium + Python) позволяет прогонять весь сценарий автоматически: получить изображение, решить, отправить форму, проверить редирект на страницу успеха. Такой подход держит регресс-тесты быстрыми и не требует ручного вмешательства при каждом обновлении формы — при условии, что тестируется собственная staging-среда компании, а не сторонний production-сайт.

Python: решение кириллической CAPTCHA через API

Функция ниже решает CAPTCHA-изображение напрямую и отдельно — CAPTCHA, полученную внутри уже открытой сессии (например, после логина или перехода по ссылке):

import requests
import base64
import time

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"


def solve_cyrillic_captcha(image_path: str) -> str:
    """Solve a Cyrillic text image CAPTCHA."""
    with open(image_path, "rb") as f:
        image_b64 = base64.b64encode(f.read()).decode()

    resp = requests.post(SUBMIT_URL, data={
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "language": 2,          # Non-Latin character support
        "json": 1,
    }, timeout=30).json()

    if resp.get("status") != 1:
        raise RuntimeError(f"Submit: {resp.get('request')}")

    task_id = resp["request"]
    for _ in range(24):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get", "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve: {poll.get('request')}")

    raise RuntimeError("Timeout")


def solve_cyrillic_from_session(session: requests.Session,
                                 captcha_url: str) -> str:
    """Solve a Cyrillic CAPTCHA within a session context."""
    resp = session.get(captcha_url, timeout=15)
    image_b64 = base64.b64encode(resp.content).decode()

    submit = requests.post(SUBMIT_URL, data={
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "language": 2,
        "json": 1,
    }, timeout=30).json()

    if submit.get("status") != 1:
        raise RuntimeError(f"Submit: {submit.get('request')}")

    task_id = submit["request"]
    for _ in range(24):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get", "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve: {poll.get('request')}")

    raise RuntimeError("Timeout")


def verify_cyrillic(text: str) -> bool:
    """Verify that solved text contains Cyrillic characters."""
    return any('\u0400' <= ch <= '\u04FF' for ch in text)


# --- Russian website form flow ---

def solve_russian_form(form_url: str, captcha_url: str,
                       form_data: dict) -> requests.Response:
    """Complete a Russian website form with CAPTCHA."""
    session = requests.Session()
    session.headers.update({
        "Accept-Language": "ru-RU,ru;q=0.9",
    })

    # Establish session
    session.get(form_url, timeout=15)

    # Solve CAPTCHA
    captcha_text = solve_cyrillic_from_session(session, captcha_url)
    print(f"Cyrillic CAPTCHA: {captcha_text}")

    if verify_cyrillic(captcha_text):
        print("Confirmed: contains Cyrillic characters")

    form_data["captcha"] = captcha_text
    return session.post(form_url, data=form_data, timeout=30)


# --- Usage ---

text = solve_cyrillic_captcha("russian_captcha.png")
print(f"Solved: {text}")
print(f"Is Cyrillic: {verify_cyrillic(text)}")
print(f"Unicode codepoints: {[hex(ord(c)) for c in text]}")

JavaScript: обработка кириллицы CAPTCHA

Тот же принцип на Node.js, с проверкой, что решённый текст действительно содержит кириллические символы:

const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
const fs = require("fs");

async function solveCyrillicCaptcha(imagePath) {
  const imageB64 = fs.readFileSync(imagePath, "base64");

  const body = new URLSearchParams({
    key: API_KEY,
    method: "base64",
    body: imageB64,
    language: "2",
    json: "1",
  });

  const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
  if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);

  const taskId = resp.request;
  for (let i = 0; i < 24; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const poll = await (await fetch(url)).json();
    if (poll.request === "CAPCHA_NOT_READY") continue;
    if (poll.status === 1) return poll.request;
    throw new Error(`Solve: ${poll.request}`);
  }
  throw new Error("Timeout");
}

function isCyrillic(text) {
  return /[\u0400-\u04FF]/.test(text);
}

function showCodepoints(text) {
  return [...text].map((ch) => `${ch}=U+${ch.codePointAt(0).toString(16).padStart(4, "0")}`);
}

// Usage
const text = await solveCyrillicCaptcha("russian_captcha.png");
console.log(`Solved: ${text}`);
console.log(`Is Cyrillic: ${isCyrillic(text)}`);
console.log(`Codepoints: ${showCodepoints(text).join(", ")}`);

Типичные проблемы и решения

Если решённый текст не проходит проверку формы, ищите причину в этой таблице, прежде чем менять код:

Проблема Причина Решение
Форма отклоняет вроде бы правильный текст несовпадение кодовых точек кириллицы и латиницы сверьте юникод: «А» (U+0410) ≠ «A» (U+0041)
Текст отображается «битым» набором символов неверная кодировка при чтении ответа используйте UTF-8 везде, задайте response.encoding = 'utf-8'
В смешанном тексте часть символов распознана неверно OCR путает похожие латинские и кириллические буквы передавайте language=2 — модель переключается в кириллический режим
Не распознаются украинские ґ, є, і, ї это отдельные буквы украинского алфавита, отсутствующие в русском они поддерживаются с тем же language=2
CaptchaAI решил CAPTCHA, а форма всё равно её не принимает не совпадает регистр символов отправляйте текст ровно так, как вернул CaptchaAI, без изменения регистра
Задача подолгу висит в статусе CAPCHA_NOT_READY сервер ещё обрабатывает изображение в первые 10–15 секунд это норма; опрашивайте res.php с интервалом, как в примере выше

Частые вопросы

Нужен ли отдельный API-ключ для кириллических CAPTCHA?

Нет. API-ключ CaptchaAI один и тот же для всех типов задач. Кириллица включается параметром language=2 в самом запросе, а не отдельным ключом или тарифом.

Сколько стоит решение CAPTCHA с кириллическим текстом?

Столько же, сколько любая другая image/OCR-задача: тариф CaptchaAI зависит от количества параллельных потоков, а не от языка или типа CAPTCHA. Например, план BASIC ($15/мес, 5 потоков) включает неограниченное число решений на поток без доплаты за кириллицу.

Поддерживается ли болгарская и сербская кириллица, а не только русская?

Да. Кириллические алфавиты этих языков пересекаются с русским по большинству символов, и language=2 распознаёт их так же, как русский и украинский текст. Символы, специфичные для конкретного языка, включая украинские ґ, є, і, ї, тоже поддерживаются.

Что делать, если задача подолгу висит в статусе CAPCHA_NOT_READY?

В первые 10–15 секунд это нормально — сервер ещё обрабатывает изображение. Опрашивайте res.php с интервалом в несколько секунд, как в примере кода выше, и не отправляйте повторный запрос на решение, пока не получите финальный ответ.

Что дальше

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