Um CAPTCHA de imagem com letras coladas, fonte diferente por caractere ou ruído de fundo derruba a precisão de qualquer OCR genérico. Isso não precisa derrubar sua automação: a API de imagem/OCR da CaptchaAI já lida com a maioria dessas distorções nativamente.
O trabalho do seu lado é descrever o desafio certo com os hints certos (textinstructions, regsense, minLen/maxLen). Este guia mostra como montar a chamada em Python, classificar o tipo de complexidade e o que fazer quando o mesmo CAPTCHA continua falhando.
Enviando o CAPTCHA pela API
O envio começa sempre da mesma forma, não importa a complexidade: a imagem em base64 vai para o endpoint de OCR, com hints opcionais no payload. A função abaixo é a base reutilizada por todas as estratégias das próximas seções.
import requests
import base64
import time
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
def solve_complex_image(image_b64, hints=None):
"""Solve a complex multi-character image CAPTCHA."""
payload = {
"key": API_KEY,
"method": "base64",
"body": image_b64,
"json": 1,
}
if hints:
payload.update(hints)
resp = requests.post(
"https://ocr.captchaai.com/in.php",
data=payload,
timeout=30,
)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(f"Submit failed: {result.get('request')}")
task_id = result["request"]
time.sleep(8)
for _ in range(24):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(5)
raise TimeoutError("Solve timeout")
Como identificar o tipo de complexidade
O mesmo endpoint resolve todos os casos abaixo, mas o hint certo muda a taxa de acerto já na primeira tentativa. Comece classificando o desafio antes de montar os hints.
Casos simples e médios
- Texto limpo — sem distorção, fonte uniforme; geralmente não precisa de hints extras.
- Texto distorcido — letras giradas ou redimensionadas individualmente; use
minLen/maxLenpara restringir o tamanho esperado. - Ruído + linhas — ruído de fundo e linhas tachadas; descreva o ruído em
textinstructions. - Variação de cor — cores diferentes por caractere; normalmente resolve sem hints adicionais.
- Expressão matemática — números e operadores com resultado esperado; ative
calc=1para receber o valor já calculado em vez da expressão bruta.
Casos difíceis
- Letras conectadas — os caracteres se sobrepõem ou se tocam.
- Multi-fonte — cada caractere usa uma fonte diferente.
Os dois casos difíceis usam a mesma função base de envio — só muda o textinstructions enviado no payload, como mostram as duas estratégias a seguir.
Letras conectadas: o desafio mais comum para OCR
Letras conectadas ou sobrepostas são onde um OCR genérico erra primeiro — mas não para a CaptchaAI. Basta descrever o padrão no textinstructions e limitar a faixa de tamanho esperada da resposta:
def solve_connected_letters(image_path):
"""Solve CAPTCHA with connected/overlapping characters."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"textinstructions": "Characters may be connected or overlapping",
"minLen": 4,
"maxLen": 8,
})
Ruído de fundo e caixa mista
Quando o CAPTCHA mistura maiúsculas e minúsculas sobre um fundo com ruído, ative regsense para preservar o caso e descreva o ruído no hint:
def solve_noisy_mixed(image_path):
"""Solve CAPTCHA with background noise and mixed case."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"regsense": 1, # Case-sensitive
"language": 2, # Latin characters
"textinstructions": "Ignore background lines and noise",
})
CAPTCHA com várias fontes por caractere
Formulários que trocam a fonte a cada caractere tentam quebrar o reconhecimento por padrão visual. Avise sobre isso e restrinja o intervalo de tamanho esperado:
def solve_multi_font(image_path):
"""Solve CAPTCHA using multiple fonts per character."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"textinstructions": "Each character may use a different font or style",
"minLen": 5,
"maxLen": 7,
})
Pré-processamento: quando vale a pena
Pré-processar antes de enviar não é obrigatório — a CaptchaAI já lida com a maior parte das distorções nativamente. Vale testar quando a imagem tem contraste baixo ou ruído pesado: o exemplo abaixo converte para tons de cinza, aumenta o contraste e binariza antes de codificar em base64.
# preprocess.py
from PIL import Image, ImageFilter, ImageEnhance
import io
import base64
def preprocess_for_ocr(image_path):
"""Preprocess image to improve OCR accuracy."""
img = Image.open(image_path)
# Convert to grayscale
img = img.convert("L")
# Increase contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Sharpen
img = img.filter(ImageFilter.SHARPEN)
# Binarize (threshold)
threshold = 128
img = img.point(lambda p: 255 if p > threshold else 0)
# Encode back to base64
buffer = io.BytesIO()
img.save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode("ascii")
Repetindo o envio com relatório de erros
Se a primeira tentativa vier com resultado ruim, tente de novo com hints mais permissivos antes de desistir — e reporte a resposta incorreta para ajudar a CaptchaAI a ajustar o modelo para o seu tipo de CAPTCHA:
# retry_strategy.py
def solve_with_retry(image_b64, hints, max_retries=3):
"""Retry solving with fallback strategies."""
strategies = [
hints, # Original hints
{**hints, "textinstructions": ""}, # Without instructions
{**hints, "numeric": 0, "regsense": 0}, # Relaxed constraints
]
for i, strategy in enumerate(strategies[:max_retries]):
try:
result = solve_complex_image(image_b64, strategy)
return {"text": result, "strategy": i, "success": True}
except RuntimeError:
continue
return {"text": None, "strategy": -1, "success": False}
def report_bad_answer(task_id):
"""Report incorrect answer for quality feedback."""
requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "reportbad",
"id": task_id,
}, timeout=10)
Perguntas frequentes
Preciso pré-processar as imagens antes de enviar para a CaptchaAI?
Só se estiver tendo resultados ruins. A CaptchaAI lida com a maioria das distorções nativamente, e o pré-processamento só ajuda mesmo em imagens com muito ruído ou contraste baixo.
O que significa "CAPCHA_NOT_READY" na resposta da consulta?
É o status intermediário enquanto o desafio ainda está sendo processado. O polling deve continuar consultando res.php normalmente nesse caso, e só tratar como erro se vier um texto diferente disso.
O CaptchaAI resolve CAPTCHAs de imagem com expressões matemáticas?
Sim. Ative calc=1 no envio para que o resultado volte já calculado, em vez da expressão bruta como "7 + 3".
Quantas threads preciso para resolver um lote grande de CAPTCHAs de imagem?
Depende do paralelismo, não do volume total — cada plano cobra por thread simultânea, com resolução ilimitada por thread. O BASIC (5 threads) cobre a maioria das suítes de QA; picos de execução paralela pedem STANDARD (15 threads) ou ADVANCE (50 threads).
Um mesmo tipo de CAPTCHA continua falhando na minha automação — o que fazer?
Reporte as respostas erradas com reportbad para ajudar a ajustar a precisão, e adicione um textinstructions mais específico descrevendo a característica do CAPTCHA (letras coladas, fonte trocada, ruído).
Onde isso aparece no dia a dia de QA
Um cenário comum de QA autorizado:
- Uma equipe testa o formulário de cadastro em
staging.example.comcom CAPTCHAs de imagem gerados só para o ambiente de teste. - Os workers de resolução rodam na região
sa-east-1da AWS para manter a latência baixa a partir do Brasil. - Os CAPTCHAs de teste usam apenas dados fictícios — nunca capturas de tela de usuários reais — evitando problema de conformidade com a LGPD nos logs de execução.
- Para esse volume, o plano BASIC (US$ 15/mês, 5 threads) costuma bastar; suítes maiores, com dezenas de CAPTCHAs em paralelo, sobem para STANDARD (US$ 30/mês, 15 threads) ou ADVANCE (US$ 90/mês, 50 threads).
Erros comuns e como corrigir
Sintomas rápidos para diagnosticar o problema:
- Caracteres ausentes — letras conectadas mal interpretadas → adicione
textinstructionssobre texto conectado. - Caracteres extras — ruído interpretado como texto → faça o pré-processamento e remova o ruído antes do envio.
- Caso errado — maiúsculas/minúsculas não preservadas → defina
regsense=1. - Resultado matemático como expressão — faltando
calc=1→ ative o modo de cálculo para CAPTCHAs matemáticos. - Erro constante em um site específico — fonte específica do site → reporte respostas ruins com
reportbadpara ajustar o modelo.
Guias relacionados
Para aprofundar:
- Como ajustar a precisão do OCR nas configurações da CaptchaAI
- Guia de pré-processamento de imagens para taxas de resolução mais altas
Resolva CAPTCHAs de imagem complexos sem perder precisão — comece agora com a CaptchaAI.