Sin KYC — sin ID, sin selfie, sin documentos. Paga con criptomonedas: BTC, USDT, USDC, ETH, SOL, LTC
Idioma: Español
Comienza ahora

Docs · concurrencia · rendimiento · cortesía

Concurrencia y rendimiento a través de proxies residenciales

La pasarela factura por GB, no por hilo, por lo que tu límite real es cada sitio objetivo. Dimensiona la concurrencia según el rendimiento que necesitas, pon un límite por host y deja que las respuestas te indiquen cuándo desacelerar.

Última actualización: · 6 minutos de lectura

Respuesta rápida

¿Cuántas solicitudes concurrentes puedo ejecutar a través de proxies residenciales?

Las que tolere cada objetivo: CrawlRelay cobra tráfico residencial por GB (0,50 US$/GB desde 50 GB), no por hilo o conexión. Dimensiona la concurrencia con la ley de Little: solicitudes en vuelo = páginas por segundo × segundos por página, luego pon un límite por host, empezando con 2 a 4. Redúcelo cuando aparezcan respuestas 429 o 503. Se paga con criptomonedas, sin KYC.

Concurrencia de un vistazo

FacturaciónPor GB de tráfico; no se factura por hilos ni conexiones
Regla para dimensionarEn vuelo = rendimiento × latencia (ley de Little)
Punto de partida por host2–4 solicitudes paralelas; 1 con retraso para sitios pequeños
Señales para desacelerar429, 503, tiempos de respuesta crecientes, páginas de desafío
Cálculo de ancho de bandaPáginas por segundo × bytes por página × 3.600 = bytes por hora
Respuesta media residencial0,93 s en la red proxy, 3,21 s en objetivos reales (Proxyway 2026)

¿Cómo dimensiono la concurrencia según el rendimiento que necesito?

Usa la ley de Little: el número de solicitudes en vuelo es igual a la tasa que deseas multiplicada por el tiempo que tarda cada solicitud. Proxyway's Proxy Market Research 2026 midió una media de 3,21 segundos por solicitud en objetivos reales a través de proxies residenciales, así que planifica con 2 a 4 segundos para sitios reales, no con la cifra inferior a un segundo de la red sola.

MetaTiempo por solicitudSolicitudes en vuelo
5 páginas por segundo2 s10
20 páginas por segundo2 s40
20 páginas por segundo4 s80
100 páginas por segundo3 s300

Luego distribuye esas solicitudes entre hosts. Cuarenta solicitudes en vuelo repartidas en 200 sitios es suave; cuarenta en un sitio pequeño es una prueba de carga que nunca aceptó.

¿Cuánto ancho de banda consume ese rendimiento?

Multiplica páginas por segundo por bytes por página. A 20 páginas HTML por segundo y 50 KB por página, el rastreo mueve 1 MB por segundo, que son 3,6 GB por hora y unos 86 GB por día. A 2 MB por página renderizada, la misma tasa movería 40 MB por segundo.

Multiplica el resultado por el precio por GB de tu plan, 0,50 US$/GB desde 50 GB a CrawlRelay, para obtener el costo por hora. La guía del calculador de ancho de banda ofrece pesos típicos según el tipo de página.

¿Con qué límites por host debería comenzar?

ObjetivoSolicitudes paralelas por hostRetraso entre solicitudesNotas
Sitio pequeño (blog, tienda local)12–5 sRespeta Crawl-delay en robots.txt si está presente
Sitio mediano2–40.5–2 sVigila los tiempos de respuesta; reduce la velocidad cuando se dupliquen
Gran plataforma con CDN4–16AutoThrottle o adaptativoAumenta solo mientras las tasas de 429 y 5xx se mantengan constantes
API públicaEl límite documentadoComo se documentaUsa la clave API y los límites que te proporciona el proveedor

¿Cómo adapto la concurrencia automáticamente?

Usa aumento aditivo y disminución multiplicativa, la regla que usa TCP para congestión: añade un espacio tras una serie de respuestas limpias, reduce a la mitad el límite ante un 429 o 503. El limitador siguiente mantiene un límite por host, pausa cada solicitud a ese host por el retraso Retry-After, reintenta una vez, y nunca supera un techo que configures. Los errores de red regresan como valores, así un timeout no detiene el lote.

Python asyncio: límite adaptativo con httpx
import asyncio
import random
from urllib.parse import urlsplit

import httpx

PROXY = "http://USERNAME-country-us:[email protected]:7777"


class AdaptiveLimit:
    """One per host: +1 slot after 20 clean responses, halve on 429/503, pause for Retry-After."""

    def __init__(self, start=2, low=1, high=16):
        self.limit, self.low, self.high = start, low, high
        self.in_flight, self.clean = 0, 0
        self.pause_until = 0.0
        self.cond = asyncio.Condition()

    async def __aenter__(self):
        loop = asyncio.get_running_loop()
        while True:
            async with self.cond:
                await self.cond.wait_for(lambda: self.in_flight < self.limit)
                delay = self.pause_until - loop.time()
                if delay <= 0:
                    self.in_flight += 1
                    return self
            await asyncio.sleep(delay)  # the host asked for a pause: wait outside the lock

    async def __aexit__(self, *exc):
        async with self.cond:
            self.in_flight -= 1
            self.cond.notify_all()

    def record(self, status, retry_after=None):
        if status in (429, 503):
            self.limit, self.clean = max(self.low, self.limit // 2), 0
            wait = int(retry_after) if retry_after and retry_after.isdigit() else 5 + random.random()
            now = asyncio.get_running_loop().time()
            self.pause_until = max(self.pause_until, now + wait)
        elif status < 400:
            self.clean += 1
            if self.clean >= 20 and self.limit < self.high:
                self.limit, self.clean = self.limit + 1, 0


gates = {}


def gate_for(url):
    host = urlsplit(url).hostname
    if host not in gates:
        gates[host] = AdaptiveLimit()
    return gates[host]


async def fetch(client, url, attempts=2):
    gate = gate_for(url)
    status = None
    for _ in range(attempts):
        try:
            async with gate:
                r = await client.get(url)
        except httpx.HTTPError as exc:
            return "error: %s" % type(exc).__name__
        status = r.status_code
        gate.record(status, r.headers.get("Retry-After"))
        if status not in (429, 503):
            break  # the retry, if any, waits for the host's pause in __aenter__
    return status


async def main(urls):
    timeout = httpx.Timeout(30.0, connect=10.0)
    async with httpx.AsyncClient(proxy=PROXY, timeout=timeout) as client:
        print(await asyncio.gather(*(fetch(client, u) for u in urls)))
    print({host: gate.limit for host, gate in gates.items()})


asyncio.run(main(["https://example.com/"] * 10))

¿Qué ralentiza un rastreo con proxy además del objetivo?

  • Handshakes TLS. Una conexión nueva por solicitud, necesaria para una IP nueva cada vez, añade una negociación con el sitio en cada vez. Mantén sesión pegajosa con keep-alive para páginas del mismo sitio cuando la diversidad de IP no importe.
  • Salidas lentas. Las salidas residencial y móvil son conexiones reales de hogar y celular. Usa timeouts y reintenta con nueva conexión en lugar de esperar.
  • Objetivo restringido. Una ciudad pequeña o un ASN único tiene menos salidas que un país. Apunta estrictamente donde los datos cambian.
  • Renderizado. Un navegador sin cabeza consume mucho más CPU, memoria y tráfico por página que un cliente HTTP. Renderiza solo las páginas que requieren JavaScript.
  • DNS. Con socks5h:// o el puerto HTTP, el DNS se resuelve en la salida; no necesitas caché local para resolver los hosts objetivo.

Preguntas sobre concurrencia

¿CrawlRelay limita el número de hilos o conexiones?

Los planes se facturan por GB de tráfico, no por hilo, conexión o solicitud, y los planes publicados no establecen límite de hilos. Los límites prácticos son la tolerancia de cada objetivo y tu propia máquina. Si planeas un rastreo muy grande, escribe primero a [email protected] para que podamos verificar la cobertura según tu objetivo.

¿Por qué mi rastreo se volvió más lento al añadir más hilos?

Normalmente porque el objetivo empezó a limitarte: suben los tiempos de respuesta, aparecen respuestas 429 o 503, y los reintentos añaden más carga. Otra causa común es que tu máquina se quede sin CPU o sockets, especialmente con navegadores sin cabeza. Mide la latencia y tasa de errores por host antes de añadir hilos.

¿Una conexión por solicitud es más lenta que keep-alive?

Sí, implica un handshake TCP y TLS por solicitud, normalmente unos cientos de milisegundos a través de una salida residencial. Ese es el costo de una IP nueva en cada solicitud. Para muchas páginas de un mismo sitio donde la IP no importa, una sesión pegajosa con keep-alive es más rápida y usa menos tráfico.

¿Cómo respeto el crawl-delay de robots.txt en un rastreador concurrente?

Analiza robots.txt una vez por host, guárdalo en caché hasta 24 horas como sugiere RFC 9309, y convierte un valor Crawl-delay en un intervalo mínimo entre solicitudes por host con concurrencia 1. El urllib.robotparser de Python lo expone vía crawl_delay().

Escala con precios por GB

0,50 US$/GB de 50 GB a 1 TB, tráfico que nunca expira.

Desde 0,50 US$/GB · sin KYC

Comienza ahora