¿La diferencia práctica? Con reCAPTCHA Grid le pasas a CaptchaAI un sitekey y recibes un token; con BLS CAPTCHA extraes tú mismo cada imagen del DOM, la codificas en base64 y recibes una lista de índices. Ambos se resuelven con la misma API de CaptchaAI, pero el trabajo de integración —y el coste operativo— no se parecen. BLS CAPTCHA es una implementación propia exclusiva de los portales de visado de BLS International; reCAPTCHA es el sistema global de Google.
Por qué BLS CAPTCHA y reCAPTCHA Grid se resuelven de forma distinta
BLS CAPTCHA no tiene sitekey, ni token, ni análisis de riesgo por solicitud: el navegador te muestra un conjunto fijo de imágenes y tú eliges las que encajan con la instrucción. Con CaptchaAI extraes cada imagen del DOM, la codificas en base64 y la envías con el texto; CaptchaAI devuelve los índices y tú los pulsas.
reCAPTCHA Grid invierte el reparto de trabajo: le pasas el googlekey (el sitekey) y la URL, y recibes un token que inyectas en g-recaptcha-response. No extraes imágenes ni pulsas mosaicos; los que reaparecen tras cada clic los gestiona el método de token.
Dónde te encuentras cada uno también marca la diferencia:
- BLS CAPTCHA: solo en los portales de cita de visado de BLS International. Los centros de España reciben mucho flujo de solicitantes latinoamericanos, así que las agencias que hacen QA de sus propios flujos autorizados chocan con él a diario.
- reCAPTCHA Grid: en millones de formularios, donde el método de token lo resuelve en dos líneas.
Como CaptchaAI factura por thread y no por resolución, un mismo plan cubre los dos tipos sin recargos: empieza con el plan BASIC ($15/mes, 5 threads) y amplía threads cuando crezca el volumen.
Comparativa lado a lado: BLS CAPTCHA vs reCAPTCHA Grid
| Característica | BLS CAPTCHA | reCAPTCHA Grid |
|---|---|---|
| Proveedor | BLS International (implementación propia) | |
| Formato | Imágenes separadas (3–9) | Imagen única dividida en cuadrícula (3×3 o 4×4) |
| Mosaicos dinámicos | No: conjunto fijo de imágenes | Sí: aparecen nuevos tras cada selección |
| Análisis de comportamiento | Mínimo | Amplio (ratón, timing, IP) |
| Sistema de puntuación | Ninguno | Análisis de riesgo en cada solicitud |
| Método de API | method=bls |
method=userrecaptcha |
| Parámetros necesarios | instructions, image_base64_1..9 |
googlekey, pageurl |
| Formato de respuesta | Índices de imágenes (p. ej. 1,3,5) |
Cadena de token |
| Resolución por token | No: se resuelven las imágenes directamente | Sí: el método de token gestiona la cuadrícula |
| Navegador necesario | Sí (extraer imágenes del DOM) | Opcional (el token funciona sin navegador) |
| Dónde se usa | Solo portales de cita de visado BLS | Millones de sitios en todo el mundo |
| Tiempo típico de resolución | 5–15 segundos | 10–30 segundos |
Cómo resolver BLS CAPTCHA con CaptchaAI
El flujo con BLS es siempre el mismo:
- Lee el texto de la instrucción en la página.
- Extrae cada imagen del DOM y conviértela a base64.
- Envía las imágenes y la instrucción con
method=bls. - Sondea
res.phphasta recibir los índices (p. ej.1,3,5). - Pulsa esas imágenes en la página en el orden correcto.
Python:
import requests
import base64
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example-bls-site.com/appointment")
# Step 1: Extract instruction text
instruction = driver.find_element(By.CSS_SELECTOR, ".captcha-instruction").text
# Example: "Select all images with a motorcycle"
# Step 2: Extract and encode each image
images = driver.find_elements(By.CSS_SELECTOR, ".captcha-image img")
image_data = {}
for i, img in enumerate(images, 1):
# Get image source and convert to base64
src = img.get_attribute("src")
if src.startswith("data:image"):
b64 = src.split(",")[1]
else:
img_bytes = requests.get(src).content
b64 = base64.b64encode(img_bytes).decode()
image_data[f"image_base64_{i}"] = b64
# Step 3: Submit to CaptchaAI
payload = {
"key": "YOUR_API_KEY",
"method": "bls",
"instructions": instruction,
**image_data
}
resp = requests.post("https://ocr.captchaai.com/in.php", data=payload)
task_id = resp.text.split("|")[1]
# Step 4: Poll for result
for _ in range(30):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
indices = result.text.split("|")[1] # e.g., "1,3,5"
break
# Step 5: Click the correct images
for idx in indices.split(","):
images[int(idx) - 1].click()
time.sleep(0.3) # Small delay between clicks
Node.js:
const axios = require("axios");
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto("https://example-bls-site.com/appointment");
// Extract instruction text
const instruction = await page.$eval(
".captcha-instruction",
(el) => el.textContent,
);
// Extract images as base64
const imageElements = await page.$$(".captcha-image img");
const imageData = {};
for (let i = 0; i < imageElements.length; i++) {
const src = await imageElements[i].evaluate((el) => el.src);
let b64;
if (src.startsWith("data:image")) {
b64 = src.split(",")[1];
} else {
const resp = await axios.get(src, { responseType: "arraybuffer" });
b64 = Buffer.from(resp.data).toString("base64");
}
imageData[`image_base64_${i + 1}`] = b64;
}
// Submit to CaptchaAI
const formData = new URLSearchParams({
key: "YOUR_API_KEY",
method: "bls",
instructions: instruction,
...imageData,
});
const submitResp = await axios.post(
"https://ocr.captchaai.com/in.php",
formData.toString(),
);
const taskId = submitResp.data.split("|")[1];
// Poll for result
let indices;
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: "YOUR_API_KEY", action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
indices = result.data.split("|")[1];
break;
}
}
// Click correct images
for (const idx of indices.split(",")) {
await imageElements[parseInt(idx) - 1].click();
await new Promise((r) => setTimeout(r, 300));
}
await browser.close();
})();
Cómo resolver reCAPTCHA Grid con CaptchaAI
reCAPTCHA usa un token: no hace falta extraer imágenes. Le pasas el sitekey y la pageurl, sondeas hasta recibir el token e inyéctalo en el campo oculto.
Python:
import requests
import time
# Step 1: Extract sitekey from page
# <div class="g-recaptcha" data-sitekey="6Le-wvkS..."></div>
sitekey = "6Le-wvkSAAAAAPBMRTvw..."
page_url = "https://example.com/form"
# Step 2: Submit to CaptchaAI
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Step 3: Poll for token
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
# Step 4: Inject token (no clicking needed)
# Option A: Hidden field injection
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# Option B: Pure HTTP submission
requests.post(page_url, data={"g-recaptcha-response": token, "other_field": "value"})
Node.js:
const axios = require("axios");
async function solveRecaptchaGrid(sitekey, pageUrl) {
// Submit
const submitResp = await axios.get("https://ocr.captchaai.com/in.php", {
params: {
key: "YOUR_API_KEY",
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
},
});
const taskId = submitResp.data.split("|")[1];
// Poll for token
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: "YOUR_API_KEY", action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
return result.data.split("|")[1];
}
}
throw new Error("Solve timed out");
}
Complejidad de integración: BLS frente a reCAPTCHA Grid
| Aspecto | BLS | reCAPTCHA Grid |
|---|---|---|
| Extracción de imágenes | Hay que extraer cada imagen del DOM a mano | No hace falta: lo gestiona el método de token |
| Manejo de instrucciones | Hay que leer el texto de la instrucción en la página | No hace falta |
| Codificación base64 | Obligatoria para cada imagen | No hace falta |
| Aplicar la solución | Pulsar cada imagen según los índices devueltos | Inyectar el token en un campo oculto o por HTTP POST |
| Automatización del navegador | Obligatoria: no hay alternativa headless | Opcional: puedes usar solicitudes HTTP puras |
| Recuperación ante errores | Volver a extraer las imágenes | Volver a pedir el token |
| Resolución concurrente | Limitada: las imágenes dependen de la sesión del navegador | Fácil: las solicitudes de token no tienen estado |
| Líneas de código (típico) | 40–60 líneas | 15–25 líneas |
Qué método elegir en cada escenario
- Reserva de cita de visado BLS: usa
method=blscon extracción de imágenes. - Cualquier sitio con reCAPTCHA: usa
method=userrecaptchacon elsitekey. - Sitio BLS con reCAPTCHA integrado: comprueba cuál protege la acción; a veces conviven los dos.
- CAPTCHA de imagen desconocido: confirma primero si es de BLS; si no, prueba los métodos reCAPTCHA u OCR.
Solución de problemas al resolver cada tipo
En BLS:
- Respuesta incorrecta: revisa que el texto de la instrucción coincida con el de la página.
- Las imágenes no cargan: añade
User-Agenty cookies al descargar las URL de imagen. - Token rechazado: pulsa los índices en el orden correcto en la página.
- Resolución lenta: envía solo las imágenes visibles.
En reCAPTCHA Grid:
- Respuesta incorrecta: verifica que el
sitekeyy lapageurlsean correctos. - Token rechazado: inyéctalo en
g-recaptcha-responsey ejecuta el callback. - Resolución demasiado lenta: usa un proxy cercano al sitio de destino.
Preguntas frecuentes
¿Por qué BLS necesita un navegador y reCAPTCHA no?
Porque BLS te entrega las imágenes en el DOM y espera que pulses las correctas: sin navegador no puedes extraerlas ni aplicar la respuesta. reCAPTCHA Grid se resuelve con un token, así que basta con solicitudes HTTP puras.
¿Qué plan de CaptchaAI conviene para resolver BLS y reCAPTCHA a volumen?
Depende de cuántas resoluciones simultáneas necesites, no del tipo de CAPTCHA: CaptchaAI factura por thread con resoluciones ilimitadas. El plan BASIC ($15/mes, 5 threads) sirve para empezar y puedes subir a STANDARD ($30/mes, 15 threads) cuando el volumen crezca.
¿Puedo reutilizar el token de reCAPTCHA Grid en varias solicitudes?
No conviene: cada token es de un solo uso y caduca en unos dos minutos, así que pide uno nuevo por envío. En BLS ni siquiera hay token, solo índices ligados a ese conjunto de imágenes.
¿Cambia el código si el sitio BLS muestra 3 imágenes en vez de 9?
No. El bucle recorre las imágenes que haya en el DOM y las numera image_base64_1..n, sea cual sea la cantidad; solo envía todas las visibles y respeta el orden de los índices al pulsar.