Volver al blog

Automatización del cambio de proxy a través de API: cómo configurar la rotación para scraping y arbitraje

Guía completa para la automatización del cambio de proxy a través de API: ejemplos de código, integración con parsers y navegadores anti-detección, solución de problemas comunes.

📅16 de febrero de 2026
```html

El cambio manual de proxy al trabajar con cientos de solicitudes es una pérdida de tiempo y dinero. La rotación por API permite cambiar automáticamente las direcciones IP ante bloqueos, distribuir la carga y escalar el scraping o multicuentas. En esta guía analizaremos cómo configurar el cambio automático de proxy para diferentes tareas: desde scraping de marketplaces hasta farming de cuentas en Facebook Ads.

El material es adecuado tanto para desarrolladores que escriben scrapers en Python o Node.js, como para arbitrajistas que utilizan herramientas listas con integración API.

Por qué se necesita la automatización del cambio de proxy mediante API

La rotación automática de direcciones IP mediante API resuelve varias tareas críticas que enfrentan especialistas en diferentes áreas:

Para scraping de marketplaces y sitios web: Al recopilar datos de Wildberries, Ozon o Avito, cada IP puede realizar un número limitado de solicitudes (generalmente 50-200 por hora). La rotación por API permite cambiar automáticamente a una nueva IP al alcanzar el límite o recibir un captcha, asegurando la recopilación continua de datos.

Para arbitraje y multicuentas: Al trabajar con 20-50 cuentas publicitarias de Facebook Ads o cuentas de Instagram, es necesario aislar cada perfil. La API permite asignar programáticamente un proxy único a cada cuenta en Dolphin Anty o AdsPower, recrear automáticamente sesiones ante bloqueos.

Para automatización de SMM: Los servicios de publicación masiva en Instagram, TikTok o VK deben distribuir acciones entre direcciones IP para evitar rate limits. La API brinda la posibilidad de obtener dinámicamente nuevos proxies para cada sesión o grupo de cuentas.

Principales ventajas de la automatización por API en comparación con el cambio manual:

  • Velocidad: El cambio de IP ocurre en milisegundos de forma programática, sin participación humana
  • Escalabilidad: Se pueden gestionar miles de proxies simultáneamente a través de una interfaz única
  • Tolerancia a fallos: Reemplazo automático de proxies que no funcionan sin detener el proceso
  • Flexibilidad: Configuración de reglas de rotación para tareas específicas: por tiempo, por número de solicitudes, por geografía
  • Ahorro: Uso óptimo del tráfico mediante balanceo de carga

Escenario típico de uso: estás scrapeando precios de competidores en Wildberries. Sin API necesitas monitorear manualmente los bloqueos, entrar al panel del proveedor de proxy, copiar nuevos datos, pegarlos en el script. Con API todo esto ocurre automáticamente: el script recibe el error 429 (Too Many Requests), envía una solicitud a la API del servicio de proxy, obtiene una nueva IP y continúa trabajando.

Tipos de rotación de proxy: sticky sessions vs cambio automático

Antes de configurar la automatización, es importante entender la diferencia entre los tipos de rotación de direcciones IP. La elección de la estrategia depende de tu tarea.

Sticky Sessions (proxies de sesión)

Al usar sticky sessions, una dirección IP se asigna a tu sesión durante un tiempo determinado (generalmente de 5 a 30 minutos). El cambio ocurre solo después de que expire el tiempo de sesión o por tu solicitud API.

Cuándo usar:

  • Trabajo con cuentas en redes sociales (Instagram, Facebook) — el cambio frecuente de IP genera sospechas
  • Llenado de formularios de múltiples páginas donde se necesita mantener la sesión
  • Prueba de publicidad desde una región determinada durante la sesión
  • Scraping de sitios con autorización, donde el cambio de IP provocará cierre de sesión

Ejemplo de solicitud API para crear sticky session (generalmente se usa un formato especial de login):

// Formato: username-session-SESSIONID:password
// SESSIONID — cualquier cadena, la misma = una IP

proxy = "username-session-abc123:password@gate.proxycove.com:8000"

// Todas las solicitudes con session-abc123 obtendrán una IP durante el tiempo de sesión
// Para una nueva IP use otro SESSIONID: session-xyz789

Rotación automática en cada solicitud

La dirección IP cambia con cada nueva conexión al servidor proxy. Este es el comportamiento estándar de los proxies residenciales sin especificar parámetros de sesión.

Cuándo usar:

  • Scraping masivo sin autorización (precios, contactos, anuncios)
  • Evasión de rate limits agresivos en APIs públicas
  • Recopilación de datos de sitios que banean IPs después de 10-20 solicitudes
  • Verificación de disponibilidad de contenido desde diferentes regiones

Ejemplo de uso en Python (cada solicitud = nueva IP):

import requests

proxy = {
    "http": "http://username:password@gate.proxycove.com:8000",
    "https": "http://username:password@gate.proxycove.com:8000"
}

# Cada solicitud obtendrá una nueva IP
for i in range(10):
    response = requests.get("https://api.ipify.org", proxies=proxy)
    print(f"Solicitud {i+1}, IP: {response.text}")

Rotación por temporizador

Controlas programáticamente cuándo cambiar la IP: cada N minutos, después de M solicitudes o al recibir ciertos errores. Este es un enfoque híbrido que se implementa mediante la API del servicio de proxy.

Cuándo usar:

  • Optimización del consumo de tráfico — cambio solo cuando sea necesario
  • Trabajo con sitios que rastrean patrones (cambio demasiado frecuente = ban)
  • Balance entre anonimato y estabilidad de sesión
Tipo de rotación Frecuencia de cambio de IP Tareas Consumo de tráfico
Sticky Session 5-30 minutos Multicuentas, autorización Bajo
Auto-rotación Cada solicitud Scraping, evasión de rate limits Medio
Por temporizador Configurable Universal Optimizado

Fundamentos del trabajo con API de servicios de proxy

La mayoría de los proveedores modernos de proxy ofrecen dos formas de gestión: a través del panel web y mediante API. La API proporciona acceso programático a funciones: obtener lista de proxies, crear nuevas sesiones, verificar saldo, estadísticas de uso.

Métodos API típicos de servicios de proxy

Aunque cada proveedor tiene su propia documentación, los métodos estándar generalmente incluyen:

  • GET /api/v1/proxy/list — obtener lista de proxies disponibles con filtrado por país, tipo
  • POST /api/v1/proxy/rotate — cambiar forzosamente la IP en la sesión activa
  • GET /api/v1/account/balance — verificar saldo de tráfico o dinero en la cuenta
  • GET /api/v1/stats — estadísticas de uso: volumen de tráfico, número de solicitudes, errores
  • POST /api/v1/session/create — crear nueva sticky session con parámetros (país, ciudad, duración)

La autenticación generalmente ocurre mediante clave API en el encabezado de la solicitud:

curl -X GET "https://api.provider.com/v1/proxy/list?country=US" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

La respuesta generalmente llega en formato JSON:

{
  "status": "success",
  "data": {
    "proxies": [
      {
        "ip": "123.45.67.89",
        "port": 8000,
        "country": "US",
        "city": "New York",
        "protocol": "http",
        "username": "user123",
        "password": "pass456"
      }
    ],
    "total": 150,
    "available": 147
  }
}

Gestión de sesiones mediante API

Para tareas que requieren control sobre el tiempo de vida de la IP (multicuentas, trabajo con cuentas), se utiliza la creación de sesiones nombradas mediante API. Esto permite gestionar programáticamente decenas y cientos de direcciones IP aisladas.

Ejemplo de creación de sesión con parámetros:

POST /api/v1/session/create
{
  "country": "US",
  "state": "California",
  "session_duration": 600,  // 10 minutos
  "session_id": "facebook_account_001"
}

// Respuesta:
{
  "status": "success",
  "session": {
    "id": "facebook_account_001",
    "proxy": "gate.provider.com:8000",
    "username": "user-session-facebook_account_001",
    "password": "your_password",
    "ip": "45.67.89.123",
    "expires_at": "2024-01-15T15:30:00Z"
  }
}

Ahora puedes usar este proxy en tu script o navegador antidetección, y la IP permanecerá sin cambios durante 10 minutos. Para prolongar la sesión se envía una solicitud repetida con el mismo session_id.

Ejemplos de automatización en Python: requests, Selenium, Scrapy

Python es el lenguaje más popular para scraping y automatización. Veamos ejemplos de integración de rotación de proxy por API con las herramientas principales.

Cambio automático de proxy en requests

La biblioteca requests se usa para solicitudes HTTP simples. Para rotación automática crearemos una clase wrapper que cambia el proxy ante errores:

import requests
import random
import time

class RotatingProxySession:
    def __init__(self, proxy_list):
        """
        proxy_list: lista de diccionarios con datos de proxy
        [{"http": "http://user:pass@ip:port", "https": "..."}]
        """
        self.proxy_list = proxy_list
        self.current_proxy = None
        self.session = requests.Session()
        self.rotate()
    
    def rotate(self):
        """Seleccionar proxy aleatorio de la lista"""
        self.current_proxy = random.choice(self.proxy_list)
        self.session.proxies.update(self.current_proxy)
        print(f"Cambiado a proxy: {self.current_proxy['http']}")
    
    def get(self, url, max_retries=3, **kwargs):
        """Solicitud GET con rotación automática ante errores"""
        for attempt in range(max_retries):
            try:
                response = self.session.get(url, timeout=10, **kwargs)
                
                # Si recibimos bloqueo — cambiar proxy
                if response.status_code in [403, 429, 503]:
                    print(f"Recibido {response.status_code}, cambiando proxy...")
                    self.rotate()
                    time.sleep(2)
                    continue
                
                return response
                
            except requests.exceptions.ProxyError:
                print(f"Proxy no funciona, intento {attempt+1}/{max_retries}")
                self.rotate()
                time.sleep(2)
            
            except requests.exceptions.Timeout:
                print("Timeout, cambiando proxy...")
                self.rotate()
                time.sleep(2)
        
        raise Exception(f"No se pudo realizar la solicitud después de {max_retries} intentos")

# Uso:
proxies = [
    {"http": "http://user1:pass@gate1.com:8000", "https": "http://user1:pass@gate1.com:8000"},
    {"http": "http://user2:pass@gate2.com:8000", "https": "http://user2:pass@gate2.com:8000"},
]

session = RotatingProxySession(proxies)

# Scrapeamos Wildberries
for page in range(1, 50):
    url = f"https://www.wildberries.ru/catalog/page={page}"
    response = session.get(url)
    print(f"Página {page}: {response.status_code}")

Integración con Selenium para automatización de navegador

Selenium se usa para scrapear sitios con JavaScript y automatizar acciones en el navegador. Para cambiar el proxy es necesario recrear el driver, ya que la configuración del proxy se establece en la inicialización:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

class SeleniumRotatingProxy:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.driver = None
        self.current_proxy_index = 0
    
    def create_driver(self):
        """Crear nuevo driver con el proxy actual"""
        if self.driver:
            self.driver.quit()
        
        proxy = self.proxy_list[self.current_proxy_index]
        
        chrome_options = Options()
        chrome_options.add_argument(f'--proxy-server={proxy}')
        chrome_options.add_argument('--headless')  # sin GUI
        
        self.driver = webdriver.Chrome(options=chrome_options)
        print(f"Driver creado con proxy: {proxy}")
    
    def rotate(self):
        """Cambiar al siguiente proxy"""
        self.current_proxy_index = (self.current_proxy_index + 1) % len(self.proxy_list)
        self.create_driver()
    
    def get_with_retry(self, url, max_retries=3):
        """Abrir URL con cambio automático de proxy ante errores"""
        for attempt in range(max_retries):
            try:
                if not self.driver:
                    self.create_driver()
                
                self.driver.get(url)
                
                # Verificación de bloqueo (por ejemplo, búsqueda de captcha)
                if "captcha" in self.driver.page_source.lower():
                    print("Captcha detectado, cambiando proxy...")
                    self.rotate()
                    time.sleep(3)
                    continue
                
                return self.driver.page_source
                
            except Exception as e:
                print(f"Error: {e}, cambiando proxy (intento {attempt+1})")
                self.rotate()
                time.sleep(3)
        
        raise Exception("No se pudo cargar la página")

# Uso:
proxies = [
    "http://user:pass@gate1.com:8000",
    "http://user:pass@gate2.com:8000",
]

bot = SeleniumRotatingProxy(proxies)

# Scrapeamos Ozon
for i in range(10):
    html = bot.get_with_retry(f"https://www.ozon.ru/category/page-{i}")
    print(f"Obtenido HTML de página {i}, longitud: {len(html)}")

bot.driver.quit()

Scrapy con middleware para rotación de proxy

Scrapy es un framework para scraping a gran escala. La rotación de proxy se implementa mediante middleware, que se aplica automáticamente a todas las solicitudes:

# middlewares.py

import random
from scrapy.exceptions import IgnoreRequest

class RotatingProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
    
    @classmethod
    def from_crawler(cls, crawler):
        # Obtener lista de proxies de la configuración
        proxy_list = crawler.settings.getlist('ROTATING_PROXY_LIST')
        return cls(proxy_list)
    
    def process_request(self, request, spider):
        # Asignar proxy aleatorio a cada solicitud
        proxy = random.choice(self.proxy_list)
        request.meta['proxy'] = proxy
        spider.logger.info(f'Usando proxy: {proxy}')
    
    def process_exception(self, request, exception, spider):
        # Ante error de proxy — repetir con otro
        proxy = random.choice(self.proxy_list)
        spider.logger.warning(f'Error de proxy, cambiando a: {proxy}')
        request.meta['proxy'] = proxy
        return request  # repetir solicitud

# settings.py

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.RotatingProxyMiddleware': 350,
}

ROTATING_PROXY_LIST = [
    'http://user:pass@gate1.com:8000',
    'http://user:pass@gate2.com:8000',
    'http://user:pass@gate3.com:8000',
]

# Repetir solicitudes ante errores
RETRY_TIMES = 5
RETRY_HTTP_CODES = [403, 429, 500, 502, 503]

Ahora cada solicitud de Scrapy obtendrá automáticamente un proxy aleatorio de la lista, y ante errores se repetirá con otra IP.

Automatización en Node.js: axios, Puppeteer, Playwright

Node.js es popular para crear scrapers y bots gracias a su asincronía y buena integración con herramientas de navegador. Veamos ejemplos de rotación de proxy en las bibliotecas principales.

Axios con rotación automática

Axios es una biblioteca para solicitudes HTTP. Crearemos una clase con pool de proxies y reemplazo automático ante errores:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

class RotatingProxyClient {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentIndex = 0;
  }

  getProxy() {
    const proxy = this.proxyList[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
    return proxy;
  }

  async request(url, options = {}, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
      const proxy = this.getProxy();
      const agent = new HttpsProxyAgent(proxy);

      try {
        const response = await axios.get(url, {
          ...options,
          httpsAgent: agent,
          timeout: 10000
        });

        // Si recibimos bloqueo — siguiente intento
        if ([403, 429, 503].includes(response.status)) {
          console.log(`Estado ${response.status}, cambiando proxy...`);
          continue;
        }

        return response.data;

      } catch (error) {
        console.log(`Error con proxy ${proxy}: ${error.message}`);
        if (i === maxRetries - 1) throw error;
      }
    }
  }
}

// Uso:
const proxies = [
  'http://user:pass@gate1.com:8000',
  'http://user:pass@gate2.com:8000',
];

const client = new RotatingProxyClient(proxies);

(async () => {
  for (let page = 1; page <= 20; page++) {
    const data = await client.request(`https://api.example.com/products?page=${page}`);
    console.log(`Página ${page}: obtenidos ${data.length} productos`);
  }
})();

Puppeteer con rotación de proxy

Puppeteer controla el navegador Chrome. El proxy se establece al iniciar el navegador, por lo que para cambiarlo es necesario recrear la instancia:

const puppeteer = require('puppeteer');

class PuppeteerRotatingProxy {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentIndex = 0;
    this.browser = null;
  }

  async createBrowser() {
    if (this.browser) await this.browser.close();

    const proxy = this.proxyList[this.currentIndex];
    console.log(`Iniciando navegador con proxy: ${proxy}`);

    this.browser = await puppeteer.launch({
      headless: true,
      args: [`--proxy-server=${proxy}`]
    });
  }

  rotate() {
    this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
  }

  async scrape(url, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
      try {
        if (!this.browser) await this.createBrowser();

        const page = await this.browser.newPage();
        
        // Autenticación de proxy (si es necesario)
        await page.authenticate({
          username: 'your_username',
          password: 'your_password'
        });

        await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });

        // Verificación de captcha
        const content = await page.content();
        if (content.includes('captcha')) {
          console.log('Captcha detectado, cambiando proxy...');
          this.rotate();
          await this.createBrowser();
          continue;
        }

        return content;

      } catch (error) {
        console.log(`Error: ${error.message}, intento ${i+1}`);
        this.rotate();
        await this.createBrowser();
      }
    }
    throw new Error('No se pudo cargar la página');
  }
}

// Uso:
const proxies = ['gate1.com:8000', 'gate2.com:8000'];
const scraper = new PuppeteerRotatingProxy(proxies);

(async () => {
  const html = await scraper.scrape('https://www.avito.ru/moskva');
  console.log(`Obtenido HTML de longitud: ${html.length}`);
  await scraper.browser.close();
})();

Playwright con soporte de rotación

Playwright es una alternativa moderna a Puppeteer con mejor rendimiento. La configuración del proxy es similar:

const { chromium } = require('playwright');

async function scrapeWithRotation(urls, proxyList) {
  let proxyIndex = 0;

  for (const url of urls) {
    const proxy = proxyList[proxyIndex];
    
    const browser = await chromium.launch({
      headless: true,
      proxy: {
        server: proxy,
        username: 'your_user',
        password: 'your_pass'
      }
    });

    const page = await browser.newPage();
    
    try {
      await page.goto(url, { timeout: 30000 });
      const title = await page.title();
      console.log(`${url} → ${title} (proxy: ${proxy})`);
    } catch (error) {
      console.log(`Error en ${url}: ${error.message}`);
    }

    await browser.close();
    
    // Siguiente proxy para siguiente URL
    proxyIndex = (proxyIndex + 1) % proxyList.length;
  }
}

const urls = [
  'https://www.wildberries.ru',
  'https://www.ozon.ru',
  'https://www.avito.ru'
];

const proxies = [
  'http://gate1.com:8000',
  'http://gate2.com:8000'
];

scrapeWithRotation(urls, proxies);

Integración de API con navegadores antidetección: Dolphin Anty, AdsPower

Para arbitrajistas y especialistas en SMM que trabajan con multicuentas, la asignación manual de proxy a cada perfil en Dolphin Anty o AdsPower lleva horas. Las API de estos navegadores permiten automatizar la creación de perfiles y la vinculación de proxies.

Automatización de Dolphin Anty mediante API

Dolphin Anty proporciona una API local (generalmente en http://localhost:3001/v1.0), mediante la cual se pueden crear perfiles, asignar proxies, iniciar navegadores programáticamente.

Ejemplo de script en Python para creación masiva de perfiles con proxies únicos:

import requests
import json

DOLPHIN_API = "http://localhost:3001/v1.0"
API_TOKEN = "your_dolphin_api_token"

# Lista de proxies de tu proveedor (obtenidos mediante su API)
proxies = [
    {"host": "gate1.com", "port": 8000, "login": "user1", "password": "pass1"},
    {"host": "gate2.com", "port": 8000, "login": "user2", "password": "pass2"},
]

def create_profile_with_proxy(name, proxy):
    """Crear perfil en Dolphin con vinculación de proxy"""
    
    payload = {
        "name": name,
        "tags": ["Facebook Ads", "Auto-created"],
        "proxy": {
            "type": "http",  # o socks5
            "host": proxy["host"],
            "port": proxy["port"],
            "login": proxy["login"],
            "password": proxy["password"]
        },
        "fingerprint": {
            "os": "win",
            "webRTC": {
                "mode": "altered",
                "fillBasedOnIp": True
            },
            "canvas": {
                "mode": "noise"
            }
        }
    }
    
    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json"
    }
    
    response = requests.post(
        f"{DOLPHIN_API}/browser_profiles",
        headers=headers,
        data=json.dumps(payload)
    )
    
    if response.status_code == 200:
        profile = response.json()
        print(f"✓ Perfil creado: {name}, ID: {profile['id']}")
        return profile['id']
    else:
        print(f"✗ Error al crear {name}: {response.text}")
        return None

# Crear 50 perfiles con rotación de proxies
for i in range(50):
    proxy = proxies[i % len(proxies)]  # rotación cíclica
    profile_name = f"FB_Account_{i+1:03d}"
    create_profile_with_proxy(profile_name, proxy)

Ahora tienes 50 perfiles en Dolphin Anty, cada uno con huella digital única de navegador y proxy. Para iniciar el perfil programáticamente:

def start_profile(profile_id):
    """Iniciar perfil de navegador"""
    response = requests.get(
        f"{DOLPHIN_API}/browser_profiles/{profile_id}/start",
        headers={"Authorization": f"Bearer {API_TOKEN}"}
    )
    
    if response.status_code == 200:
        data = response.json()
        print(f"Perfil iniciado, puerto WebDriver: {data['automation']['port']}")
        return data['automation']['port']
    else:
        print(f"Error al iniciar: {response.text}")

# Iniciar perfil y controlar mediante Selenium
port = start_profile("profile_id_here")

from selenium import webdriver
driver = webdriver.Remote(
    command_executor=f'http://127.0.0.1:{port}',
    options=webdriver.ChromeOptions()
)
driver.get("https://facebook.com")

Automatización de AdsPower

AdsPower también proporciona una API local. La lógica es similar a Dolphin, pero con diferentes endpoints:

import requests

ADSPOWER_API = "http://local.adspower.net:50325/api/v1"

def create_adspower_profile(name, proxy):
    payload = {
        "name": name,
        "group_id": "0",  # ID de grupo de perfiles
        "domain_name": "facebook.com",
        "open_urls": ["https://facebook.com"],
        "repeat_config": ["0"],
        "username": proxy["login"],
        "password": proxy["password"],
        "proxy_type": "http",
        "proxy_host": proxy["host"],
        "proxy_port": proxy["port"],
        "proxy_user": proxy["login"],
        "proxy_password": proxy["password"]
    }
    
    response = requests.post(
        f"{ADSPOWER_API}/user/create",
        json=payload
    )
    
    if response.json()["code"] == 0:
        user_id = response.json()["data"]["id"]
        print(f"✓ Perfil AdsPower creado: {name}, ID: {user_id}")
        return user_id
    else:
        print(f"✗ Error: {response.json()['msg']}")

# Creación de perfiles
for i, proxy in enumerate(proxies):
    create_adspower_profile(f"TikTok_Account_{i+1}", proxy)

Esta automatización es críticamente importante al trabajar con decenas de cuentas. En lugar de copiar manualmente los datos del proxy en cada perfil, ejecutas el script y obtienes la infraestructura lista en minutos.

Manejo de errores y fallback automático

Al trabajar con proxies son inevitables situaciones: IP bloqueada por el sitio objetivo, servidor proxy no responde, tráfico agotado. El manejo correcto de errores es clave para una automatización estable.

Tipos de errores y estrategias de manejo

Error Causa Solución
HTTP 403 Forbidden IP en lista de bloqueo del sitio Cambiar proxy, añadir retraso
HTTP 429 Too Many Requests Rate limit excedido Cambiar IP, aumentar intervalo
ProxyError / Timeout Servidor proxy no responde Eliminar del pool, tomar siguiente
407 Proxy Authentication Required Usuario/contraseña incorrectos Verificar credenciales, actualizar
Captcha en la página Sitio detectó bot Cambiar IP, usar proxies móviles

Implementación de sistema inteligente de retry

En lugar de una simple repetición de solicitud, crearemos un sistema con retraso exponencial y lista negra de proxies que no funcionan:

import requests
import time
from collections import defaultdict

class SmartProxyRotator:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.blacklist = set()  # IPs que no funcionan
        self.error_count = defaultdict(int)  # contador de errores por IP
        self.max_errors = 3  # después de 3 errores — a lista negra
    
    def get_working_proxy(self):
        """Obtener proxy que no esté en lista negra"""
        available = [p for p in self.proxy_list if p not in self.blacklist]
        if not available:
            # Todos los proxies bloqueados — limpiar lista negra
            print("⚠ Todos los proxies bloqueados, reiniciando lista negra")
            self.blacklist.clear()
            self.error_count.clear()
            available = self.proxy_list
        return available[0]
    
    def mark_error(self, proxy):
        """Marcar error de proxy"""
        self.error_count[proxy] += 1
        if self.error_count[proxy] >= self.max_errors:
            self.blacklist.add(proxy)
            print(f"✗ Proxy {proxy} añadido a lista negra")
    
    def request_with_retry(self, url, max_retries=5):
        """Solicitud con reintentos inteligentes"""
        for attempt in range(max_retries):
            proxy = self.get_working_proxy()
            
            try:
                # Retraso exponencial: 1s, 2s, 4s, 8s...
                if attempt > 0:
                    delay = 2 ** attempt
                    print(f"Esperando {delay}s antes del intento {attempt+1}")
                    time.sleep(delay)
                
                response = requests.get(
                    url,
                    proxies={"http": proxy, "https": proxy},
                    timeout=15
                )
                
                # Éxito — reiniciar contador de errores
                if response.status_code == 200:
                    self.error_count[proxy] = 0
                    return response
                
                # Bloqueo — cambiar proxy
                elif response.status_code in [403, 429]:
                    print(f"Estado {response.status_code}, cambiando proxy")
                    self.mark_error(proxy)
                    continue
                
            except requests.exceptions.ProxyError:
                print(f"ProxyError con {proxy}")
                self.mark_error(proxy)
                
            except requests.exceptions.Timeout:
                print(f"Timeout con {proxy}")
                self.mark_error(proxy)
        
        raise Exception(f"No se pudo realizar la solicitud después de {max_retries} intentos")

# Uso:
proxies = [
    "http://user:pass@gate1.com:8000",
    "http://user:pass@gate2.com:8000",
    "http://user:pass@gate3.com:8000",
]

rotator = SmartProxyRotator(proxies)

for i in range(100):
    try:
        response = rotator.request_with_retry(f"https://api.example.com/data?page={i}")
        print(f"✓ Página {i}: {len(response.text)} bytes")
    except Exception as e:
        print(f"✗ Error crítico en página {i}: {e}")

Monitoreo y alertas

Para sistemas en producción es importante rastrear la salud del pool de proxies en tiempo real. Añade registro de métricas:

import logging
from datetime import datetime

class ProxyMonitor:
    def __init__(self):
        self.stats = {
            "total_requests": 0,
            "successful": 0,
            "failed": 0,
            "proxy_errors": defaultdict(int),
            "start_time": datetime.now()
        }
        
        # Configuración de logging
        logging.basicConfig(
            filename='proxy_rotation.log',
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s'
        )
    
    def log_request(self, proxy, success, error=None):
        self.stats["total_requests"] += 1
        
        if success:
            self.stats["successful"] += 1
            logging.info(f"✓ Éxito con {proxy}")
        else:
            self.stats["failed"] += 1
            self.stats["proxy_errors"][proxy] += 1
            logging.error(f"✗ Error con {proxy}: {error}")
    
    def get_report(self):
        uptime = datetime.now() - self.stats["start_time"]
        success_rate = (self.stats["successful"] / self.stats["total_requests"] * 100) if self.stats["total_requests"] > 0 else 0
        
        return f"""
=== Informe de rotación de proxy ===
Tiempo de actividad: {uptime}
Total de solicitudes: {self.stats["total_requests"]}
Exitosas: {self.stats["successful"]} ({success_rate:.1f}%)
Errores: {self.stats["failed"]}

Proxies problemáticos:
{self._format_errors()}
        """
    
    def _format_errors(self):
        sorted_errors = sorted(
            self.stats["proxy_errors"].items(),
            key=lambda x: x[1],
            reverse=True
        )
        return "\n".join([f"  {proxy}: {count} errores" for proxy, count in sorted_errors[:5]])

# Integración con rotator
monitor = ProxyMonitor()

# En el bucle de solicitudes:
try:
    response = rotator.request_with_retry(url)
    monitor.log_request(current_proxy, success=True)
except Exception as e:
    monitor.log_request(current_proxy, success=False, error=str(e))

Mejores prácticas y optimización del consumo de tráfico

Para maximizar la eficiencia de la rotación de proxies y minimizar costos, sigue estas recomendaciones probadas:

1. Usa sticky sessions cuando sea posible

El cambio constante de IP consume más tráfico y puede parecer sospechoso. Para tareas donde la sesión puede durar varios minutos (trabajo con cuentas, navegación por sitio), usa sticky sessions de 10-30 minutos.

2. Implementa caché de respuestas

Si scrapeeas datos que cambian raramente (información de productos, contactos), guarda las respuestas en caché local para evitar solicitudes repetidas:

import hashlib
import json
import os

class CachedProxySession:
    def __init__(self, rotator, cache_dir='./cache'):
        self.rotator = rotator
        self.cache_dir = cache_dir
        os.makedirs(cache_dir, exist_ok=True)
    
    def _get_cache_key(self, url):
        return hashlib.md5(url.encode()).hexdigest()
    
    def get(self, url, cache_ttl=3600):
        """GET con caché (TTL en segundos)"""
        cache_key = self._get_cache_key(url)
        cache_file = f"{self.cache_dir}/{cache_key}.json"
        
        # Verificar caché
        if os.path.exists(cache_file):
            cache_age = time.time() - os.path.getmtime(cache_file)
            if cache_age < cache_ttl:
                with open(cache_file, 'r') as f:
                    print(f"✓ Caché hit para {url}")
                    return json.load(f)
        
        # Solicitud real
        response = self.rotator.request_with_retry(url)
        
        # Guardar en caché
        with open(cache_file, 'w') as f:
            json.dump(response.text, f)
        
        return response.text

3. Distribuye la carga geográficamente

Si scrapeeas sitios con servidores regionales (marketplaces, sitios de anuncios), usa proxies del mismo país para reducir latencia y evitar bloqueos geográficos.

4. Monitorea métricas clave

Rastrea estas métricas para optimizar el uso de proxies:

  • Tasa de éxito: % de solicitudes exitosas (objetivo: >95%)
  • Tiempo promedio de respuesta: latencia de proxies (objetivo: <2s)
  • Consumo de tráfico por tarea: optimizar para reducir costos
  • Tasa de bloqueo por IP: identificar proxies problemáticos

5. Configura rate limiting inteligente

No envíes solicitudes al máximo de velocidad. Añade retrasos aleatorios para imitar comportamiento humano:

import random
import time

def human_like_delay():
    """Retraso aleatorio entre 1-5 segundos"""
    delay = random.uniform(1, 5)
    time.sleep(delay)

# En el bucle de scraping:
for url in urls:
    response = session.get(url)
    process_data(response)
    human_like_delay()  # Imitar comportamiento humano

Conclusión

La automatización del cambio de proxy mediante API transforma tareas manuales que llevan horas en procesos que se ejecutan en minutos sin intervención humana. Ya sea que estés scrapeando marketplaces, gestionando cuentas publicitarias o automatizando SMM, la rotación programática de IP es la base de operaciones escalables y estables.

Puntos clave para recordar:

  • Elige el tipo de rotación según la tarea: sticky sessions para multicuentas, auto-rotación para scraping masivo
  • Implementa manejo robusto de errores con lista negra y reintentos exponenciales
  • Integra API de proxies con tus herramientas: Python/Node.js para scripts, API de navegadores antidetección para multicuentas
  • Monitorea métricas y optimiza el consumo de tráfico mediante caché y rate limiting inteligente
  • Usa proxies de calidad con buena documentación API y soporte técnico

Con las herramientas y ejemplos de código de esta guía, puedes construir sistemas de automatización que escalan a miles de solicitudes por hora manteniendo alta tasa de éxito y bajos costos operativos. Comienza con implementaciones simples y añade gradualmente funciones avanzadas como balanceo de carga geográfico, caché distribuido y monitoreo en tiempo real.

```