¿Automatizar una cita de visa en un centro BLS, consultar un expediente judicial o descargar un registro público? El muro casi nunca es el formulario: es el CAPTCHA que salta justo antes de enviarlo. Aquí resuelves las tres familias —BLS, reCAPTCHA v2 y CAPTCHA de imagen— con la API de CaptchaAI y Python.
En el mundo hispanohablante domina el visado BLS, que atiende a toda América Latina, junto con la cita previa en España, el SAT en México o AFIP en Argentina. Todos repiten el patrón: sesión corta, CAPTCHA en el punto crítico y validación de IP entre páginas. Automatiza solo flujos propios o pruebas autorizadas y respeta los términos de servicio y la protección de datos.
Qué CAPTCHA usa cada tipo de portal gubernamental
Saber qué esquema protege cada trámite te dice a qué te enfrentas:
| Categoría del portal | CAPTCHA habitual | Caso de uso |
|---|---|---|
| Visa / inmigración | BLS, reCAPTCHA v2 | Reserva de cita |
| DMV / vehículos | reCAPTCHA v2, imagen | Renovación |
| Registros judiciales | reCAPTCHA v2 | Expedientes |
| Permisos / licencias | Imagen | Solicitudes |
| Portales fiscales | reCAPTCHA v2 | Declaración |
| Registros públicos | Imagen, reCAPTCHA | Propiedades |
- Los portales públicos suelen ir por detrás en tecnología de CAPTCHA.
- Con tres métodos cubres casi todo:
bls,userrecaptchaybase64para imagen.
Gestión de sesiones: conoce el reloj de cada portal
Estos portales imponen tiempos de espera cortos: la sesión caduca justo cuando ibas a enviar. Márgenes típicos:
- Visado: 5-10 minutos; completa el flujo sin pausas.
- DMV: 15 minutos; refresca la cookie a mitad del flujo.
- Registros judiciales: 20-30 minutos; agrupa por lotes.
- Fiscales: 10-15 minutos; proxy fijo, misma IP.
- Permisos: 30 minutos; guarda el progreso.
Automatizar citas de visa en portales BLS
Los portales BLS usan su propio esquema. CaptchaAI lo resuelve con una alta tasa de éxito mediante bls, o con base64 cuando trabajas con la imagen:
import requests
import time
import base64
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_bls_captcha(captcha_image_url, session):
"""Solve BLS-specific CAPTCHA."""
# Download CAPTCHA image
img_resp = session.get(captcha_image_url)
img_b64 = base64.b64encode(img_resp.content).decode()
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "base64",
"body": img_b64,
"json": 1,
})
task_id = resp.json()["request"]
for _ in range(30):
time.sleep(3)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("BLS CAPTCHA timeout")
class BLSAppointmentBooker:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
def login(self, portal_url, email, password):
"""Login to BLS portal with CAPTCHA."""
resp = self.session.get(portal_url)
# Extract CAPTCHA image URL from page
import re
match = re.search(r'src="(/captcha[^"]+)"', resp.text)
if match:
captcha_url = portal_url.rstrip("/") + match.group(1)
captcha_text = solve_bls_captcha(captcha_url, self.session)
else:
captcha_text = ""
login_resp = self.session.post(portal_url, data={
"email": email,
"password": password,
"captcha": captcha_text,
})
return login_resp.status_code == 200
def check_appointment_slots(self, slots_url):
"""Check available appointment slots."""
resp = self.session.get(slots_url)
if resp.status_code == 200:
return resp.json().get("available_slots", [])
return []
def book_slot(self, booking_url, slot_id, applicant_data):
"""Book an appointment slot, handling any CAPTCHA."""
resp = self.session.get(booking_url)
# Check for CAPTCHA on booking page
import re
match = re.search(r'src="(/captcha[^"]+)"', resp.text)
if match:
captcha_url = booking_url.rstrip("/") + match.group(1)
captcha_text = solve_bls_captcha(captcha_url, self.session)
else:
captcha_text = ""
resp = self.session.post(booking_url, data={
"slot_id": slot_id,
"captcha": captcha_text,
**applicant_data,
})
return {
"success": resp.status_code == 200,
"confirmation": resp.json().get("confirmation_number"),
}
El patrón se repite: descargas la imagen desde la sesión, la envías a in.php, sondeas res.php y adjuntas el texto resuelto al formulario. La misma Session conserva las cookies de principio a fin.
Consultar expedientes judiciales con reCAPTCHA v2
Los registros judiciales casi siempre esconden un reCAPTCHA v2. No hay imagen: resuelves un token con userrecaptcha, lo adjuntas como g-recaptcha-response y envías la búsqueda.
def solve_recaptcha(sitekey, pageurl):
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Timeout")
class CourtRecordSearcher:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
def search_cases(self, court_url, search_params, sitekey):
"""Search court records with reCAPTCHA handling."""
# Load search page
self.session.get(court_url)
# Solve CAPTCHA
token = solve_recaptcha(sitekey, court_url)
# Submit search with token
resp = self.session.post(court_url, data={
**search_params,
"g-recaptcha-response": token,
})
if resp.status_code == 200:
return self._parse_results(resp.text)
return []
def _parse_results(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
cases = []
for row in soup.select("table.results tr")[1:]:
cols = row.select("td")
if len(cols) >= 4:
cases.append({
"case_number": cols[0].get_text(strip=True),
"parties": cols[1].get_text(strip=True),
"date": cols[2].get_text(strip=True),
"status": cols[3].get_text(strip=True),
})
return cases
- Lees el
sitekeyuna sola vez del HTML de la página. - Si el tribunal exige una IP estable, pasa un
proxyal constructor.
CAPTCHA de imagen en portales de permisos y licencias
Muchos portales municipales se quedan en el CAPTCHA de imagen clásico: texto distorsionado que la API resuelve por OCR. El método vuelve a ser base64, sin reserva de cita:
def solve_image_captcha(image_url, session):
"""Solve image-based CAPTCHA common on local government sites."""
img = session.get(image_url)
img_b64 = base64.b64encode(img.content).decode()
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "base64",
"body": img_b64,
"json": 1,
})
task_id = resp.json()["request"]
for _ in range(20):
time.sleep(3)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Image CAPTCHA timeout")
Consultas por lotes en registros públicos
Para revisar muchos registros de una tanda, resuelve un token, reutilízalo mientras sea válido y deja un intervalo entre solicitudes:
import csv
def batch_property_lookup(addresses, portal_url, sitekey, output_file):
"""Look up multiple property records, solving CAPTCHA per batch."""
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
results = []
for i, address in enumerate(addresses):
try:
# Solve CAPTCHA every 5th request (or when required)
if i % 5 == 0:
token = solve_recaptcha(sitekey, portal_url)
resp = session.post(portal_url, data={
"address": address,
"g-recaptcha-response": token,
})
if resp.status_code == 200:
results.append({
"address": address,
"data": resp.json(),
})
time.sleep(3) # Be respectful
except Exception as e:
results.append({"address": address, "error": str(e)})
# Save results
with open(output_file, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["address", "data", "error"])
writer.writeheader()
writer.writerows(results)
return results
- Resolver el token cada cinco solicitudes recorta el gasto sin que caduque a mitad del lote.
- CaptchaAI factura por thread, no por resolución: un hilo del plan BASIC ($15/mes, 5 threads) basta para lotes moderados.
Errores frecuentes y cómo resolverlos
La causa número uno de fallos no es el CAPTCHA, sino el desajuste de tiempos: el token se resuelve, pasan los segundos y el servidor lo rechaza. Resuelve lo más cerca posible del POST. Tropiezos habituales:
| Problema | Causa | Solución |
|---|---|---|
| La imagen no carga | Cookie caducada | Inicia sesión nueva |
| "Sesión expirada" en el formulario | Tardaste en resolver | Resuelve por adelantado |
| Respuesta incorrecta | Imagen distorsionada | Repórtala por la API |
| El portal bloquea la automatización | Detección de IP/UA | Red autorizada y UA real |
| Validación falla tras el CAPTCHA | Token caducado en el servidor | Resuelve justo antes de enviar |
Preguntas frecuentes
¿CaptchaAI resuelve el CAPTCHA de los portales BLS?
Sí. CaptchaAI resuelve el BLS CAPTCHA con una alta tasa de éxito usando method=bls para resolución directa, o method=base64 con la imagen del desafío.
¿Cuánto cuesta resolver el CAPTCHA de estos portales?
CaptchaAI cobra por thread, no por resolución, con resoluciones ilimitadas al mes. El plan BASIC ($15/mes, 5 threads) cubre QA y consultas moderadas.
¿Qué hago si la sesión expira antes de enviar el formulario?
Resuelve el CAPTCHA justo antes del POST y mantén viva la cookie con la misma requests.Session. Si el portal caduca en minutos, precarga el formulario y deja la resolución para el final.
Guías relacionadas
- Resolver BLS CAPTCHA con la API
- Resolver CAPTCHA de imagen con la API
- Mantener la sesión del navegador
Siguientes pasos
- Inicio rápido de CaptchaAI en 5 minutos
- Resolver reCAPTCHA v2 con la API
- Resolver Cloudflare Turnstile con la API
- Resolver GeeTest v3 con la API