Volver al blog

Cómo eludir la detección de Cloudflare al usar proxies

¿Cloudflare bloquea tus solicitudes a través de un proxy? Analizamos métodos técnicos para eludir la detección: desde la configuración adecuada de TLS hasta el uso de navegadores sin cabeza con ejemplos reales.

📅17 de diciembre de 2025
```html

7 métodos probados para eludir la detección de Cloudflare al trabajar a través de proxies

Cloudflare maneja más del 20% de todo el tráfico web y utiliza un sistema de protección contra bots en múltiples niveles. Al trabajar a través de servidores proxy, la probabilidad de recibir un captcha o un bloqueo aumenta exponencialmente. En esta guía, analizaremos los aspectos técnicos de la detección y los métodos prácticos de elusión que funcionan en 2024.

Cómo Cloudflare identifica proxies y bots

Cloudflare utiliza un sistema de análisis integral que verifica decenas de parámetros de cada solicitud. Comprender los mecanismos de detección es el primer paso para eludir con éxito la protección.

Métodos principales de detección

TLS Fingerprinting: Cloudflare analiza los parámetros del apretón de manos SSL/TLS (cipher suites, extensiones, orden de aparición). Cada cliente HTTP tiene una "huella" única. Por ejemplo, Python requests utiliza OpenSSL con un conjunto característico de cifrados que es fácil de distinguir de Chrome o Firefox.

Al analizar la solicitud, Cloudflare compara el TLS fingerprint con el User-Agent declarado. Si especificas Chrome 120, pero los parámetros TLS corresponden a Python requests, esto resulta en una detección instantánea de un bot.

Parámetro de verificación Qué se analiza Riesgo de detección
TLS fingerprint Cipher suites, extensiones, versión de TLS Alto
HTTP/2 fingerprint Orden de encabezados, frames de SETTINGS Alto
Reputación IP Historial de IP, pertenencia a centros de datos Medio
Desafío de JavaScript Ejecución de JS, huella de canvas, WebGL Alto
Análisis de comportamiento Patrones de solicitudes, timing, movimientos del mouse Medio

Desde 2023, Cloudflare utiliza activamente el aprendizaje automático para analizar patrones de comportamiento. El sistema no solo rastrea parámetros técnicos, sino también los intervalos de tiempo entre solicitudes, la secuencia de acciones del usuario, los movimientos del mouse y el desplazamiento de la página.

Enmascaramiento de TLS fingerprint

El TLS fingerprinting es el método más efectivo para la detección de bots. Los clientes HTTP estándar (requests, curl, axios) generan un fingerprint que no se puede confundir con un navegador real. La solución es utilizar bibliotecas especializadas que imitan el comportamiento TLS de los navegadores.

Uso de curl-impersonate

La biblioteca curl-impersonate es una versión modificada de curl que copia con precisión los fingerprints de TLS y HTTP/2 de los navegadores populares. Soporta Chrome, Firefox, Safari y Edge.

# Instalación de curl-impersonate
git clone https://github.com/lwthiker/curl-impersonate
cd curl-impersonate
make chrome-build

# Uso con imitación de Chrome 120
curl_chrome120 -x http://username:password@proxy.example.com:8080 \
  -H "Accept-Language: en-US,en;q=0.9" \
  https://example.com

Python: biblioteca tls-client

Para Python existe un wrapper tls-client que utiliza curl-impersonate bajo el capó y proporciona una interfaz similar a requests.

import tls_client

# Creación de sesión con fingerprint de Chrome 120
session = tls_client.Session(
    client_identifier="chrome_120",
    random_tls_extension_order=True
)

# Configuración del proxy
proxies = {
    'http': 'http://username:password@proxy.example.com:8080',
    'https': 'http://username:password@proxy.example.com:8080'
}

# Ejecución de la solicitud
response = session.get(
    'https://example.com',
    proxies=proxies,
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br',
        'DNT': '1',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1'
    }
)

print(response.status_code)

Importante: Al usar tls-client, es crítico que el User-Agent en los encabezados coincida con el client_identifier elegido. La discrepancia resultará en una detección inmediata.

Verificación de TLS fingerprint

Antes de comenzar a hacer scraping, se recomienda verificar tu TLS fingerprint. Utiliza servicios como tls.peet.ws o ja3er.com para el análisis.

# Verificación del fingerprint
response = session.get('https://tls.peet.ws/api/all')
print(response.json()['tls']['ja3'])

# Compara con el fingerprint de un Chrome real:
# https://kawayiyi.com/tls-fingerprint-database/

Configuración correcta de los encabezados HTTP

Incluso con el TLS fingerprint correcto, encabezados HTTP incorrectos delatarán a un bot. Cloudflare analiza no solo la presencia de encabezados, sino también su orden, formato de valores y coherencia lógica.

Encabezados obligatorios para Chrome

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
    'Sec-Ch-Ua-Mobile': '?0',
    'Sec-Ch-Ua-Platform': '"Windows"',
    'Cache-Control': 'max-age=0'
}

Los encabezados Sec-Ch-Ua-* aparecieron en Chrome 89 y son parte de la API Client Hints. Su ausencia al usar un User-Agent moderno es un signo claro de un bot.

El orden de los encabezados importa

En HTTP/2, el orden de los encabezados es fijo para cada navegador. Python requests y otros clientes estándar envían encabezados en orden alfabético, lo que difiere del comportamiento de los navegadores. Utiliza bibliotecas que soporten un orden personalizado de encabezados.

Consejo: Utiliza las DevTools del navegador (pestaña Network → clic derecho en la solicitud → Copiar → Copiar como cURL) para obtener una copia exacta de los encabezados de un navegador real. Luego, adáptalos a tu código.

Generación dinámica de User-Agent

Usar el mismo User-Agent para todas las solicitudes aumenta el riesgo de detección. Crea un pool de User-Agents actualizados y rótalos.

import random

# Pool de User-Agents actualizados (diciembre 2024)
USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
]

def get_random_headers():
    ua = random.choice(USER_AGENTS)
    
    # Adaptación de otros encabezados según el UA elegido
    if 'Chrome' in ua:
        return {
            'User-Agent': ua,
            'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120"',
            # ... otros encabezados de Chrome
        }
    elif 'Firefox' in ua:
        return {
            'User-Agent': ua,
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            # ... encabezados de Firefox
        }
    # ... manejo de otros navegadores

Uso de navegadores sin cabeza

Cuando Cloudflare utiliza un desafío de JavaScript o detección avanzada, la única forma confiable de eludirlo es con un navegador real. Los navegadores sin cabeza manejan automáticamente JavaScript, cookies y crean un fingerprint completamente auténtico.

Playwright con parches anti-detect

Playwright es una alternativa moderna a Selenium con mejor rendimiento. Sin embargo, el Playwright estándar es fácilmente detectado a través de navigator.webdriver y otros marcadores. Utiliza playwright-stealth para enmascarar.

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

def bypass_cloudflare(url, proxy):
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            proxy={
                "server": f"http://{proxy['host']}:{proxy['port']}",
                "username": proxy['username'],
                "password": proxy['password']
            },
            args=[
                '--disable-blink-features=AutomationControlled',
                '--disable-dev-shm-usage',
                '--no-sandbox'
            ]
        )
        
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            locale='en-US',
            timezone_id='America/New_York'
        )
        
        page = context.new_page()
        stealth_sync(page)  # Aplicación de parches anti-detect
        
        # Navegar a la página
        page.goto(url, wait_until='networkidle', timeout=30000)
        
        # Esperar a que se complete el desafío de Cloudflare (normalmente 5-10 segundos)
        page.wait_for_timeout(8000)
        
        # Verificar si se ha eludido con éxito
        if 'Just a moment' in page.content():
            print('Desafío de Cloudflare no superado')
            return None
        
        # Extraer cookies para uso posterior
        cookies = context.cookies()
        html = page.content()
        
        browser.close()
        return {'html': html, 'cookies': cookies}

# Uso
proxy_config = {
    'host': 'proxy.example.com',
    'port': 8080,
    'username': 'user',
    'password': 'pass'
}

result = bypass_cloudflare('https://example.com', proxy_config)

Puppeteer Extra con plugins

Para el ecosistema de Node.js, la mejor solución es puppeteer-extra con el plugin puppeteer-extra-plugin-stealth. Este plugin aplica más de 30 técnicas diferentes de enmascaramiento de automatización.

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

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url, proxyUrl) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            `--proxy-server=${proxyUrl}`,
            '--disable-blink-features=AutomationControlled',
            '--window-size=1920,1080'
        ]
    });
    
    const page = await browser.newPage();
    
    // Establecer viewport y user-agent
    await page.setViewport({ width: 1920, height: 1080 });
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    
    // Sobrescribir navigator.webdriver
    await page.evaluateOnNewDocument(() => {
        delete Object.getPrototypeOf(navigator).webdriver;
    });
    
    // Navegar a la página
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
    
    // Esperar a que se complete el desafío
    await page.waitForTimeout(8000);
    
    // Obtener contenido y cookies
    const content = await page.content();
    const cookies = await page.cookies();
    
    await browser.close();
    
    return { content, cookies };
}

// Ejemplo de uso
bypassCloudflare('https://example.com', 'http://user:pass@proxy.example.com:8080')
    .then(result => console.log('Éxito'))
    .catch(err => console.error(err));

Rendimiento: Los navegadores sin cabeza consumen significativamente más recursos (200-500 MB de RAM por instancia). Para tareas de alta carga, úsalos solo para obtener cookies, luego cambia a clientes HTTP con esas cookies.

Selección del tipo de proxy para eludir Cloudflare

El tipo de proxy influye críticamente en el éxito de la elusión. Cloudflare mantiene bases de datos de direcciones IP de centros de datos y aplica reglas de verificación más estrictas a ellas.

Tipo de proxy Probabilidad de elusión Velocidad Costo Recomendación
Datacenter 30-40% Alta Baja Solo con navegadores sin cabeza
Residencial 85-95% Media Alta Elección óptima
Móvil 90-98% Media Muy alta Para tareas críticas
ISP (Residencial Estático) 80-90% Alta Media Balance entre precio y calidad

Por qué los proxies residenciales son más efectivos

Los proxies residenciales utilizan direcciones IP de dispositivos reales (enrutadores domésticos, teléfonos inteligentes). Cloudflare no puede bloquear masivamente estas IP, ya que eso bloquearía a los usuarios normales. Las estadísticas muestran que las IP residenciales reciben captcha 15-20 veces menos que los centros de datos.

Al trabajar con proxies residenciales, la geolocalización es crítica. Si el sitio objetivo está orientado a EE.UU., usar proxies de Asia aumentará la sospecha. Elige proveedores con una amplia geografía y la posibilidad de segmentación por ciudades.

Proxies móviles para máxima fiabilidad

Los proxies móviles utilizan direcciones IP de operadores móviles (4G/5G). La característica de las redes móviles es el cambio dinámico de IP a través del modo avión, lo que proporciona prácticamente un número ilimitado de direcciones IP limpias. La probabilidad de bloqueo de una IP móvil es cercana a cero.

# Ejemplo de rotación de IP móvil a través de API
import requests
import time

def rotate_mobile_ip(proxy_api_url):
    """Cambio de IP de proxy móvil"""
    response = requests.get(f"{proxy_api_url}/rotate")
    if response.status_code == 200:
        print("IP cambiada con éxito")
        time.sleep(5)  # Espera para aplicar cambios
        return True
    return False

# Uso con proxy móvil
mobile_proxy = "http://user:pass@mobile.proxy.com:8080"

for i in range(10):
    # Realizar solicitud
    response = requests.get(
        'https://example.com',
        proxies={'http': mobile_proxy, 'https': mobile_proxy}
    )
    
    # Rotar IP después de cada solicitud
    rotate_mobile_ip('https://api.proxy.com/mobile')

Gestión de cookies y sesiones

Después de superar con éxito el desafío de Cloudflare, el servidor establece cookies (cf_clearance, __cfduid y otras) que confirman la legitimidad del cliente. La gestión adecuada de estas cookies permite evitar verificaciones repetidas.

Extracción y reutilización de cf_clearance

La cookie cf_clearance generalmente es válida durante 30-60 minutos. Después de obtenerla a través de un navegador sin cabeza, se puede usar en solicitudes HTTP normales.

import requests
import pickle
from datetime import datetime, timedelta

class CloudflareCookieManager:
    def __init__(self, cookie_file='cf_cookies.pkl'):
        self.cookie_file = cookie_file
        self.cookies = self.load_cookies()
    
    def load_cookies(self):
        """Carga de cookies guardadas"""
        try:
            with open(self.cookie_file, 'rb') as f:
                data = pickle.load(f)
                # Verificación de la fecha de caducidad
                if data['expires'] > datetime.now():
                    return data['cookies']
        except FileNotFoundError:
            pass
        return None
    
    def save_cookies(self, cookies, ttl_minutes=30):
        """Guardado de cookies con TTL"""
        data = {
            'cookies': cookies,
            'expires': datetime.now() + timedelta(minutes=ttl_minutes)
        }
        with open(self.cookie_file, 'wb') as f:
            pickle.dump(data, f)
    
    def get_cf_clearance(self, url, proxy):
        """Obtención de cf_clearance a través del navegador"""
        if self.cookies:
            return self.cookies
        
        # Aquí va el código para iniciar el navegador (de la sección anterior)
        # ...
        browser_cookies = bypass_cloudflare(url, proxy)['cookies']
        
        # Conversión al formato de requests
        cookies_dict = {c['name']: c['value'] for c in browser_cookies}
        self.save_cookies(cookies_dict)
        self.cookies = cookies_dict
        
        return cookies_dict
    
    def make_request(self, url, proxy):
        """Solicitud con gestión automática de cookies"""
        cookies = self.get_cf_clearance(url, proxy)
        
        response = requests.get(
            url,
            cookies=cookies,
            proxies={'http': proxy, 'https': proxy},
            headers=get_random_headers()
        )
        
        # Si se recibe un desafío nuevamente, actualizamos las cookies
        if response.status_code == 403 or 'cf-browser-verification' in response.text:
            print("Cookies caducadas, obteniendo nuevas...")
            self.cookies = None
            return self.make_request(url, proxy)
        
        return response

# Uso
manager = CloudflareCookieManager()
response = manager.make_request(
    'https://example.com/api/data',
    'http://user:pass@proxy.example.com:8080'
)

Vinculación de cookies a la dirección IP

Cloudflare vincula cf_clearance a la dirección IP desde la que se superó el desafío. Usar esta cookie desde otra IP resultará en un bloqueo. Al trabajar con proxies rotativos, es necesario mantener un conjunto separado de cookies para cada IP.

import hashlib

class IPBoundCookieManager:
    def __init__(self):
        self.cookies_by_ip = {}
    
    def get_ip_hash(self, proxy_url):
        """Creación de un hash para identificar el proxy"""
        return hashlib.md5(proxy_url.encode()).hexdigest()
    
    def get_cookies_for_proxy(self, proxy_url, target_url):
        """Obtención de cookies para un proxy específico"""
        ip_hash = self.get_ip_hash(proxy_url)
        
        if ip_hash in self.cookies_by_ip:
            cookies_data = self.cookies_by_ip[ip_hash]
            if cookies_data['expires'] > datetime.now():
                return cookies_data['cookies']
        
        # Obtención de nuevas cookies a través del navegador
        new_cookies = self.fetch_cookies_with_browser(target_url, proxy_url)
        
        self.cookies_by_ip[ip_hash] = {
            'cookies': new_cookies,
            'expires': datetime.now() + timedelta(minutes=30)
        }
        
        return new_cookies

Rotación de proxies y control de la frecuencia de solicitudes

Incluso con la pila técnica correcta, una frecuencia de solicitudes demasiado alta desde una sola IP activa el rate limiting. Cloudflare analiza los patrones de tráfico y detecta actividad anómala.

Estrategias de rotación de proxies

Hay tres enfoques principales para la rotación: round-robin (secuencial), random (aleatorio) y sticky sessions (vinculación a la sesión). Para eludir Cloudflare, la estrategia óptima es sticky sessions con limitación de solicitudes por IP.

import time
import random
from collections import defaultdict
from datetime import datetime, timedelta

class SmartProxyRotator:
    def __init__(self, proxy_list, max_requests_per_ip=20, cooldown_minutes=10):
        self.proxy_list = proxy_list
        self.max_requests_per_ip = max_requests_per_ip
        self.cooldown_minutes = cooldown_minutes
        
        # Contadores de uso
        self.usage_count = defaultdict(int)
        self.last_used = {}
        self.cooldown_until = {}
    
    def get_proxy(self):
        """Obtención del siguiente proxy disponible"""
        available_proxies = []
        
        for proxy in self.proxy_list:
            # Verificación de cooldown
            if proxy in self.cooldown_until:
                if datetime.now() < self.cooldown_until[proxy]:
                    continue
                else:
                    # Reinicio del contador después del cooldown
                    self.usage_count[proxy] = 0
                    del self.cooldown_until[proxy]
            
            # Verificación del límite de solicitudes
            if self.usage_count[proxy] < self.max_requests_per_ip:
                available_proxies.append(proxy)
        
        if not available_proxies:
            # Si todos los proxies están en cooldown, esperamos
            wait_time = min(
                (self.cooldown_until[p] - datetime.now()).total_seconds()
                for p in self.cooldown_until
            )
            print(f"Todos los proxies están en cooldown. Esperando {wait_time:.0f} segundos...")
            time.sleep(wait_time + 1)
            return self.get_proxy()
        
        # Selección del proxy con menor uso
        proxy = min(available_proxies, key=lambda p: self.usage_count[p])
        
        self.usage_count[proxy] += 1
        self.last_used[proxy] = datetime.now()
        
        # Establecimiento de cooldown al alcanzar el límite
        if self.usage_count[proxy] >= self.max_requests_per_ip:
            self.cooldown_until[proxy] = datetime.now() + timedelta(
                minutes=self.cooldown_minutes
            )
            print(f"El proxy {proxy} ha alcanzado el límite. Cooldown de {self.cooldown_minutes} minutos.")
        
        return proxy
    
    def add_delay(self):
        """Retraso aleatorio entre solicitudes (simulación de humano)"""
        delay = random.uniform(2, 5)  # 2-5 segundos
        time.sleep(delay)

# Uso
proxy_pool = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080',
    # ... hasta 50-100 proxies para un funcionamiento estable
]

rotator = SmartProxyRotator(
    proxy_pool,
    max_requests_per_ip=15,  # Valor conservador
    cooldown_minutes=15
)

# Ejecución de solicitudes
for i in range(1000):
    proxy = rotator.get_proxy()
    
    response = requests.get(
        'https://example.com/page',
        proxies={'http': proxy, 'https': proxy},
        headers=get_random_headers()
    )
    
    print(f"Solicitud {i+1}: {response.status_code}")
    rotator.add_delay()

Rate limiting adaptativo

Un enfoque más avanzado es la adaptación dinámica de la frecuencia de solicitudes basada en las respuestas del servidor. Si comienzan a aparecer errores 429 o captchas, automáticamente disminuimos la velocidad.

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=3.0):
        self.delay = initial_delay
        self.min_delay = 1.0
        self.max_delay = 30.0
        self.success_streak = 0
        self.failure_streak = 0
    
    def on_success(self):
        """Solicitud exitosa — se puede acelerar"""
        self.success_streak += 1
        self.failure_streak = 0
        
        if self.success_streak >= 10:
            # Reducimos el retraso en un 10%
            self.delay = max(self.min_delay, self.delay * 0.9)
            self.success_streak = 0
    
    def on_failure(self, status_code):
        """Error — desaceleramos"""
        self.failure_streak += 1
        self.success_streak = 0
        
        if status_code == 429:  # Rate limit
            # Desaceleración agresiva
            self.delay = min(self.max_delay, self.delay * 2.0)
        elif status_code == 403:  # Posible bloqueo
            self.delay = min(self.max_delay, self.delay * 1.5)
        
        print(f"Retraso aumentado a {self.delay:.2f}s")
    
    def wait(self):
        """Espera antes de la siguiente solicitud"""
        # Añadimos aleatoriedad ±20%
        actual_delay = self.delay * random.uniform(0.8, 1.2)
        time.sleep(actual_delay)

Herramientas y bibliotecas listas para usar para eludir

Desarrollar una solución propia desde cero requiere tiempo y experiencia. Existen herramientas listas que automatizan el proceso de eludir Cloudflare.

cloudscraper (Python)

La biblioteca cloudscraper es una extensión de requests que resuelve automáticamente desafíos de JavaScript. Funciona con protecciones básicas, pero puede no manejar verificaciones avanzadas.

import cloudscraper

# Creación de scraper con soporte de proxy
scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

# Configuración del proxy
proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'http://user:pass@proxy.example.com:8080'
}

# Ejecución de la solicitud
response = scraper.get('https://example.com', proxies=proxies)

if response.status_code == 200:
    print("Elusión exitosa")
    print(response.text)
else:
    print(f"Error: {response.status_code}")

FlareSolverr (universal)

FlareSolverr es un servidor proxy que ejecuta un navegador sin cabeza para resolver desafíos de Cloudflare. Funciona a través de una API HTTP y es compatible con cualquier lenguaje de programación.

# Ejecución de FlareSolverr a través de Docker
docker run -d \
  --name=flaresolverr \
  -p 8191:8191 \
  -e LOG_LEVEL=info \
  ghcr.io/flaresolverr/flaresolverr:latest

# Uso desde Python
import requests

def solve_cloudflare(url, proxy=None):
    flaresolverr_url = "http://localhost:8191/v1"
    
    payload = {
        "cmd": "request.get",
        "url": url,
        "maxTimeout": 60000
    }
    
    if proxy:
        payload["proxy"] = {
            "url": proxy
        }
    
    response = requests.post(flaresolverr_url, json=payload)
    result = response.json()
    
    if result['status'] == 'ok':
        return {
            'html': result['solution']['response'],
            'cookies': result['solution']['cookies'],
            'user_agent': result['solution']['userAgent']
        }
    else:
        raise Exception(f"Error de FlareSolverr: {result['message']}")

# Ejemplo de uso
result = solve_cloudflare(
    'https://example.com',
    proxy='http://user:pass@proxy.example.com:8080'
)

print(result['html'])

undetected-chromedriver

Versión parcheada de Selenium ChromeDriver que aplica automáticamente muchas técnicas anti-detect. Más fácil de usar que Playwright, pero menos flexible.

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def bypass_with_uc(url, proxy):
    options = uc.ChromeOptions()
    options.add_argument(f'--proxy-server={proxy}')
    options.add_argument('--disable-blink-features=AutomationControlled')
    
    driver = uc.Chrome(options=options, version_main=120)
    
    try:
        driver.get(url)
        
        # Esperar a que desaparezca el desafío de Cloudflare
        WebDriverWait(driver, 20).until_not(
            EC.presence_of_element_located((By.ID, "cf-spinner-please-wait"))
        )
        
        # Espera adicional para mayor fiabilidad
        time.sleep(3)
        
        # Obtener el resultado
        html = driver.page_source
        cookies = driver.get_cookies()
        
        return {'html': html, 'cookies': cookies}
    
    finally:
        driver.quit()

# Uso
result = bypass_with_uc(
    'https://example.com',
    'http://user:pass@proxy.example.com:8080'
)

Enfoque combinado: La estrategia óptima es utilizar un navegador sin cabeza solo para la obtención inicial de cookies, luego cambiar a clientes HTTP (tls-client, cloudscraper) con esas cookies. Esto proporciona un equilibrio entre fiabilidad y rendimiento.

Conclusión

Eludir Cloudflare al trabajar a través de proxies requiere un enfoque integral: un TLS fingerprint correcto, encabezados HTTP auténticos, proxies de calidad y una gestión adecuada de sesiones. Recomendaciones clave:

  • Utiliza proxies residenciales o móviles en lugar de centros de datos
  • Aplica bibliotecas con el TLS fingerprint correcto (tls-client, curl-impersonate)
  • Para casos complejos, utiliza navegadores sin cabeza con parches anti-detect
  • Guarda y reutiliza las cookies cf_clearance
  • Rota los proxies teniendo en cuenta el rate limiting (no más de 15-20 solicitudes por IP)
  • Agrega retrasos aleatorios entre solicitudes (2-5 segundos)

La protección de Cloudflare evoluciona constantemente, por lo que es importante actualizar regularmente las herramientas y adaptar las estrategias. Monitorea los cambios en las técnicas de fingerprinting y prueba las soluciones en las versiones actuales de protección.

Para un funcionamiento estable, se recomienda utilizar servicios de proxy profesionales con un amplio pool de IP y rotación automática.

```