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.