Tutoriales de API

Cómo resolver BLS CAPTCHA paso a paso

Para resolver un BLS CAPTCHA por API necesitas tres cosas: las imágenes de la cuadrícula en Base64, el texto de la instrucción que dice qué seleccionar, y una llamada al método bls de CaptchaAI que te devuelve los índices correctos. Con esos índices, tu script hace clic en las imágenes y envía el formulario.

El BLS CAPTCHA aparece en los portales de citas de BLS International, el intermediario que tramita las solicitudes de visado de decenas de consulados y que recibe un enorme flujo de solicitantes latinoamericanos. Cuando automatizas la vigilancia de disponibilidad de un flujo que tú administras, este desafío es la barrera que interrumpe cada sesión: muestra entre tres y nueve imágenes y pide seleccionar las que coinciden con una frase como "selecciona todas las imágenes con un automóvil". Se parece a la cuadrícula de reCAPTCHA, pero usa imágenes propias e instrucciones personalizadas, así que no puedes reutilizar tal cual un solver genérico de reCAPTCHA.

El recorrido completo son cuatro etapas encadenadas:

  1. Extraer las imágenes y el texto de la instrucción de la página.
  2. Enviar todo a CaptchaAI con el método bls.
  3. Sondear el resultado hasta recibir los índices correctos.
  4. Hacer clic en esas imágenes y enviar el formulario.

Qué necesitas antes de empezar

Elemento Valor
Clave API de CaptchaAI Desde tu panel en captchaai.com
Imágenes del BLS CAPTCHA Codificadas en Base64 desde la página
Texto de instrucciones La frase que indica qué imágenes seleccionar
Entorno Python 3.7+ o Node.js 14+

Un par de detalles antes del código:

  • CaptchaAI resuelve el BLS CAPTCHA de forma nativa con el método bls, junto a reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3 y desafíos de imagen y texto.
  • La facturación es por threads con resoluciones ilimitadas: el plan BASIC ($15/mes, 5 threads) cubre un flujo de citas individual y puedes escalar cuando vigiles varios portales a la vez.

Paso 1: extrae las imágenes y la instrucción de la página

El BLS CAPTCHA muestra normalmente entre 3 y 9 imágenes con una instrucción de texto, por ejemplo "Selecciona todas las imágenes con un automóvil". En esta etapa capturas dos cosas de la página:

  • El texto de la instrucción, que viajará en el campo instructions.
  • Cada imagen convertida a Base64, sin el prefijo data:image/...;base64,.

Con Selenium

from selenium import webdriver
from selenium.webdriver.common.by import By
import base64
import requests as req

driver = webdriver.Chrome()
driver.get("https://blsitalypakistan.com/appointment")

# Get instruction text
instruction = driver.find_element(By.CSS_SELECTOR, ".captcha-instruction").text
print(f"Instruction: {instruction}")

# Get all captcha images as base64
images = {}
captcha_imgs = driver.find_elements(By.CSS_SELECTOR, ".captcha-image img")
for i, img in enumerate(captcha_imgs, 1):
    src = img.get_attribute("src")
    if src.startswith("data:image"):
        # Already base64
        images[f"image_base64_{i}"] = src.split(",")[1]
    else:
        # Download and encode
        img_data = req.get(src).content
        images[f"image_base64_{i}"] = base64.b64encode(img_data).decode()

Con Puppeteer

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.goto('https://blsitalypakistan.com/appointment');

// Get instruction
const instruction = await page.$eval('.captcha-instruction', el => el.textContent);

// Get images as base64
const images = await page.$$eval('.captcha-image img', imgs =>
  imgs.map((img, i) => ({
    key: `image_base64_${i + 1}`,
    value: img.src.startsWith('data:') ? img.src.split(',')[1] : null
  }))
);

Paso 2: envía las imágenes a CaptchaAI

Reúne el texto de instrucciones y todas las imágenes en un mismo payload y envíalo al endpoint in.php con el método bls. La respuesta trae un task_id que necesitarás para consultar el resultado.

Python

import requests
import time

API_KEY = "YOUR_API_KEY"

payload = {
    "key": API_KEY,
    "method": "bls",
    "instructions": instruction,
    "json": 1
}

# Add each image (up to 9)
for key, value in images.items():
    payload[key] = value

response = requests.post("https://ocr.captchaai.com/in.php", data=payload)
data = response.json()

if data.get("status") != 1:
    raise Exception(f"Submit error: {data.get('request')}")

task_id = data["request"]
print(f"Task submitted: {task_id}")

Node.js

const axios = require('axios');
const FormData = require('form-data');

async function submitBLS(instruction, images) {
  const params = {
    key: 'YOUR_API_KEY',
    method: 'bls',
    instructions: instruction,
    json: 1,
    ...Object.fromEntries(images.map(img => [img.key, img.value]))
  };

  const { data } = await axios.post('https://ocr.captchaai.com/in.php', null, { params });
  if (data.status !== 1) throw new Error(data.request);
  return data.request;
}

Paso 3: consulta el resultado con sondeo

El solver no responde al instante: hay que sondear el endpoint res.php cada pocos segundos hasta que el estado sea 1. Al terminar, devuelve los índices de las imágenes correctas en formato "1,3,5".

Python

def get_bls_solution(task_id):
    for _ in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1
        }).json()

        if result.get("status") == 1:
            return result["request"]  # e.g., "1,3,5" (image indices)
        if result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {result.get('request')}")

    raise Exception("Timeout")

solution = get_bls_solution(task_id)
print(f"Select images: {solution}")  # e.g., "1,3,5"

Recibir CAPCHA_NOT_READY en las primeras vueltas es normal: significa que el desafío sigue en la cola. Cualquier otra respuesta distinta sí debes tratarla como error.

Paso 4: haz clic en las imágenes y envía el formulario

Con la lista de índices, recorre los elementos de la cuadrícula y haz clic en los que corresponden. La API numera desde 1, así que resta uno para el índice base cero del navegador.

# Parse the solution indices
selected = [int(i) for i in solution.split(",")]

# Click each correct image
captcha_imgs = driver.find_elements(By.CSS_SELECTOR, ".captcha-image img")
for idx in selected:
    captcha_imgs[idx - 1].click()  # Convert 1-based to 0-based
    time.sleep(0.3)  # Small delay between clicks

# Submit the form
driver.find_element(By.CSS_SELECTOR, ".captcha-submit").click()

Errores frecuentes y cómo resolverlos

Antes de juntar todo en un solo script, conviene reconocer los fallos que más aparecen en producción:

Error Causa Qué hacer
ERROR_BAD_PARAMETERS Faltan las instrucciones o las imágenes Incluye tanto el texto de la instrucción como al menos una imagen
ERROR_CAPTCHA_UNSOLVABLE Imágenes borrosas o irreconocibles Captura imágenes de mayor calidad y verifica que la codificación Base64 sea correcta
Imágenes incorrectas seleccionadas Orden de imágenes equivocado Numera las imágenes en el orden real de visualización
Selección rechazada Las imágenes cambiaron tras la extracción Extrae y envía las imágenes de inmediato, en la misma sesión

Ejemplo completo en Python

Este script encadena las cuatro etapas —extraer, enviar, sondear y hacer clic— en un flujo continuo.

import requests
import time
import base64
from selenium import webdriver
from selenium.webdriver.common.by import By

API_KEY = "YOUR_API_KEY"
driver = webdriver.Chrome()
driver.get("https://blsitalypakistan.com/appointment")

# 1. Extract instruction and images
instruction = driver.find_element(By.CSS_SELECTOR, ".captcha-instruction").text
captcha_imgs = driver.find_elements(By.CSS_SELECTOR, ".captcha-image img")

payload = {"key": API_KEY, "method": "bls", "instructions": instruction, "json": 1}
for i, img in enumerate(captcha_imgs, 1):
    src = img.get_attribute("src")
    if src.startswith("data:image"):
        payload[f"image_base64_{i}"] = src.split(",")[1]

# 2. Submit to CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data=payload).json()
task_id = resp["request"]

# 3. Poll for solution
for _ in range(30):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY, "action": "get", "id": task_id, "json": 1
    }).json()
    if result.get("status") == 1:
        selected = [int(i) for i in result["request"].split(",")]
        break

# 4. Click correct images and submit
for idx in selected:
    captcha_imgs[idx - 1].click()
    time.sleep(0.3)
driver.find_element(By.CSS_SELECTOR, ".captcha-submit").click()

print("CAPTCHA solved!")
driver.quit()

Automatiza solo flujos de citas que tú administras y respeta los términos de servicio del portal y la normativa de protección de datos aplicable (GDPR y LOPDGDD en España, LFPDPPP en México y normas equivalentes en la región).

Proyecto ejecutable completo

¿Quieres un proyecto funcional con configuración del entorno, sondeo, reintentos y manejo de errores ya resueltos? El repositorio de ejemplos incluye todo listo para clonar y ejecutar.

Consulta el ejemplo ejecutable completo en GitHub →

Preguntas frecuentes

¿La API de CaptchaAI resuelve el BLS CAPTCHA de cualquier centro de visas?

Sí. El método bls trabaja sobre las imágenes y el texto que le envías, no sobre la URL, así que no depende del consulado ni del país concretos. Tú te encargas de la extracción y la API resuelve la cuadrícula.

¿Por qué se rechaza mi selección aunque los índices sean correctos?

Casi siempre porque las imágenes cambiaron entre la extracción y el envío. El BLS CAPTCHA regenera la cuadrícula por sesión, así que extrae, resuelve y haz clic en un único ciclo sin recargar la página. Si tardas demasiado, la instrucción ya apunta a otras imágenes.

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

CaptchaAI factura por threads con resoluciones ilimitadas dentro del mes, no por CAPTCHA resuelto. El plan BASIC ($15/mes, 5 threads) cubre un flujo individual; si vigilas varios portales en paralelo, STANDARD ($30/mes, 15 threads) te da más resoluciones simultáneas.

¿Necesito Selenium o me basta con solicitudes HTTP?

Para la parte de resolución no necesitas Selenium. Si consigues leer las imágenes y la instrucción con solicitudes HTTP directas, la API solo requiere las imágenes en Base64 y el texto. Selenium sigue siendo útil cuando la página arma la cuadrícula con JavaScript y hace falta un navegador real para renderizarla.

Guías relacionadas

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