Casos de Uso

BLS CAPTCHA en portales gubernamentales: estrategias de manejo

Sí, se puede automatizar la resolución del BLS CAPTCHA de los portales gubernamentales de citas y trámites, pero el CAPTCHA es solo la mitad del problema: el otro reto es la sesión. Los centros de visa BLS que atienden a solicitantes de Latinoamérica, España y el norte de África combinan formularios de varios pasos, tokens CSRF y sesiones que caducan en minutos. CaptchaAI resuelve el BLS CAPTCHA con una alta tasa de éxito, en 5 a 15 segundos; el verdadero reto es encajar esa resolución sin que la sesión se caiga a medio camino. Trátalo como QA de un flujo autorizado, respetando los términos de servicio y la normativa de protección de datos aplicable.

Por qué la sesión pesa más que el propio CAPTCHA

Antes de escribir código, ten claro qué exige el portal. Estos son los requisitos que más fallan:

Requisito Cómo cumplirlo
Cookies intactas Usa requests.Session() o un contexto persistente del navegador
No superar los límites Añade pausas entre cargas de página (2–5 segundos)
Tokens CSRF Extrae e incluye el token CSRF en cada POST
Tiempos de espera de sesión Completa el flujo dentro de la ventana de sesión
Cadenas de redirección Permite las redirecciones automáticas en tu cliente HTTP

Con estos puntos cubiertos, resolver el CAPTCHA deja de ser el cuello de botella.

Dónde aparece el BLS CAPTCHA

El portal coloca el CAPTCHA justo donde quiere frenar la automatización:

  • Reserva de cita de visa: antes de elegir el espacio.
  • Carga de documentos: antes de enviar el archivo.
  • Consulta del estado de la cita: antes de mostrar el estado.
  • Formularios de solicitud: antes de confirmar el envío.

Qué tipo de desafío esperar

El BLS CAPTCHA no es un formato único: aparece como texto distorsionado, expresiones matemáticas, selección de imágenes con una consigna o rompecabezas de texto. Cada variante necesita un código instructions que le dice a CaptchaAI cómo interpretar la imagen.

Resolver el BLS CAPTCHA paso a paso

El flujo son tres pasos: obtener la imagen del portal, enviarla a la API y devolver la respuesta en el mismo formulario.

Paso 1: obtén la imagen del CAPTCHA y las instrucciones

import requests
from bs4 import BeautifulSoup
import base64

session = requests.Session()

# Load the portal page
page = session.get("https://portal.example.gov/appointment")
soup = BeautifulSoup(page.text, "html.parser")

# Find the CAPTCHA image
captcha_img = soup.select_one("img#captcha-image, img.captcha")
captcha_url = captcha_img["src"]

# Download the CAPTCHA image
if captcha_url.startswith("data:"):
    # Base64 encoded inline image
    img_data = captcha_url.split(",")[1]
else:
    # URL-referenced image
    img_response = session.get(captcha_url)
    img_data = base64.b64encode(img_response.content).decode()

Paso 2: envía la imagen a CaptchaAI

import time

def solve_bls_captcha(image_base64, instructions=""):
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": "YOUR_API_KEY",
        "method": "base64",
        "body": image_base64,
        "instructions": instructions,
        "json": 1
    })
    task_id = resp.json()["request"]

    for _ in range(30):
        time.sleep(3)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": "YOUR_API_KEY",
            "action": "get",
            "id": task_id,
            "json": 1
        })
        data = result.json()
        if data["status"] == 1:
            return data["request"]
    raise TimeoutError("BLS solve timed out")

# Solve
captcha_answer = solve_bls_captcha(img_data)

Paso 3: devuelve la respuesta en el formulario

# Find form fields
form_data = {
    "captcha_response": captcha_answer,
    "appointment_type": "visa",
    "location": "embassy-city",
    # ... other form fields
}

# Submit with the same session (cookies preserved)
result = session.post(
    "https://portal.example.gov/appointment/submit",
    data=form_data
)

if "success" in result.text.lower():
    print("Form submitted successfully")

Reutiliza siempre el mismo requests.Session(): las cookies del portal deben viajar intactas con la respuesta.

Diagnóstico de problemas frecuentes

Estos son los fallos más habituales al resolver:

Problema Causa probable Solución
"La sesión expiró" tras resolver Demasiado tiempo entre resolver y enviar Resuelve justo antes de enviar
La imagen del CAPTCHA no carga Falta el header Referer Fija el Referer a la URL del portal
Respuesta correcta pero formulario rechazado Falta el token CSRF o campos ocultos Extrae todos los inputs ocultos del formulario
El portal bloquea tras varios intentos Límite de solicitudes Espacia los intentos y rota la salida de red autorizada
Un CAPTCHA distinto cada vez El portal genera uno nuevo por solicitud Descarga una imagen fresca cada vez

Patrones habituales en portales gubernamentales

Se repiten tres patrones que conviene resolver de antemano.

Patrón 1: formularios de varios pasos

Muchos portales reparten el trámite en varias pantallas y colocan el CAPTCHA en el último paso:

# Step 1: Select service type
session.post(url, data={"service": "passport"})

# Step 2: Fill personal details
session.post(url, data={"name": "...", "dob": "..."})

# Step 3: Select appointment slot
session.post(url, data={"slot": "2026-04-10-09:00"})

# Step 4: Solve CAPTCHA and confirm
captcha_answer = solve_bls_captcha(get_captcha_image(session))
session.post(url, data={"captcha": captcha_answer, "confirm": "true"})

Patrón 2: el CAPTCHA se regenera tras un fallo

Si la respuesta no es válida, el portal genera un CAPTCHA nuevo. Nunca reenvíes la misma respuesta: descarga una imagen fresca en cada intento.

max_attempts = 3
for attempt in range(max_attempts):
    # Get fresh CAPTCHA for each attempt
    captcha_image = get_captcha_image(session)
    answer = solve_bls_captcha(captcha_image)

    result = session.post(submit_url, data={"captcha": answer})
    if "incorrect" not in result.text.lower():
        break
    print(f"Attempt {attempt + 1} — CAPTCHA refreshed, retrying")

Patrón 3: sesiones con tiempo limitado

Los portales cierran la sesión tras unos minutos. Deja un margen de seguridad y renuévala antes de que caduque:

import time

session_start = time.time()
SESSION_TIMEOUT = 600  # 10 minutes typical

def check_session_valid():
    elapsed = time.time() - session_start
    if elapsed > SESSION_TIMEOUT - 60:  # 1 min safety margin
        print("Session expiring — refresh needed")
        return False
    return True

# Before CAPTCHA submission
if not check_session_valid():
    # Start a fresh session
    session = requests.Session()
    session.get(portal_url)
    session_start = time.time()

Cuándo controlar un navegador (JavaScript)

Si el portal renderiza el formulario con JavaScript o valida en el cliente, las solicitudes HTTP no bastan. Controla un navegador con Puppeteer, captura la imagen desde el DOM y escribe la respuesta en el campo:

const puppeteer = require('puppeteer');

async function handleBLSPortal() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto('https://portal.example.gov/appointment');

  // Wait for CAPTCHA to load
  await page.waitForSelector('img#captcha-image');

  // Get CAPTCHA image as base64
  const imgBase64 = await page.evaluate(() => {
    const img = document.querySelector('img#captcha-image');
    const canvas = document.createElement('canvas');
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    return canvas.toDataURL('image/png').split(',')[1];
  });

  // Solve con CaptchaAI
  const answer = await solveBLSCaptcha(imgBase64);

  // Type the answer
  await page.type('#captcha-input', answer);

  // Submit
  await page.click('#submit-button');

  // Wait for result
  await page.waitForNavigation();
}

Preguntas frecuentes

¿Cuánto cuesta resolver BLS CAPTCHA a gran volumen?

CaptchaAI factura por thread concurrente, no por resolución: es un precio mensual predecible en USD. El plan BASIC ($15/mes, 5 threads) cubre volúmenes pequeños; ADVANCE ($90/mes, 50 threads) encaja con varios portales en paralelo. Todos los planes incluyen resoluciones ilimitadas por thread.

¿Qué código instructions debo enviar?

Depende del desafío: para texto distorsionado suele bastar con OCR estándar, y para selección de imágenes o expresiones matemáticas, el parámetro instructions le indica a CaptchaAI qué esperar. Prueba con una muestra real y ajusta la consigna.

¿La sesión caducará antes de que termine la resolución?

No debería si dejas margen: una resolución típica tarda de 5 a 15 segundos y las sesiones duran varios minutos. Pide el CAPTCHA lo más cerca posible del envío y renueva la sesión con el chequeo del Patrón 3.

¿Sirve el mismo flujo para cita previa en España o Latinoamérica?

Sí. Obtener imagen, resolver con la API y devolver la respuesta en la misma sesión es igual para citas de visa, cita previa u otros servicios públicos con BLS CAPTCHA. Entre portales cambia el formulario y la política de sesión, no la resolución del CAPTCHA.

Artículos relacionados

Obtén tu API key de CaptchaAI y resuelve tu primer BLS CAPTCHA con alta tasa de éxito.

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