Tutoriales

Conexión Keep-Alive y HTTP/2 para llamadas API CAPTCHA más rápidas

La forma más barata de acelerar tus llamadas a la API de CaptchaAI no es cambiar de plan ni añadir workers: es dejar de abrir una conexión nueva en cada solicitud. Reutilizar una sola conexión TCP/TLS con keep-alive —y multiplexarla con HTTP/2 cuando resuelves en paralelo— recorta cientos de milisegundos por resolución sin tocar tu lógica de negocio.

Esta guía lo muestra en Python y Node.js con el código exacto, y desglosa las cifras que hay detrás del ahorro para que sepas cuándo el esfuerzo vale la pena y cuándo HTTP/1.1 keep-alive ya te basta.

Qué gana tu pipeline al reutilizar la conexión

Cada resolución no es una sola llamada, sino una tanda: un envío a in.php y varios sondeos a res.php hasta que el token está listo. Una resolución típica de reCAPTCHA v2 son entre 5 y 7 solicitudes HTTP: el envío inicial más 4 a 6 sondeos.

Sin keep-alive, cada una de esas solicitudes vuelve a pagar el handshake TCP y la negociación TLS —entre 100 y 300 ms por conexión—. Con keep-alive, solo la primera paga ese precio completo y el resto reutiliza el canal ya abierto:

Escenario Cálculo de la sobrecarga Total
Sin keep-alive 5 × (TCP ~50 ms + TLS ~100 ms) 750 ms
Con keep-alive 1 × (TCP + TLS) + 4 × (~5 ms) 170 ms

El resultado es un ahorro de ~580 ms por resolución. Con 10.000 resoluciones al día son unas 1,6 horas de latencia que dejas de acumular, y esa cifra crece cuanto más lejos esté tu servidor de los endpoints. Para una agencia en Latinoamérica o España que corre QA de scraping desde una máquina regional, la distancia de red suma latencia en cada salto: reutilizar la conexión hace que ese costo se pague una sola vez. Y como los planes de CaptchaAI se facturan por thread —BASIC arranca en $15/mes con 5 threads—, cada milisegundo que recortas libera antes ese thread para la siguiente tarea.

Python con requests.Session: keep-alive sin configuración extra

La biblioteca requests mantiene la conexión abierta de forma predeterminada en cuanto usas un objeto Session. Reutiliza esa misma sesión para el envío y todos los sondeos:

# keepalive_solver.py
import os
import time
import requests

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")

# Create a session — reuses TCP connections across requests
session = requests.Session()
session.headers.update({"Connection": "keep-alive"})

def solve_captcha(sitekey, pageurl):
    """Solve reCAPTCHA v2 using a persistent connection."""
    # Submit — uses existing connection if available
    resp = session.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

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

    task_id = result["request"]

    # Poll — reuses the same connection
    time.sleep(15)
    for _ in range(25):
        poll = session.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Solve multiple CAPTCHAs reusing the same connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

HTTP/2 en Python con httpx

requests solo habla HTTP/1.1. Para multiplexación real —varios sondeos por una misma conexión sin esperar en fila— cambia a httpx con http2=True:

# http2_solver.py
import os
import time
import httpx

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"

# HTTP/2 client with connection pooling
client = httpx.Client(http2=True, timeout=30.0)

def solve_captcha(sitekey, pageurl):
    """Solve using HTTP/2 multiplexed connections."""
    resp = client.get(f"{BASE_URL}/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

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

    task_id = result["request"]
    time.sleep(15)

    for _ in range(25):
        poll = client.get(f"{BASE_URL}/res.php", params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Multiple solves over a single HTTP/2 connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

client.close()

Node.js: una instancia de Axios con conexiones persistentes

En Node.js el keep-alive no viene activado por defecto: crea agentes http y https con keepAlive: true y pásalos a una instancia de Axios que reutilizas en todas las llamadas. El maxSockets fija cuántas conexiones simultáneas mantiene el pool:

// keepalive_solver.js
const axios = require('axios');
const http = require('http');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';

// Create agents with keep-alive enabled
const httpAgent = new http.Agent({ keepAlive: true, maxSockets: 10 });
const httpsAgent = new https.Agent({ keepAlive: true, maxSockets: 10 });

// Axios instance with persistent connections
const api = axios.create({
  baseURL: 'https://ocr.captchaai.com',
  httpAgent,
  httpsAgent,
  timeout: 30000,
});

async function solveCaptcha(sitekey, pageurl) {
  // Submit — reuses connection
  const submit = await api.get('/in.php', {
    params: {
      key: API_KEY, method: 'userrecaptcha',
      googlekey: sitekey, pageurl, json: '1',
    },
  });

  if (submit.data.status !== 1) throw new Error(submit.data.request);
  const taskId = submit.data.request;

  // Poll — reuses same connection
  await new Promise(r => setTimeout(r, 15000));
  for (let i = 0; i < 25; i++) {
    const poll = await api.get('/res.php', {
      params: { key: API_KEY, action: 'get', id: taskId, json: '1' },
    });

    if (poll.data.status === 1) return poll.data.request;
    if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Timeout');
}

(async () => {
  for (let i = 0; i < 5; i++) {
    const token = await solveCaptcha(
      '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
      'https://www.google.com/recaptcha/api2/demo'
    );
    console.log(`Solve ${i + 1}: ${token.slice(0, 30)}...`);
  }

  // Clean up agents
  httpAgent.destroy();
  httpsAgent.destroy();
})();

HTTP/2 o HTTP/1.1 keep-alive: cuál te conviene

Ambos reutilizan la conexión; la diferencia está en cómo la comparten cuando tienes varias resoluciones en vuelo a la vez.

Característica HTTP/1.1 Keep-Alive HTTP/2
Reutilización de la conexión Sí (secuencial) Sí (multiplexado)
Flujos simultáneos 1 por conexión Hasta 100+ por conexión
Compresión de cabeceras No HPACK
Reducción de latencia ~60% ~70%
Requiere soporte del navegador No No (llamadas API)
Ideal para Resoluciones secuenciales Resoluciones paralelas

La regla práctica es sencilla:

  • Resoluciones secuenciales (un CAPTCHA a la vez): HTTP/1.1 keep-alive ya te da casi todo el ahorro.
  • Resoluciones concurrentes (muchas a la vez): HTTP/2 gana, porque todas comparten una única conexión en lugar de disputarse el pool de sockets.

Cómo dimensionar el pool de conexiones

El tamaño del pool debe seguir a tu nivel de concurrencia real, no a un número al azar:

Resoluciones concurrentes Tamaño de pool recomendado
1–5 5 conexiones
5–20 10 conexiones
20–50 25 conexiones
50–100 50 conexiones
100+ Usa HTTP/2 (1 conexión)

Un pool sobredimensionado desperdicia memoria con sockets ociosos; uno demasiado pequeño obliga a abrir conexiones nuevas y anula el beneficio del keep-alive. Ajústalo a los threads que tienes contratados: no ganas nada con 50 conexiones si tu plan resuelve 15 tareas en paralelo.

Problemas frecuentes y cómo resolverlos

Si activaste el keep-alive y no ves mejora, casi siempre es uno de estos cuatro casos:

Problema Causa Solución
Se cierran conexiones entre sondeos Timeout del servidor o del proxy Sube el timeout de keep-alive por encima de 30 s en la configuración del cliente
Sin mejora de rendimiento Ya usabas keep-alive (predeterminado en algunas librerías) Verifícalo con herramientas de monitoreo de red
Errores de conexión rechazada Pool agotado Aumenta maxSockets o reduce la concurrencia
HTTP/2 no se negocia El servidor no soporta h2 Recurre a HTTP/1.1 keep-alive

Checklist para exprimir el keep-alive

Antes de dar por optimizado tu cliente, repasa estos cuatro puntos:

  • Reutiliza una única Session o cliente para el envío y todos los sondeos, nunca uno por solicitud.
  • Sube el timeout de keep-alive por encima de tu intervalo de sondeo para que la conexión no muera entre llamadas.
  • Dimensiona el pool según los threads que resuelves en paralelo, ni más ni menos.
  • Reserva HTTP/2 para cargas concurrentes; en un flujo secuencial, HTTP/1.1 keep-alive ya basta.

Preguntas frecuentes

¿Cuánta latencia ahorro de verdad con keep-alive?

Depende de tu distancia a los endpoints, pero en una resolución de 5 a 7 solicitudes es habitual recortar ~580 ms frente a abrir una conexión nueva cada vez. Cuanto más lejos esté tu servidor, mayor es el ahorro por sondeo evitado.

¿HTTP/2 me sirve si resuelvo un CAPTCHA a la vez?

Poco. Su multiplexación brilla con resoluciones en paralelo; para un flujo secuencial, HTTP/1.1 keep-alive ya reutiliza la conexión y da prácticamente el mismo tiempo de respuesta.

¿Reutilizar la conexión afecta a la tasa de resolución?

No. El keep-alive solo cambia cómo viajan tus solicitudes por la red: el envío, los sondeos y el token que devuelve res.php son idénticos. Lo que ganas es latencia, no una resolución distinta.

¿Debo cerrar la sesión después de cada lote?

No. Mantén la sesión o el cliente abiertos entre lotes si ejecutas resoluciones periódicas; ciérralos solo al terminar la aplicación. Reabrir en cada lote vuelve a pagar el handshake que intentas evitar.

¿El keep-alive funciona detrás de un proxy?

Sí, siempre que el proxy también mantenga la conexión abierta. Conviene revisar dos cosas antes de darlo por hecho:

  • Que el proxy no cierre el canal entre solicitudes: algunos proxies SOCKS5 lo hacen y anulan la ventaja.
  • Que soporte HTTP/2 si tu cliente lo negocia; de lo contrario, quédate en HTTP/1.1 keep-alive.

Artículos relacionados

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