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
- Resolver BLS CAPTCHA paso a paso
- Resolver BLS CAPTCHA con Node.js
Obtén tu API key de CaptchaAI y resuelve tu primer BLS CAPTCHA con alta tasa de éxito.