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 :
- Résoudre les CAPTCHA sur les sites web chinois
- Jeux de caractères pour les CAPTCHA image multilingues
- Localisation des CAPTCHA et paramètres de langue