Um formulário em árabe não fica mais simples só porque você inverteu a leitura de LTR para RTL. O problema real é outro: as letras árabes mudam de forma conforme a posição na palavra, números e texto latino se misturam ao árabe (bidirecional), e o layout da página é espelhado. Para resolver o CAPTCHA de imagem, a CaptchaAI usa o mesmo endpoint de sempre — a diferença fica em um único parâmetro, language=2.
Isso aparece com frequência em times de QA brasileiros testando portais de visto e comércio exterior com o Golfo e o Norte da África: o formulário roda em staging, os testes partem da região sa-east-1 da AWS, e o texto sai invertido na tela sem tratamento RTL — não porque o solver errou, mas porque o cliente exibiu texto RTL como LTR.
Por que o CAPTCHA em árabe e RTL é mais difícil de resolver
| Desafio | Detalhe |
|---|---|
| Conexão de caracteres | Uma mesma letra árabe muda de forma conforme a posição na palavra — inicial, medial, final ou isolada |
| Leitura da direita para a esquerda | O texto do CAPTCHA é lido da direita para a esquerda |
| Direção mista (bidirecional) | Números e texto latino aparecem misturados com árabe na mesma string |
| Marcas diacríticas | Pontos e sinais acima ou abaixo dos caracteres — fáceis de perder em imagem de baixa resolução |
| Layout de página RTL | Formulário e posição do CAPTCHA ficam espelhados em relação a uma página LTR |
Os dois primeiros pontos quebram um OCR genérico, que trata cada forma de uma letra árabe como um caractere diferente e ignora a leitura direita-para-esquerda. O solver Image/OCR da CaptchaAI já lida com escrita conectada — é isso que language=2 ativa.
Roteiros RTL que a CaptchaAI reconhece
| Roteiro | Idiomas cobertos | Parâmetro na API |
|---|---|---|
| Árabe | Árabe, urdu, pashto | language=2 |
| Farsi/Persa | Persa, com caracteres extras | language=2 |
| Hebraico | Hebraico | language=2 |
O parâmetro é o mesmo nos três casos — a CaptchaAI detecta o conjunto de caracteres estendido automaticamente.
Resolvendo CAPTCHA de imagem em árabe com Python
Envie a imagem em base64 para in.php com language=2, faça o polling em res.php e trate o texto retornado como UTF-8.
O exemplo cobre os dois casos mais comuns nesse fluxo: resolver a partir de um arquivo local e da URL do CAPTCHA dentro de uma sessão autenticada, terminando no envio do formulário.
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": "[email protected]",
},
)
CAPTCHA árabe e RTL em JavaScript (Playwright)
Em Node.js o padrão é o mesmo — muda como você localiza o CAPTCHA. Em layout RTL, o seletor por posição costuma falhar; use id/class, baixe o src, resolva e preencha o campo de resposta.
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}`);
Problemas comuns e como corrigir
Estes são os erros mais relatados por quem já roda language=2 em produção — a maioria tem origem na exibição do texto no cliente, não no solver.
| Problema | Causa | Correção |
|---|---|---|
| Texto árabe invertido na tela | Cliente exibe texto RTL como LTR | Envolva a saída em \u202B (incorporação RTL) |
| Faltam marcas diacríticas | Imagem de baixa resolução | Use imagens de CAPTCHA em resolução mais alta |
| Texto bidirecional fora de ordem | Algoritmo BiDi inconsistente | Trate caracteres direcionais com marcadores Unicode |
| Envio falha com texto em árabe | Incompatibilidade de codificação | Use charset=UTF-8 no Content-Type |
| Posição do CAPTCHA difere do esperado | Layout RTL espelha a posição dos elementos | Use seletores CSS (id/class), não posição |
Perguntas frequentes
Estas são as dúvidas mais comuns de times que integram roteiros RTL pela primeira vez.
O CaptchaAI reconhece a escrita árabe conectada?
Sim. As letras árabes mudam de forma conforme a posição na palavra — inicial, medial, final ou isolada — e o solver Image/OCR da CaptchaAI reconhece essas variações, não apenas letras isoladas.
O mesmo parâmetro language=2 funciona para urdu, pashto e hebraico, ou preciso mudar algo?
Funciona para os três, além do árabe e do farsi. A CaptchaAI detecta o conjunto de caracteres estendido automaticamente — não é preciso trocar o parâmetro por idioma.
Como corrijo texto árabe que sai invertido depois de resolver o CAPTCHA?
O solver retorna o texto correto; o problema costuma estar na exibição. Envolva a string em \u202B (incorporação RTL) antes de mostrá-la, ou use um componente de UI já preparado para texto bidirecional.
Preciso tratar números misturados ao texto árabe de forma diferente?
Sim. Números dentro de uma string árabe seguem leitura da esquerda para a direita mesmo em texto RTL — isso é bidirecional. Se seu pipeline reformata a resposta antes do envio, trate isso com marcadores Unicode, em vez de assumir uma única direção.
Comece agora
Resolva CAPTCHA em árabe, farsi e hebraico sem reescrever seu pipeline — obtenha sua chave de API da CaptchaAI e ative language=2.
Guias relacionados:
- Como resolver CAPTCHAs em sites chineses
- Conjunto de caracteres para CAPTCHA de imagem multilíngue
- Como configurar localização e idioma no CAPTCHA
Esses três guias cobrem os cenários mais comuns de expansão para roteiros não latinos e RTL.