Use Cases

Résolution de CAPTCHA de texte cyrillique avec CaptchaAI

Pour résoudre un CAPTCHA en cyrillique, un seul réglage compte : envoyez l'image à l'OCR de CaptchaAI avec le paramètre language=2, qui active les modèles non latins. Le reste — encodage UTF-8, vérification des points de code Unicode — sert à éviter le vrai piège de ces CAPTCHA : des caractères russes qui ressemblent à s'y méprendre à des lettres latines.

Ces caractères, ce sont les homoglyphes : А, В, С, Е, Н, О paraissent identiques à leurs équivalents latins mais occupent des points de code Unicode différents. Un OCR latin lit « B » là où le formulaire attend « В » (U+0412), et rejette une saisie pourtant correcte à l'œil.

Pourquoi le cyrillique piège l'OCR latin

Le problème n'est pas la lisibilité — ces CAPTCHA sont souvent nets — mais l'identité des caractères. Un OCR entraîné sur l'alphabet latin rabat chaque glyphe cyrillique sur la lettre latine la plus proche et renvoie le mauvais point de code.

Les caractères qui trompent l'œil

Ressemble à Latin Cyrillique Remarque
A A (U+0041) А (U+0410) Points de code distincts
B B (U+0042) В (U+0412) Cyrillique « Ve »
C C (U+0043) С (U+0421) Cyrillique « Es »
E E (U+0045) Е (U+0415) Encodage différent
H H (U+0048) Н (U+041D) Cyrillique « En »
O O (U+004F) О (U+041E) Points de code distincts
P P (U+0050) Р (U+0420) Cyrillique « Er »

Soumettre le mauvais point de code revient à envoyer un tout autre caractère : le formulaire compare octet par octet et rejette la saisie, même parfaite à l'œil. La sortie de l'OCR doit donc renvoyer de vrais caractères cyrilliques, pas leurs sosies latins.

Quand le problème surgit

Le cas revient souvent dans les équipes francophones qui collectent des données publiques — veille tarifaire, open data — sur des portails russes, ukrainiens ou bulgares. Dès qu'un formulaire protège l'accès par un CAPTCHA en toutes lettres, le pipeline se bloque sur des caractères que l'OCR standard lit mal. Si vous journalisez des données personnelles au passage, gardez vos obligations RGPD en tête et minimisez ce que vous conservez.

Les formats de CAPTCHA cyrilliques les plus courants

Modèle Description Exemple
Mot cyrillique pur Mot russe courant ШКАФ, ПИРОГ
Latin + cyrillique mélangés Deux scripts dans une même image ABСDе (A, B, D latins ; С, е cyrilliques)
Nombres écrits en toutes lettres Mots-nombres ПЯТЬ (cinq), ТРИ (trois)
Calcul en russe Arithmétique en toutes lettres два плюс три = ?
Cyrillique déformé Texte russe distordu Défi OCR classique en cyrillique

Résoudre un CAPTCHA cyrillique en Python

Le flux est classique : encodez l'image en base64, envoyez-la à in.php avec language=2, puis interrogez res.php jusqu'à obtenir le texte. La fonction verify_cyrillic() confirme que la réponse contient bien des points de code de la plage U+0400–U+04FF avant de la soumettre.

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

Gérer les CAPTCHA cyrilliques en JavaScript

La même logique en Node.js, si votre stack de scraping tourne déjà sur fetch. Le helper isCyrillic() teste la plage cyrillique par expression régulière, et showCodepoints() liste chaque point de code pour déboguer un rejet inattendu.

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(", ")}`);

Trois réflexes avant de soumettre le texte

Avant de renvoyer le texte au formulaire, trois vérifications évitent l'essentiel des rejets :

  • Forcez language=2 à la soumission : sans lui, l'OCR retombe sur des modèles latins qui confondent В et B.
  • Imposez l'UTF-8 de bout en bout, y compris sur la réponse HTTP (response.encoding = 'utf-8').
  • Comparez les points de code à la plage U+0400–U+04FF avant de valider — verify_cyrillic() le fait en une ligne.

Dépannage

Problème Cause Correctif
Le formulaire rejette un texte pourtant correct Homoglyphe latin/cyrillique Vérifiez les points de code : А (U+0410) ≠ A (U+0041)
Caractères illisibles à l'affichage Mauvais encodage Utilisez UTF-8 partout ; response.encoding = 'utf-8'
Texte mixte partiellement faux L'OCR confond latin et cyrillique language=2 distingue correctement les deux scripts
Caractères ukrainiens manquants (ґ, є, і, ї) Modèle non adapté au script Ils sont pris en charge avec language=2
Casse ignorée Majuscules et minuscules sont significatives Soumettez le texte exactement tel que renvoyé par CaptchaAI

FAQ

Quel paramètre active la reconnaissance du cyrillique ?

Le paramètre language=2. Il indique à l'OCR d'employer des modèles non latins qui renvoient les points de code Unicode corrects (U+0400–U+04FF) au lieu de leurs sosies latins. Sans lui, un OCR latin standard confond В et B.

L'OCR de CaptchaAI gère-t-il l'ukrainien, le bulgare et le serbe ?

Oui. Avec language=2, il reconnaît l'ensemble des scripts cyrilliques, y compris les caractères propres à l'ukrainien absents du russe : ґ (U+0491), є (U+0454), і (U+0456), ї (U+0457).

Pourquoi un texte cyrillique correct est-il parfois refusé par le formulaire ?

Presque toujours à cause d'un homoglyphe : un caractère latin envoyé à la place de son sosie cyrillique. Comparez les points de code (А vaut U+0410, pas U+0041) et vérifiez que la chaîne est bien encodée en UTF-8.

Un CAPTCHA en cyrillique coûte-t-il plus cher à résoudre ?

Non. CaptchaAI facture au thread simultané, sans surcoût selon le type de CAPTCHA. Le forfait BASIC ($15/mois, 5 threads) traite les images cyrilliques comme n'importe quel CAPTCHA texte, avec des résolutions illimitées par thread.

Pour aller plus loin

Vous savez repérer les homoglyphes, forcer l'UTF-8 et activer language=2 sur vos CAPTCHA cyrilliques — créez votre clé API CaptchaAI pour l'appliquer à vos flux.

Guides associés :

Les commentaires sont désactivés pour cet article.