Solución de Problemas

Errores y soluciones comunes de OCR CAPTCHA

Cuando un CAPTCHA de imagen vuelve mal resuelto, el culpable casi nunca es el motor OCR: es la imagen que enviaste o el parámetro que no enviaste. Reintentar sin cambiar nada solo repite el mismo error más caro.

Clasifica el fallo en una de tres familias: envío rechazado con un código ERROR_*, texto que no coincide con la imagen, o imagen demasiado degradada para leerse. Esta guía recorre las tres en ese orden, con el parámetro que corrige cada caso.


Triaje en 30 segundos

Lo que ves Familia del fallo Dónde mirar
Un código ERROR_* en la respuesta de in.php Envío rechazado Cómo lees y codificas el archivo
Texto plausible, pero equivocado por uno o dos caracteres Faltan sugerencias numeric, regsense, min_len, calc
Texto sin ninguna relación con la imagen Imagen degradada Tamaño de captura, GIF animado, transparencia

Las dos primeras filas se arreglan en tu código; la tercera, en cómo capturas.


La API rechaza el envío

Estos tres códigos llegan en la respuesta de in.php: la tarea ni siquiera entró en cola, así que el OCR no tuvo nada que ver. Se arreglan al leer y codificar el archivo.

ERROR_WRONG_FILE_EXTENSION: base64 mal formado

  • Causa: base64 inválido o formato no compatible. Lo habitual es dejar el prefijo data:image/png;base64, que devuelve el navegador.
  • Arreglo: codifica el archivo crudo y manda solo la cadena, sin el prefijo.
import base64

# Ensure proper encoding
with open("captcha.png", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()

# Don't include the data URI prefix
# WRONG: "data:image/png;base64,iVBOR..."
# RIGHT: "iVBOR..."

ERROR_ZERO_CAPTCHA_FILESIZE: el archivo llegó vacío

  • Causa: guardaste un archivo de cero bytes, casi siempre porque la imagen exige la cookie de sesión y tu cliente la descargó sin ella.
  • Arreglo: comprueba el tamaño antes de enviar y vuelve a capturar dentro de la misma sesión.
import os

# Check file size before submitting
if os.path.getsize("captcha.png") == 0:
    print("Image file is empty — re-download")
    # Re-capture the captcha

ERROR_TOO_BIG_CAPTCHA_FILESIZE: imagen por encima del límite

  • Causa: la imagen supera el máximo admitido (normalmente 600 KB) porque envías todo el viewport en vez del recorte del CAPTCHA.
  • Arreglo: recorta al elemento y optimiza sin perder nitidez en los trazos.
from PIL import Image
import io

img = Image.open("captcha.png")
# Reduce quality without losing text clarity
buffer = io.BytesIO()
img.save(buffer, format="PNG", optimize=True)

El texto vuelve mal: parámetros de sugerencia

Aquí se gana la mayor parte de la precisión: lo que ya sabes del CAPTCHA — solo dígitos, seis caracteres, distingue mayúsculas — hay que decirlo en el envío.

Confusión entre caracteres parecidos: 0/O, 1/l/I, 5/S

  • Causa: el conjunto de caracteres está abierto y el solver duda entre glifos casi idénticos, captura tras captura.
  • Solución: cierra el conjunto con numeric.
# If captcha is digits only
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "base64", "body": b64,
    "numeric": 1,  # 1 = digits only
    "json": 1
})

# If captcha is letters only
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "base64", "body": b64,
    "numeric": 2,  # 2 = letters only
    "json": 1
})

El formulario distingue mayúsculas y minúsculas

  • Qué ves: las letras son correctas, pero el formulario rechaza la respuesta igual.
  • Causa: la respuesta vuelve en minúsculas por defecto y el formulario compara carácter a carácter.
  • Solución: activa regsense=1.
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "base64", "body": b64,
    "regsense": 1,  # Case-sensitive
    "json": 1
})

Sobran o faltan caracteres

  • Qué ves: la respuesta llega con siete caracteres cuando el campo admite seis, o al revés.
  • Causa: el ruido se lee como un carácter más, o dos glifos pegados se leen como uno.
  • Solución: si la longitud es fija, decláralo con min_len y max_len.
# If you know the CAPTCHA is always 6 characters
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "base64", "body": b64,
    "min_len": 6,
    "max_len": 6,
    "json": 1
})

El CAPTCHA es una operación matemática

  • Causa: recibes "3+7" en vez de "10": el OCR transcribe la expresión, no la evalúa.
  • Solución: pide el cálculo con calc=1.
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "base64", "body": b64,
    "calc": 1,  # Compute the math expression
    "json": 1
})

Referencia rápida de parámetros

Cada fila corresponde a uno de los síntomas anteriores.

Parámetro Cuándo usarlo Efecto
numeric=1 Solo dígitos Elimina la confusión letra/dígito
numeric=2 Solo letras Elimina la confusión letra/dígito
min_len / max_len Longitud conocida Previene caracteres extra o faltantes
regsense=1 Diferencia mayúsculas/minúsculas Conserva el caso original
calc=1 Expresión matemática Devuelve la respuesta calculada
phrase=1 Contiene espacios Permite respuestas de varias palabras
language=1 Texto cirílico Usa el juego de caracteres correcto
language=2 Texto latino Usa el juego de caracteres correcto

Cambia un parámetro por vez contra el mismo lote de capturas; con dos a la vez no sabrás cuál ayudó.


La imagen no da para más

Si ya cerraste el conjunto de caracteres y el texto sigue sin parecerse a la imagen, lo que capturas no lleva información suficiente. Estos tres casos cubren casi todo.

La capturas demasiado pequeña

  • Problema: por debajo de unos 50 píxeles de altura los trazos se funden.
  • Solución: busca una URL de origen con más resolución si la página la muestra reducida.
# Check for higher-res version
img_src = captcha_el.get_attribute("src")
# Some sites use ?size=small — try removing or changing the parameter
high_res_src = img_src.replace("size=small", "size=large")

El texto solo aparece en un fotograma

  • Problema: algunos portales sirven GIF animados donde el texto solo es visible en ciertos cuadros.
  • Solución: extrae los fotogramas y envía el que lleva el texto.
from PIL import Image

gif = Image.open("captcha.gif")
# Extract each frame and find the one with text
for i in range(gif.n_frames):
    gif.seek(i)
    gif.save(f"frame_{i}.png")

PNG con fondo transparente

  • Problema: un PNG con canal alfa puede renderizarse sobre fondo oscuro y quedar ilegible.
  • Solución: aplánalo sobre fondo blanco antes de codificarlo.
from PIL import Image

img = Image.open("captcha.png").convert("RGBA")
background = Image.new("RGBA", img.size, (255, 255, 255, 255))
background.paste(img, mask=img)
background.convert("RGB").save("captcha_white_bg.png")

Reporta las respuestas incorrectas

Si la respuesta llega mal pese a enviar la imagen y los parámetros correctos, repórtala con reportbad en vez de descartarla en silencio:

# Report bad answer
requests.get("https://ocr.captchaai.com/res.php", params={
    "key": API_KEY,
    "action": "reportbad",
    "id": task_id
})

El reporte alimenta la precisión del solver y, en casos válidos, CaptchaAI puede compensar esa resolución. Hazlo solo con fallos reales: reportar aciertos ensucia la señal.


Un caso frecuente en portales públicos

Buena parte del volumen de OCR en el mercado hispanohablante viene de portales públicos: cita previa en España, trámites del SAT en México, AFIP en Argentina o los centros de visado BLS. Casi todos sirven texto en imágenes pequeñas y con ruido — el escenario exacto de numeric y min_len. Prueba esos dos parámetros contra veinte capturas guardadas antes de tocar nada más.

Si tus comprobaciones corren en paralelo, recuerda que CaptchaAI factura por thread concurrente, no por resolución: BASIC ($15/mes, 5 threads) cubre un monitor pequeño y ADVANCE ($90/mes, 50 threads) un pipeline con decenas de comprobaciones simultáneas. Respeta siempre los términos de servicio del sitio y la normativa de protección de datos aplicable (GDPR y LOPDGDD en España, LFPDPPP en México).


Preguntas frecuentes

¿Conviene reintentar automáticamente cuando el texto sale mal?

Sí, pero con un tope. Un reintento con una captura nueva resuelve el caso puntual; a partir del segundo el fallo es sistemático y toca revisar parámetros.

¿Qué hago si el CAPTCHA mezcla letras y números?

No uses numeric: cerrar el conjunto a un solo tipo empeora la lectura alfanumérica. Apóyate en min_len, max_len y regsense, que restringen sin descartar caracteres válidos.

¿Me conviene preprocesar la imagen antes de enviarla?

Solo cuando corrige un defecto concreto: aplanar transparencia, recortar o subir la resolución de origen. La binarización agresiva borra trazos finos y baja la precisión.

¿Los CAPTCHA de audio se resuelven por este mismo endpoint?

No. El flujo de audio es distinto y no se cubre con method=base64. Consulta la documentación de CaptchaAI para la compatibilidad vigente.

¿Los reintentos me suben la factura?

No: con facturación por thread y resoluciones ilimitadas dentro del plan, un reintento consume tiempo de thread, no un cargo aparte. Lo que sí baja es tu throughput.


Guías relacionadas

Los comentarios están deshabilitados para este artículo.