Volver al blog

Cómo ocultar el uso de Selenium y Puppeteer

Descubre cómo ocultar eficazmente el uso de Selenium y Puppeteer de los sistemas de protección contra bots. Métodos prácticos, ejemplos de código y técnicas comprobadas de enmascaramiento de la automatización.

📅26 de diciembre de 2025
```html

Guía completa para ocultar Selenium y Puppeteer de la detección

Los sistemas modernos de protección contra bots pueden reconocer fácilmente los navegadores automatizados por decenas de signos: desde variables de JavaScript hasta características del comportamiento de WebDriver. Los sitios utilizan Cloudflare, DataDome, PerimeterX y soluciones propias que bloquean hasta el 90% de las solicitudes de Selenium y Puppeteer en su configuración estándar.

En esta guía, analizaremos todos los métodos de ocultación de la automatización: desde configuraciones básicas hasta técnicas avanzadas para eludir la detección. Obtendrás soluciones listas con ejemplos de código para Python y Node.js, que funcionan contra la mayoría de los sistemas de protección.

Cómo los sitios detectan la automatización

Los sistemas de protección contra bots analizan el navegador por múltiples parámetros al mismo tiempo. Incluso si ocultas un signo, los demás revelarán la automatización. Comprender todos los métodos de detección es clave para una ocultación efectiva.

Indicadores de WebDriver

El método más simple de detección es la verificación de variables de JavaScript que solo están presentes en navegadores automatizados:

// Estas variables revelan Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // Variable específica de ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // Los navegadores automatizados no tienen plugins
navigator.languages === "" // Lista de idiomas vacía

Cloudflare y sistemas similares verifican estas propiedades en primer lugar. Si al menos una devuelve un resultado positivo, la solicitud es bloqueada.

Fingerprinting del navegador

Los sistemas avanzados crean una huella única del navegador basada en decenas de parámetros:

  • Fingerprinting de Canvas — renderizado de imágenes ocultas y análisis de datos de píxeles
  • Fingerprinting de WebGL — parámetros del renderizador gráfico y la tarjeta de video
  • Contexto de Audio — características únicas del procesamiento de audio
  • Fingerprinting de Fuentes — lista de fuentes instaladas en el sistema
  • Resolución de Pantalla — resolución de pantalla, profundidad de color, área disponible
  • Zona Horaria y Lenguaje — zona horaria, idiomas del navegador, configuración regional del sistema

Los navegadores automatizados a menudo tienen combinaciones atípicas de estos parámetros. Por ejemplo, Chrome sin cabeza no tiene plugins, pero soporta WebGL; tal combinación es extremadamente rara entre usuarios reales.

Análisis del comportamiento

Los sistemas modernos rastrean patrones de comportamiento:

  • Movimientos del ratón — los bots mueven el cursor en líneas rectas o no lo mueven en absoluto
  • Velocidad de las acciones — llenado instantáneo de formularios, velocidad de clics no humana
  • Patrones de desplazamiento — saltos bruscos en lugar de desplazamiento suave
  • Eventos del teclado — ausencia de retrasos naturales entre pulsaciones
  • Frecuencia de solicitudes — intervalos demasiado regulares entre acciones

Importante: DataDome y PerimeterX utilizan aprendizaje automático para analizar el comportamiento. Están entrenados en millones de sesiones y pueden reconocer un bot incluso con la ocultación técnica correcta, si el comportamiento parece poco natural.

Ocultación básica de Selenium

Selenium WebDriver en su configuración estándar deja muchas huellas. Veamos una configuración paso a paso para minimizar la detección usando Python y ChromeDriver.

Desactivación de la bandera webdriver

El primer paso es ocultar la variable navigator.webdriver. Esto se hace a través del Protocolo de DevTools de Chrome:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Configuración de opciones de Chrome
chrome_options = Options()

# Desactivamos la bandera de automatización
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# Creamos el driver
driver = webdriver.Chrome(options=chrome_options)

# Eliminamos webdriver a través de CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://example.com')

Configuración de User-Agent y otros encabezados

Los navegadores sin cabeza a menudo utilizan cadenas de User-Agent obsoletas o específicas. Es necesario establecer un User-Agent actual de un navegador real:

# User-Agent actual de Chrome en Windows
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'
chrome_options.add_argument(f'user-agent={user_agent}')

# Argumentos adicionales para la ocultación
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')

# Tamaño de ventana como un usuario real
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

Adición de plugins y lenguajes

Los navegadores automatizados no tienen plugins y a menudo muestran una lista de idiomas vacía. Corregimos esto a través de CDP:

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['es-ES', 'es', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf", description: ""},
                    description: "",
                    filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
                    length: 1,
                    name: "Chrome PDF Viewer"
                }
            ]
        });
        
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
    '''
})

Ejemplo completo de configuración de Selenium

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

def create_stealth_driver():
    chrome_options = Options()
    
    # Configuraciones básicas de ocultación
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    chrome_options.add_argument('--disable-blink-features=AutomationControlled')
    
    # User-Agent
    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'
    chrome_options.add_argument(f'user-agent={user_agent}')
    
    # Tamaño de ventana
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Script de ocultación a través de CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['es-ES', 'es']});
        Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
        
        window.chrome = {
            runtime: {}
        };
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
    '''
    
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': stealth_script
    })
    
    return driver

# Uso
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # Sitio para verificar la detección

Configuración de Puppeteer para eludir la detección

Puppeteer tiene los mismos problemas de detección que Selenium. Sin embargo, para Node.js existe una biblioteca lista llamada puppeteer-extra-plugin-stealth, que automatiza la mayoría de las configuraciones de ocultación.

Instalación de puppeteer-extra

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

Configuración básica con el plugin stealth

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

// Conectamos el plugin de ocultación
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // Nuevo modo sin cabeza de Chrome
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-accelerated-2d-canvas',
            '--disable-gpu',
            '--window-size=1920,1080',
            '--disable-web-security',
            '--disable-features=IsolateOrigins,site-per-process'
        ]
    });
    
    const page = await browser.newPage();
    
    // Establecemos el viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // Establecemos User-Agent
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
    
    // Encabezados adicionales
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'es-ES,es;q=0.9',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    });
    
    await page.goto('https://bot.sannysoft.com/');
    
    // Captura de pantalla para verificar
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

Configuración manual sin plugins

Si deseas control total o no puedes usar bibliotecas de terceros, configura la ocultación manualmente:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // Sobrescribimos webdriver y otras propiedades
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['es-ES', 'es']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // Ocultamos Chrome sin cabeza
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // Sobrescribimos permisos
        const originalQuery = window.navigator.permissions.query;
        window.navigator.permissions.query = (parameters) => (
            parameters.name === 'notifications' ?
                Promise.resolve({ state: Notification.permission }) :
                originalQuery(parameters)
        );
    });
    
    await page.goto('https://example.com');
    await browser.close();
})();

Configuración para eludir Cloudflare

Cloudflare utiliza métodos avanzados de detección. Para eludirlo, es necesario agregar retrasos aleatorios y emulación de acciones:

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

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-web-security'
        ]
    });
    
    const page = await browser.newPage();
    
    // User-Agent aleatorio
    const userAgents = [
        '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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    ];
    await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
    
    // Navegación a la página
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // Esperamos la verificación de Cloudflare (generalmente de 5 a 10 segundos)
    await page.waitForTimeout(8000);
    
    // Movimiento aleatorio del ratón
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

Lucha contra el fingerprinting de JavaScript

El fingerprinting de JavaScript es la creación de una huella única del navegador basada en múltiples parámetros. Incluso si ocultas el webdriver, los sistemas analizan cientos de otras propiedades para detectar la automatización.

Principales vectores de fingerprinting

Los sistemas de protección contra bots verifican los siguientes parámetros:

Parámetro Qué se verifica Riesgo de detección
navigator.webdriver Presencia de la bandera de automatización Crítico
navigator.plugins Número y tipos de plugins Alto
window.chrome Presencia de la API de Chrome Medio
navigator.permissions API de permisos del navegador Medio
screen.colorDepth Profundidad de color de la pantalla Bajo
navigator.hardwareConcurrency Número de núcleos del procesador Bajo

Script de ocultación integral

El siguiente script sobrescribe la mayoría de las propiedades problemáticas. Implémenlo a través de CDP (Selenium) o evaluateOnNewDocument (Puppeteer):

const stealthScript = `
    // Eliminamos webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // Agregamos objeto chrome
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // Sobrescribimos permisos
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // Ocultamos plugins
    Object.defineProperty(navigator, 'plugins', {
        get: () => {
            return [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Viewer"
                },
                {
                    0: {type: "application/x-nacl"},
                    description: "Native Client Executable",
                    filename: "internal-nacl-plugin",
                    length: 2,
                    name: "Native Client"
                }
            ];
        }
    });
    
    // Idiomas
    Object.defineProperty(navigator, 'languages', {
        get: () => ['es-ES', 'es']
    });
    
    // Plataforma
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // Vendedor
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // Eliminamos huellas de Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // API de batería (ausente en headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

Eliminación de propiedades de WebDriver

ChromeDriver y otras implementaciones de WebDriver añaden variables específicas al ámbito global. Estas variables comienzan con el prefijo cdc_ y son fácilmente detectables por los sistemas de protección.

Detección de variables cdc

Puedes verificar la presencia de estas variables con un simple script:

// Búsqueda de todas las variables cdc
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('Variable WebDriver detectada:', key);
    }
}

// Variables típicas de ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

Método 1: Eliminación a través de CDP

La forma más confiable es eliminar las variables antes de cargar la página a través del Protocolo de DevTools de Chrome:

from selenium import webdriver

driver = webdriver.Chrome()

# Eliminamos todas las variables cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // Eliminamos las variables cdc conocidas
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // Eliminamos todas las variables que contienen 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

Método 2: Modificación de ChromeDriver

Un enfoque más radical es modificar el archivo binario de ChromeDriver, reemplazando la cadena cdc_ por otra secuencia de caracteres. Esto evita la creación de estas variables:

import re

def patch_chromedriver(driver_path):
    """
    Parchea ChromeDriver reemplazando 'cdc_' por una cadena aleatoria
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # Reemplazamos todas las ocurrencias de 'cdc_' por 'dog_' (o cualquier otra cadena de la misma longitud)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver parcheado: {driver_path}')

# Uso
patch_chromedriver('/path/to/chromedriver')

Atención: La modificación del archivo binario de ChromeDriver puede interrumpir su funcionamiento. Siempre haz una copia de seguridad antes de aplicar el parche. Este método no funciona con todas las versiones de ChromeDriver.

Método 3: Uso de undetected-chromedriver

La biblioteca undetected-chromedriver parchea automáticamente ChromeDriver al iniciarlo:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# Creación del driver con parcheo automático
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # Sitio para verificar la detección
input('Presiona Enter para cerrar...')
driver.quit()

Ocultación de Canvas, WebGL y Audio API

El fingerprinting de Canvas, WebGL y Audio son métodos para crear una huella única basada en características de renderizado gráfico y procesamiento de sonido. Cada combinación de navegador, SO y hardware da un resultado único.

Fingerprinting de Canvas

Los sistemas dibujan una imagen oculta en Canvas y analizan los píxeles resultantes. Los navegadores sin cabeza a menudo dan resultados atípicos debido a la falta de aceleración GPU.

// Código típico de Fingerprinting de Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Huella del navegador', 2, 2);
const fingerprint = canvas.toDataURL();

Para protegerse, se puede agregar ruido aleatorio a la API de Canvas:

const canvasNoiseScript = `
    // Agregamos ruido aleatorio a Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // Función para agregar ruido
    const addNoise = (canvas, context) => {
        const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            // Agregamos ruido mínimo a RGB (no visible al ojo)
            imageData.data[i] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
        }
        context.putImageData(imageData, 0, 0);
    };
    
    // Sobrescribimos toDataURL
    HTMLCanvasElement.prototype.toDataURL = function() {
        if (this.width > 0 && this.height > 0) {
            const context = this.getContext('2d');
            addNoise(this, context);
        }
        return originalToDataURL.apply(this, arguments);
    };
`;

Fingerprinting de WebGL

WebGL proporciona información sobre la tarjeta gráfica y los controladores. Los navegadores sin cabeza a menudo muestran SwiftShader (renderizador por software) en lugar de la GPU real:

const webglMaskScript = `
    // Ocultamos parámetros de WebGL
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        // UNMASKED_VENDOR_WEBGL
        if (parameter === 37445) {
            return 'Intel Inc.';
        }
        // UNMASKED_RENDERER_WEBGL
        if (parameter === 37446) {
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter.call(this, parameter);
    };
    
    // También para WebGL2
    if (typeof WebGL2RenderingContext !== 'undefined') {
        const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
        WebGL2RenderingContext.prototype.getParameter = function(parameter) {
            if (parameter === 37445) {
                return 'Intel Inc.';
            }
            if (parameter === 37446) {
                return 'Intel Iris OpenGL Engine';
            }
            return getParameter2.call(this, parameter);
        };
    }
`;

Fingerprinting del Contexto de Audio

La API de Audio también proporciona una huella única. Agregamos ruido al procesamiento de audio:

const audioMaskScript = `
    // Agregamos ruido al Contexto de Audio
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.call(this);
            const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                originalGetFloatFrequencyData.call(this, array);
                // Agregamos ruido mínimo
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

Imitación del comportamiento humano

Incluso con una ocultación técnica perfecta, los bots se delatan por su comportamiento. Los sistemas de aprendizaje automático analizan patrones de movimientos del ratón, velocidad de acciones y secuencia de eventos.

Retrasos aleatorios entre acciones

Nunca uses retrasos fijos. Los usuarios reales hacen pausas de diferentes duraciones:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """Retraso aleatorio que imita a un humano"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# Uso
driver.get('https://example.com')
human_delay(2, 4)  # Pausa de 2 a 4 segundos

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # Pausa corta antes de introducir

element.send_keys('consulta de búsqueda')
human_delay(1, 2)

Movimiento suave del ratón

Los bots mueven el ratón en líneas rectas o teletransportan el cursor. Los usuarios reales crean trayectorias curvas con aceleración y desaceleración:

// Puppeteer: movimiento suave del ratón
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // Número de puntos intermedios
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // Usamos easing para suavidad
        const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        
        const x = currentPos.x + (targetX - currentPos.x) * ease;
        const y = currentPos.y + (targetY - currentPos.y) * ease;
        
        await page.mouse.move(x, y);
        await page.waitForTimeout(Math.random() * 10 + 5);
    }
    
    // Guardamos la posición
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// Uso
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

Desplazamiento natural

Los usuarios reales desplazan suavemente, con paradas para leer contenido:

async function humanScroll(page) {
    const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
    const viewportHeight = await page.evaluate(() => window.innerHeight);
    
    let currentPosition = 0;
    
    while (currentPosition < scrollHeight - viewportHeight) {
        // Paso de desplazamiento aleatorio (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // Desplazamiento suave
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // Pausa para "leer" contenido (1-3 segundos)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// Uso
await page.goto('https://example.com');
await humanScroll(page);

Entrada de texto natural

Las personas escriben a diferentes velocidades, cometen errores tipográficos y los corrigen:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // Retraso aleatorio entre pulsaciones (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% de probabilidad de error tipográfico
        if (Math.random() < 0.05) {
            // Escribimos un carácter aleatorio
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // Borramos (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// Uso
await humanTypeText(page, '#search-input', 'consulta de búsqueda de ejemplo');

Integración de proxies para total anonimato

La ocultación del navegador es inútil si todas las solicitudes provienen de una sola dirección IP. Los sistemas de protección contra bots rastrean la cantidad de solicitudes de cada IP y bloquean la actividad sospechosa. Los proxies son un componente esencial de cualquier automatización seria.

Selección del tipo de proxy

Diferentes tareas requieren diferentes tipos de proxies:

Tipo de proxy Ventajas Aplicación
Proxy Residencial IP reales, menos bloqueos Raspado de datos, acceso a contenido georestringido
Proxy de Centro de Datos Rápido y económico Pruebas, automatización de tareas
Proxy Móvil IP de dispositivos móviles, alta rotación Acceso a aplicaciones móviles, scraping de redes sociales

Bibliotecas y herramientas listas

Existen varias bibliotecas y herramientas que pueden facilitar el proceso de ocultación:

  • puppeteer-extra — Extensión de Puppeteer con plugins de ocultación.
  • selenium-stealth — Librería para ocultar Selenium.
  • undetected-chromedriver — ChromeDriver que evita la detección.

Pruebas de nivel de detección

Es importante probar el nivel de detección de tu configuración. Puedes usar herramientas como Sannysoft Bot Detection para verificar la efectividad de tus métodos de ocultación.

Conclusión

Ocultar la automatización de navegadores es un desafío constante, ya que las técnicas de detección evolucionan. Sin embargo, con las estrategias y herramientas adecuadas, puedes mejorar significativamente tus posibilidades de éxito. Mantente actualizado con las últimas tendencias y técnicas para asegurar la efectividad de tus métodos de ocultación.

```