Use Cases

Gérer les CAPTCHA arabes et les interfaces RTL avec CaptchaAI

Un CAPTCHA image en arabe se résout avec le même endpoint OCR que n'importe quelle image, à une condition près : passer language=2 pour activer la reconnaissance des écritures non latines. La vraie difficulté n'est donc pas l'appel API, mais tout ce qui entoure le caractère arabe : sa forme change selon sa position dans le mot, le texte se lit de droite à gauche, et la page elle-même est souvent en right-to-left (RTL), ce qui déplace les champs et la zone du CAPTCHA par rapport à une page latine.

Il faut donc traiter deux problèmes en parallèle : l'OCR de l'image et le contexte d'affichage RTL de la page. Un flux calibré pour l'alphabet latin casse vite sur ces sites : il lit mal les lettres connectées et localise mal les éléments dans une mise en page inversée. Ce guide montre comment gérer les deux, en Python et en JavaScript.

Pourquoi les CAPTCHA arabes et RTL sont plus exigeants

Cinq caractéristiques rendent ces CAPTCHA plus délicats que leurs équivalents latins. Elles touchent à la fois la lecture de l'image et la structure de la page.

Contrainte Ce qui se passe
Formes contextuelles Une même lettre arabe s'écrit différemment selon sa position : initiale, médiane, finale ou isolée
Lecture de droite à gauche Le contenu du CAPTCHA se lit en RTL, à rebours du sens latin
Direction mixte Chiffres et caractères latins se mêlent à l'arabe, créant du texte bidirectionnel
Signes diacritiques Points et marques au-dessus ou en dessous des lettres changent le sens (ش contre س)
Mise en page RTL Formulaires et zone CAPTCHA sont positionnés en miroir par rapport à une page LTR

Activer la reconnaissance des écritures non latines

Le paramètre décisif est language=2 dans la requête d'envoi. Il indique au solveur Image/OCR de CaptchaAI d'attendre des caractères non latins plutôt que l'alphabet A–Z. C'est le même code pour l'arabe, le farsi et l'hébreu : vous n'avez pas à détecter la langue exacte en amont. Le reste du flux reste identique à un CAPTCHA image classique : envoi de l'image en base64 vers in.php, puis interrogation de res.php jusqu'à obtention du résultat.

Résoudre un CAPTCHA image en arabe en Python

Le script ci-dessous couvre trois cas : une image locale, une image téléchargée depuis une URL, et l'envoi complet d'un formulaire sur un site arabe. Notez l'en-tête Accept-Language: ar-SA et le charset=UTF-8, indispensables pour que le serveur accepte des données saisies en arabe.

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_arabic_captcha(image_path: str) -> str:
    """Solve an Arabic script 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_arabic_captcha_from_url(session: requests.Session,
                                   captcha_url: str) -> str:
    """Download and solve an Arabic CAPTCHA from a URL."""
    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")


# --- RTL-aware form submission ---

def submit_form_with_arabic_captcha(
    form_url: str,
    captcha_url: str,
    form_data: dict,
    captcha_field: str = "captcha",
) -> requests.Response:
    """Complete an Arabic website form with CAPTCHA."""
    session = requests.Session()
    session.headers.update({
        "Accept-Language": "ar-SA,ar;q=0.9",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    })

    # Load the form page to establish session
    session.get(form_url, timeout=15)

    # Solve the CAPTCHA
    captcha_text = solve_arabic_captcha_from_url(session, captcha_url)
    print(f"Arabic CAPTCHA solved: {captcha_text}")

    # Submit with the solved text
    form_data[captcha_field] = captcha_text
    response = session.post(form_url, data=form_data, timeout=30)

    return response


# --- Usage ---

# Simple Arabic image CAPTCHA
text = solve_arabic_captcha("arabic_captcha.png")
print(f"Arabic text: {text}")

# Form submission on Arabic site
response = submit_form_with_arabic_captcha(
    form_url="https://example.sa/registration",
    captcha_url="https://example.sa/captcha/generate",
    form_data={
        "name": "اسم المستخدم",
        "email": "user@example.com",
    },
)

Gérer un CAPTCHA arabe sur une page RTL en JavaScript

Côté navigateur, la localisation de l'image compte autant que la résolution. Sur une page RTL, ne vous fiez pas à la position visuelle : ciblez le <img> du CAPTCHA par son id ou sa classe avec Playwright, résolvez, puis remplissez le champ. La zone de saisie gère seule la direction du texte.

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

// Inject CAPTCHA token into RTL page with Playwright
async function solveAndInjectRTL(page) {
  // RTL pages may position the CAPTCHA differently
  const captchaImg = await page.locator("img[id*='captcha'], img[class*='captcha']");
  const imgSrc = await captchaImg.getAttribute("src");

  // Download the image
  const buffer = await (await fetch(imgSrc)).arrayBuffer();
  const imageB64 = Buffer.from(buffer).toString("base64");

  // Solve
  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) {
      // Fill the input — RTL input handles text direction automatically
      await page.locator("input[name*='captcha']").fill(poll.request);
      return poll.request;
    }
    throw new Error(`Solve: ${poll.request}`);
  }
}

// Usage
const text = await solveArabicCaptcha("arabic_captcha.png");
console.log(`Arabic text: ${text}`);

Écritures RTL prises en charge par l'OCR

Le même paramètre language=2 couvre l'ensemble des écritures RTL courantes, sans changement de code entre elles.

Écriture Langues concernées Remarque
Arabe Arabe, ourdou, pachto Lettres connectées, formes contextuelles
Farsi / persan Farsi Quelques lettres supplémentaires (پ, چ, ژ, گ)
Hébreu Hébreu Alphabet non connecté, lecture de droite à gauche

Un cas concret : collecter des données sur des portails en arabe

Prenons une équipe data au Maroc ou en Tunisie qui consolide des informations publiques depuis des portails de services en arabe. Beaucoup de ces sites sont bilingues arabe/français, mais servent le CAPTCHA en arabe, parfois avec des chiffres arabes orientaux (٠١٢٣) mêlés au texte. Un flux calibré pour l'anglais renvoie alors des résultats tronqués ou dans le désordre.

La marche à suivre reste celle des scripts ci-dessus : language=2, en-tête Accept-Language cohérent, et localisation des champs par sélecteur CSS plutôt que par position. Côté conformité, restez sur votre propre démarche ou un environnement que vous êtes autorisé à automatiser, et appliquez les principes RGPD : minimisez les données personnelles collectées et ne conservez que ce qui est strictement nécessaire. La logique technique ne change pas d'un marché à l'autre ; seuls le jeu de caractères et la mise en page évoluent.

Dépannage des CAPTCHA arabes et RTL

Symptôme Cause probable Correctif
Le texte arabe ressort à l'envers Le client affiche le RTL comme du LTR Encadrez la sortie d'un marqueur d'incorporation RTL (U+202B) ou utilisez un affichage compatible RTL
Les diacritiques disparaissent Image trop compressée ou basse résolution Repartez d'une image plus nette et moins dégradée
Texte arabe et chiffres illisibles une fois mélangés Algorithme bidirectionnel appliqué de façon incohérente Gérez explicitement les marqueurs directionnels Unicode
L'envoi du formulaire échoue avec une saisie arabe Problème d'encodage Envoyez charset=UTF-8 dans l'en-tête Content-Type
Le CAPTCHA n'est pas là où on l'attend La mise en page RTL inverse la position des éléments Localisez par sélecteur CSS ou id, jamais par position visuelle

FAQ

CaptchaAI prend-il en charge hCaptcha sur les sites arabes ?

Non — hCaptcha n'est pas pris en charge, quelle que soit la langue du site. CaptchaAI résout les CAPTCHA image/OCR (dont l'arabe), reCAPTCHA v2 et v3, Cloudflare Turnstile et Challenge, GeeTest v3, les grilles d'images et BLS. Pour un CAPTCHA image en arabe, c'est le solveur Image/OCR qui intervient.

Comment gérer le mélange de chiffres et de texte arabe ?

Ce texte bidirectionnel — arabe de droite à gauche, chiffres de gauche à droite — est la première source d'affichage incohérent. Le solveur renvoie les caractères reconnus ; c'est à votre code d'appliquer les marqueurs directionnels Unicode au moment de l'affichage ou du stockage, plutôt que de se fier au rendu par défaut du terminal.

Le farsi et l'hébreu passent-ils par le même workflow que l'arabe ?

Oui. Les trois écritures s'envoient avec language=2 et suivent exactement le même flux OCR. Le farsi ajoute quelques lettres à la base arabe, et l'hébreu possède son propre alphabet non connecté ; dans les deux cas, vous n'avez rien à changer au code.

Combien coûte la résolution de CAPTCHA arabes avec CaptchaAI ?

Le tarif ne dépend pas de la langue : la facturation se fait au thread, pas au CAPTCHA résolu. L'offre BASIC ($15/mois, 5 threads) inclut un nombre illimité de résolutions par thread pendant le mois, CAPTCHA arabes compris. Vous montez de palier selon le débit visé, pas selon le type d'écriture.

Pour aller plus loin

Vous ciblez des sites en arabe ou d'autres interfaces RTL ? Récupérez votre clé API CaptchaAI et adaptez votre pipeline OCR à ces jeux d'écriture avec language=2, au lieu de forcer un flux pensé pour l'alphabet latin.

Guides associés :

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