Volver al blog

Qué hacer si el proxy se bloquea constantemente: guía completa de diagnóstico y solución de problemas

Analizamos las razones del bloqueo de proxies y proporcionamos soluciones prácticas: desde la rotación correcta hasta la configuración de la huella digital del navegador.

📅15 de diciembre de 2025

Qué hacer si los proxies se banean constantemente: guía completa de diagnóstico y solución de problemas

Los bloqueos constantes de proxies son uno de los problemas más frecuentes al hacer web scraping, automatización y trabajar con múltiples cuentas. En este artículo analizaremos por qué sucede esto y cómo resolver el problema de manera sistemática, en lugar de cambiar proveedores infinitamente esperando un milagro.

Por qué realmente se banean los proxies

Antes de buscar soluciones, necesitas entender la mecánica de los bloqueos. Los sistemas antifraude modernos utilizan protección multinivel, y el bloqueo de proxies es solo una consecuencia, no la causa. Comprender cómo funcionan estos sistemas te permite construir una estrategia efectiva de evasión.

Reputación de IP y listas negras

Cada dirección IP tiene una reputación que se forma basándose en el historial de su uso. Si una dirección se utilizó anteriormente para spam, ataques DDoS o web scraping masivo, termina en bases de datos como Spamhaus, SORBS o listas propietarias de servicios específicos. Cuando te conectas a través de tal IP, el sistema inmediatamente te trata con sospecha.

Los proxies de centros de datos son especialmente propensos a este problema. Subredes completas pueden estar marcadas como "hosting", y cualquier tráfico desde ellas recibe automáticamente un nivel de verificación elevado. Amazon AWS, Google Cloud, DigitalOcean — sus rangos de IP son bien conocidos y frecuentemente bloqueados de manera preventiva.

Puedes verificar la reputación de una IP a través de servicios como IPQualityScore, Scamalytics o AbuseIPDB. Si tu proxy muestra una puntuación de fraude superior a 75, el problema está exactamente aquí — cambia de proveedor o tipo de proxy.

Patrones de solicitudes

Un humano no realiza 100 solicitudes por segundo. Un humano no navega por páginas con una periodicidad perfecta de 2 segundos. Un humano no ignora imágenes, CSS y JavaScript, solicitando solo HTML. Los sistemas antifraude analizan exactamente estos patrones, y cualquier desviación del comportamiento "humano" aumenta el riesgo de bloqueo.

Especialmente reveladora es la estadística del tiempo entre solicitudes. Si tienes un intervalo estable — es un signo evidente de automatización. Agregar un retraso aleatorio (por ejemplo, de 1 a 5 segundos) reduce significativamente la probabilidad de detección.

Inconsistencia de metadatos

Cuando tu User-Agent dice que usas Chrome en Windows, pero los encabezados HTTP revelan características de Python requests — es una bandera roja. Cuando la dirección IP se geolocaliza en Alemania, pero la configuración de idioma del navegador indica ruso — otra bandera roja. Cuando la zona horaria en JavaScript no coincide con la geografía de la IP — una tercera bandera.

La acumulación de tales inconsistencias hace que el sistema clasifique la conexión como sospechosa y aplique medidas de protección: desde captchas hasta bloqueo completo de IP.

Huella digital del navegador

Los sistemas de protección modernos recopilan decenas de parámetros del navegador: resolución de pantalla, fuentes instaladas, complementos, renderizado WebGL, contexto de audio y mucho más. El conjunto de estos parámetros crea una "huella" única que permanece constante incluso cuando cambias de IP.

Si cambias de proxy pero la huella digital permanece igual, el sistema entiende que eres el mismo usuario. Y si una huella digital aparece desde cientos de IPs diferentes en poco tiempo — es un signo evidente de automatización.

Diagnóstico: cómo entender la causa del bloqueo

Antes de cambiar configuraciones al azar, realiza un diagnóstico. Esto te ahorrará horas de experimentación y te ayudará a encontrar la causa real del problema. Un enfoque sistemático del diagnóstico es la clave para una solución efectiva.

Paso 1: Verifica el proxy en sí

Comienza con una verificación básica de la funcionalidad del proxy independientemente de tu script principal:

import requests

proxy = {
    "http": "http://user:pass@proxy-server:port",
    "https": "http://user:pass@proxy-server:port"
}

# Verificación de funcionalidad básica
try:
    response = requests.get("https://httpbin.org/ip", proxies=proxy, timeout=10)
    print(f"IP a través del proxy: {response.json()['origin']}")
except Exception as e:
    print(f"Error de conexión: {e}")

# Verificación de fuga de IP real
response = requests.get("https://browserleaks.com/ip", proxies=proxy)
# Compara con tu IP real

Si el proxy no funciona ni en solicitudes simples — el problema está en el proxy mismo o en las credenciales. Verifica el formato correcto de conexión, la disponibilidad de fondos en la cuenta y los límites del proveedor.

Paso 2: Verifica la reputación de la IP

Usa varios servicios para una evaluación integral:

# Obtén la IP del proxy
proxy_ip = requests.get("https://api.ipify.org", proxies=proxy).text

# Verifica en estos servicios:
# https://www.ipqualityscore.com/free-ip-lookup-proxy-vpn-test
# https://scamalytics.com/ip/{proxy_ip}
# https://www.abuseipdb.com/check/{proxy_ip}
# https://whatismyipaddress.com/ip/{proxy_ip}

print(f"Verifica la IP {proxy_ip} en los servicios anteriores")

Presta atención a los siguientes indicadores: puntuación de fraude (debe ser inferior a 50), tipo de IP (residencial es mejor que centro de datos), presencia en listas negras. Si la IP está marcada como VPN/Proxy — muchos sitios la tratarán con sospecha desde el principio.

Paso 3: Aísla el problema

Intenta el mismo proxy en diferentes sitios objetivo. Si el bloqueo ocurre en todas partes — el problema está en el proxy o tu configuración. Si solo en un sitio específico — el problema está en la protección de ese sitio o tu comportamiento en él.

También intenta diferentes proxies en un sitio. Si todos se bloquean — el problema no está en el proxy, sino en tu script, huella digital o patrón de comportamiento. Esta es una prueba crítica que muchos omiten.

Paso 4: Análisis de respuestas del servidor

Diferentes tipos de bloqueos se manifiestan de diferentes maneras. Aprende a distinguirlos:

def analyze_response(response):
    status = response.status_code
    
    if status == 403:
        print("Acceso prohibido — posiblemente IP en lista negra")
    elif status == 429:
        print("Demasiadas solicitudes — reduce la frecuencia")
    elif status == 503:
        print("Servicio no disponible — posiblemente protección DDoS")
    elif status == 407:
        print("Se requiere autenticación de proxy — verifica credenciales")
    elif "captcha" in response.text.lower():
        print("Captcha detectada — sospecha de bot")
    elif "blocked" in response.text.lower():
        print("Bloqueo explícito — cambia IP y reconsideración el enfoque")
    elif len(response.text) < 1000:
        print("Respuesta sospechosamente corta — posiblemente un stub")
    else:
        print(f"Estado {status}, longitud de respuesta: {len(response.text)}")

Rotación correcta: frecuencia, lógica, implementación

La rotación de proxies no es simplemente "cambiar IP más frecuentemente". La rotación incorrecta puede causar más daño que su ausencia. Consideremos diferentes estrategias y cuándo aplicarlas.

Estrategia 1: Rotación por número de solicitudes

El enfoque más simple — cambiar IP después de un cierto número de solicitudes. Adecuado para web scraping donde no se necesita sesión:

import random

class ProxyRotator:
    def __init__(self, proxy_list, requests_per_proxy=50):
        self.proxies = proxy_list
        self.requests_per_proxy = requests_per_proxy
        self.current_proxy = None
        self.request_count = 0
    
    def get_proxy(self):
        if self.current_proxy is None or self.request_count >= self.requests_per_proxy:
            # Agregamos aleatoriedad al número de solicitudes
            self.requests_per_proxy = random.randint(30, 70)
            self.current_proxy = random.choice(self.proxies)
            self.request_count = 0
        
        self.request_count += 1
        return self.current_proxy

# Uso
rotator = ProxyRotator(proxy_list)
for url in urls_to_scrape:
    proxy = rotator.get_proxy()
    response = requests.get(url, proxies={"http": proxy, "https": proxy})

Nota la aleatoriedad en el número de solicitudes por proxy. Un número fijo (por ejemplo, exactamente 50) es un patrón que puede ser detectado. Un rango aleatorio hace el comportamiento menos predecible.

Estrategia 2: Rotación por tiempo

Para tareas donde la sesión es importante (por ejemplo, trabajar con cuentas), es mejor vincular la IP al tiempo:

import time
import random

class TimeBasedRotator:
    def __init__(self, proxy_list, min_minutes=10, max_minutes=30):
        self.proxies = proxy_list
        self.min_seconds = min_minutes * 60
        self.max_seconds = max_minutes * 60
        self.current_proxy = None
        self.rotation_time = 0
    
    def get_proxy(self):
        current_time = time.time()
        
        if self.current_proxy is None or current_time >= self.rotation_time:
            self.current_proxy = random.choice(self.proxies)
            # Intervalo aleatorio hasta la próxima rotación
            interval = random.randint(self.min_seconds, self.max_seconds)
            self.rotation_time = current_time + interval
            print(f"Nuevo proxy, próxima rotación en {interval//60} minutos")
        
        return self.current_proxy

Estrategia 3: Sesiones pegajosas para cuentas

Al trabajar con múltiples cuentas, es crítico que cada cuenta use una IP constante. Cambiar IP para una cuenta conectada es el camino seguro al bloqueo:

class AccountProxyManager:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool
        self.account_proxies = {}  # account_id -> proxy
        self.used_proxies = set()
    
    def get_proxy_for_account(self, account_id):
        # Si la cuenta ya tiene un proxy asignado — lo devolvemos
        if account_id in self.account_proxies:
            return self.account_proxies[account_id]
        
        # Encontramos un proxy libre
        available = [p for p in self.proxy_pool if p not in self.used_proxies]
        
        if not available:
            raise Exception("No hay proxies libres para nuevas cuentas")
        
        proxy = random.choice(available)
        self.account_proxies[account_id] = proxy
        self.used_proxies.add(proxy)
        
        return proxy
    
    def release_account(self, account_id):
        """Libera el proxy al eliminar la cuenta"""
        if account_id in self.account_proxies:
            proxy = self.account_proxies.pop(account_id)
            self.used_proxies.discard(proxy)

# Uso
manager = AccountProxyManager(residential_proxy_list)

for account in accounts:
    proxy = manager.get_proxy_for_account(account.id)
    # Todas las acciones de esta cuenta van a través de una IP

Estrategia 4: Rotación adaptativa

El enfoque más avanzado — cambiar proxy en respuesta a señales del sitio objetivo:

class AdaptiveRotator:
    def __init__(self, proxy_list):
        self.proxies = proxy_list
        self.current_proxy = random.choice(proxy_list)
        self.proxy_scores = {p: 100 for p in proxy_list}  # "Salud" inicial del proxy
    
    def get_proxy(self):
        return self.current_proxy
    
    def report_result(self, success, response_code=200):
        """Se llama después de cada solicitud"""
        if success and response_code == 200:
            # Solicitud exitosa — aumentamos ligeramente la puntuación
            self.proxy_scores[self.current_proxy] = min(100, 
                self.proxy_scores[self.current_proxy] + 1)
        elif response_code == 429:
            # Límite de velocidad — reducimos mucho y rotamos
            self.proxy_scores[self.current_proxy] -= 30
            self._rotate()
        elif response_code == 403:
            # Bloqueo — ponemos puntuación a cero y rotamos
            self.proxy_scores[self.current_proxy] = 0
            self._rotate()
        elif response_code == 503:
            # Posible protección — reducimos y rotamos
            self.proxy_scores[self.current_proxy] -= 20
            self._rotate()
    
    def _rotate(self):
        # Seleccionamos proxy con mejor puntuación
        available = [(p, s) for p, s in self.proxy_scores.items() if s > 20]
        if not available:
            # Todos los proxies están "muertos" — reiniciamos puntuaciones
            self.proxy_scores = {p: 50 for p in self.proxies}
            available = list(self.proxy_scores.items())
        
        # Selección ponderada por puntuación
        self.current_proxy = max(available, key=lambda x: x[1])[0]
        print(f"Rotación a proxy con puntuación {self.proxy_scores[self.current_proxy]}")

Huella digital del navegador y su papel en los bloqueos

La huella digital es el conjunto de características del navegador que permite identificar al usuario incluso sin cookies. Si cambias de IP pero la huella digital permanece igual, el sistema de protección fácilmente vincula todas tus sesiones.

De qué se compone la huella digital

La huella digital moderna incluye decenas de parámetros. Aquí están las categorías principales:

Categoría Parámetros Peso en identificación
User-Agent Navegador, versión, SO Medio
Pantalla Resolución, profundidad de color, pixel ratio Medio
Fuentes Lista de fuentes instaladas Alto
WebGL Renderer, vendor, hash de renderizado Muy alto
Canvas Hash de imagen dibujada Muy alto
Audio Huella de AudioContext Alto
Zona horaria Zona horaria, offset Medio
Idiomas navigator.languages Medio
Complementos navigator.plugins Bajo (en navegadores modernos)

Consistencia entre huella digital e IP

Es crítico que la huella digital corresponda a la geografía de la IP. Si el proxy está en Alemania, la huella digital debe parecer un usuario alemán:

// Ejemplo de inconsistencia (MALO):
// IP: Alemania
// Zona horaria: America/New_York
// Idiomas: ["ru-RU", "ru"]
// Esto causará sospecha

// Huella digital consistente (BUENO):
// IP: Alemania
// Zona horaria: Europe/Berlin
// Idiomas: ["de-DE", "de", "en-US", "en"]

Herramientas para gestionar la huella digital

Para trabajo serio, usa herramientas especializadas:

Playwright con Stealth:

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={"server": "http://proxy:port", "username": "user", "password": "pass"}
    )
    
    context = browser.new_context(
        viewport={"width": 1920, "height": 1080},
        locale="de-DE",
        timezone_id="Europe/Berlin",
        geolocation={"latitude": 52.52, "longitude": 13.405},
        permissions=["geolocation"]
    )
    
    page = context.new_page()
    stealth_sync(page)  # Aplicamos parches stealth
    
    page.goto("https://target-site.com")

Puppeteer con puppeteer-extra:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

const browser = await puppeteer.launch({
    args: [`--proxy-server=http://proxy:port`]
});

const page = await browser.newPage();

// Redefinimos la zona horaria
await page.evaluateOnNewDocument(() => {
    Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {
        value: function() {
            return { timeZone: 'Europe/Berlin' };
        }
    });
});

Navegadores anti-detección

Para trabajar con cuentas, a menudo se usan navegadores anti-detección (Multilogin, GoLogin, Dolphin Anty y otros). Permiten crear perfiles aislados con huella digital única. Cada perfil tiene su propio conjunto de parámetros, cookies, localStorage — un entorno completamente aislado.

La ventaja de los anti-detectores es que resuelven el problema de huella digital "de fábrica". La desventaja es el costo y la complejidad de automatización (aunque muchos tienen API).

Patrones de comportamiento: cómo no parecer un bot

Incluso con huella digital perfecta e IP limpia, puedes recibir un bloqueo por comportamiento no humano. Los sistemas modernos analizan no solo parámetros técnicos, sino también patrones de interacción con el sitio.

Retrasos temporales

Un humano no realiza solicitudes con intervalo constante. Agrega retrasos aleatorios con distribución normal:

import random
import time
import numpy as np

def human_delay(min_sec=1, max_sec=5, mean=2.5):
    """
    Genera un retraso similar al humano.
    Usa distribución lognormal — 
    la mayoría de retrasos son cortos, pero a veces hay retrasos largos.
    """
    delay = np.random.lognormal(mean=np.log(mean), sigma=0.5)
    delay = max(min_sec, min(max_sec, delay))
    return delay

def human_typing_delay():
    """Retraso entre pulsaciones de teclas al escribir texto"""
    return random.uniform(0.05, 0.25)

# Uso
for url in urls:
    response = requests.get(url, proxies=proxy)
    process(response)
    time.sleep(human_delay())  # Pausa aleatoria entre solicitudes

Imitación de navegación

Un humano no va directamente a la página del producto por un enlace directo. Entra en la página principal, usa búsqueda, navega por categorías. Imita este camino:

async def human_like_navigation(page, target_url):
    """Imita navegación humana hacia la página objetivo"""
    
    # 1. Vamos a la página principal
    await page.goto("https://example.com")
    await page.wait_for_timeout(random.randint(2000, 4000))
    
    # 2. A veces desplazamos la página principal
    if random.random() > 0.5:
        await page.evaluate("window.scrollBy(0, 300)")
        await page.wait_for_timeout(random.randint(1000, 2000))
    
    # 3. Usamos búsqueda o navegación
    if random.random() > 0.3:
        search_box = await page.query_selector('input[type="search"]')
        if search_box:
            await search_box.type("search query", delay=100)
            await page.keyboard.press("Enter")
            await page.wait_for_timeout(random.randint(2000, 4000))
    
    # 4. Vamos a la página objetivo
    await page.goto(target_url)
    
    # 5. Desplazamos la página como un humano
    await human_scroll(page)

async def human_scroll(page):
    """Imita desplazamiento humano"""
    scroll_height = await page.evaluate("document.body.scrollHeight")
    current_position = 0
    
    while current_position < scroll_height * 0.7:  # No hasta el final
        scroll_amount = random.randint(200, 500)
        await page.evaluate(f"window.scrollBy(0, {scroll_amount})")
        current_position += scroll_amount
        await page.wait_for_timeout(random.randint(500, 1500))

Movimientos del ratón

Algunos sistemas rastrean movimientos del ratón. El movimiento lineal del punto A al punto B es un signo de bot. Un humano mueve el ratón en una curva con micro-correcciones:

import bezier
import numpy as np

def generate_human_mouse_path(start, end, num_points=50):
    """
    Genera un camino de ratón similar al humano,
    usando curvas de Bezier con pequeño ruido.
    """
    # Puntos de control para la curva de Bezier
    control1 = (
        start[0] + (end[0] - start[0]) * random.uniform(0.2, 0.4) + random.randint(-50, 50),
        start[1] + (end[1] - start[1]) * random.uniform(0.2, 0.4) + random.randint(-50, 50)
    )
    control2 = (
        start[0] + (end[0] - start[0]) * random.uniform(0.6, 0.8) + random.randint(-50, 50),
        start[1] + (end[1] - start[1]) * random.uniform(0.6, 0.8) + random.randint(-50, 50)
    )
    
    # Creamos la curva de Bezier
    nodes = np.asfortranarray([
        [start[0], control1[0], control2[0], end[0]],
        [start[1], control1[1], control2[1], end[1]]
    ])
    curve = bezier.Curve(nodes, degree=3)
    
    # Generamos puntos en la curva
    points = []
    for t in np.linspace(0, 1, num_points):
        point = curve.evaluate(t)
        # Agregamos micro-ruido
        x = point[0][0] + random.uniform(-2, 2)
        y = point[1][0] + random.uniform(-2, 2)
        points.append((x, y))
    
    return points

async def human_click(page, selector):
    """Hace clic en elemento con movimiento de ratón similar al humano"""
    element = await page.query_selector(selector)
    box = await element.bounding_box()
    
    # Punto objetivo — no el centro, sino un punto aleatorio dentro del elemento
    target_x = box['x'] + random.uniform(box['width'] * 0.2, box['width'] * 0.8)
    target_y = box['y'] + random.uniform(box['height'] * 0.2, box['height'] * 0.8)
    
    # Posición actual del ratón (o punto de inicio aleatorio)
    start_x = random.randint(0, 1920)
    start_y = random.randint(0, 1080)
    
    # Generamos el camino
    path = generate_human_mouse_path((start_x, start_y), (target_x, target_y))
    
    # Movemos el ratón por el camino
    for x, y in path:
        await page.mouse.move(x, y)
        await page.wait_for_timeout(random.randint(5, 20))
    
    # Pequeña pausa antes del clic
    await page.wait_for_timeout(random.randint(50, 150))
    await page.mouse.click(target_x, target_y)

Carga de recursos

Un navegador real carga no solo HTML, sino también CSS, JavaScript, imágenes, fuentes. Si usas requests y solicitas solo HTML — es sospechoso. Al trabajar con navegadores headless, este problema se resuelve automáticamente, pero al usar clientes HTTP, necesitas considerar este aspecto.

Selección del tipo de proxy para tu tarea

Diferentes tipos de proxies tienen diferentes características y son adecuados para diferentes tareas. La selección incorrecta es una causa frecuente de bloqueos.

Proxies de centro de datos

Los proxies de centro de datos son direcciones IP que pertenecen a proveedores de hosting. Se pueden identificar fácilmente por pertenencia a AS (sistemas autónomos) de grandes centros de datos.

Ventajas:

  • Alta velocidad y estabilidad
  • Bajo costo
  • Grandes pools de IP

Desventajas:

  • Fáciles de detectar
  • Frecuentemente en listas negras
  • No adecuados para sitios con protección seria

Adecuados para: herramientas SEO, verificación de disponibilidad, trabajo con API sin protección estricta, pruebas.

Proxies residenciales

Los proxies residenciales son direcciones IP de usuarios reales, proporcionadas a través de programas de asociados o SDK en aplicaciones. Pertenecen a proveedores de Internet ordinarios (ISP).

Ventajas:

  • Parecen usuarios ordinarios
  • Puntuación de fraude baja
  • Geografía amplia
  • Difíciles de detectar

Desventajas:

  • Costo más alto (pago por tráfico)
  • La velocidad depende del usuario final
  • Las IP pueden "desaparecer" (el usuario apagó el dispositivo)

Adecuados para: web scraping de sitios protegidos, trabajo con redes sociales, e-commerce, cualquier tarea donde es importante no ser detectado.

Proxies móviles

Los proxies móviles son direcciones IP de operadores móviles (MTS, Beeline, Megafon y análogos en otros países). Tienen un estado especial debido a la tecnología CGNAT.

Ventajas:

  • Máxima confianza de los sitios
  • Una IP la usan miles de usuarios reales — difícil de banear
  • Ideales para trabajar con cuentas
  • Cambio de IP por solicitud (reconexión a la red)

Desventajas:

  • El costo más alto
  • Velocidad limitada
  • Menos opciones de geografía

Adecuados para: multi-accounting, trabajo con Instagram/Facebook/TikTok, registro de cuentas, cualquier tarea con alto riesgo de bloqueo.

Tabla comparativa

Parámetro Centro de datos Residenciales Móviles
Detectabilidad Alta Baja Muy baja
Velocidad Alta Media Baja-media
Costo $ $$ $$$
Para redes sociales No adecuados Adecuados Ideales
Para web scraping Sitios simples Cualquier sitio Excesivo

Técnicas avanzadas de evasión de protección

Cuando los métodos básicos no funcionan, es necesario usar técnicas más complejas. Consideremos varios enfoques avanzados.

Trabajo con Cloudflare y protecciones similares

Cloudflare, Akamai, PerimeterX — estos sistemas usan desafíos JavaScript para verificar el navegador. Una solicitud HTTP simple no pasará. Opciones de solución:

1. Uso de navegador real:

from playwright.sync_api import sync_playwright

def bypass_cloudflare(url, proxy):
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=False,  # A veces headless se detecta
            proxy={"server": proxy}
        )
        
        page = browser.new_page()
        page.goto(url)
        
        # Esperamos el paso de la verificación (normalmente 5-10 segundos)
        page.wait_for_timeout(10000)
        
        # Verificamos si pasamos
        if "challenge" not in page.url:
            # Guardamos cookies para solicitudes posteriores
            cookies = page.context.cookies()
            return cookies
        
        browser.close()
        return None

2. Uso de soluciones listas:

# cloudscraper — biblioteca para evadir Cloudflare
import cloudscraper

scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

scraper.proxies = {"http": proxy, "https": proxy}
response = scraper.get("https://protected-site.com")

Solución de captchas

Si el sitio muestra una captcha, hay varios enfoques:

Servicios de reconocimiento: 2Captcha, Anti-Captcha, CapMonster. Resuelven captchas por ti