Automatizacion de navegador con Puppeteer y perfiles de huella digital
Guia completa para integrar Puppeteer con perfiles de navegador consistentes con huella digital, soporte de proxy y despliegue en produccion.
Prefieres la documentación del producto mantenida?
Este artículo tiene una página equivalente en el centro de documentación. Usa los docs para el flujo canónico, las flags actuales y la referencia duradera.
Introduccion
Puppeteer es la biblioteca de Node.js de Google para controlar Chrome a traves del Chrome DevTools Protocol (CDP). Proporciona una API de alto nivel para navegacion, captura de pantallas, interaccion con formularios, intercepcion de red y mas. BotBrowser reemplaza el binario estandar de Chromium con uno que produce una salida de huella digital consistente controlada por archivos de perfil. Puppeteer maneja la automatizacion, BotBrowser maneja la identidad.
Esta guia cubre la integracion completa: instalacion, configuracion de lanzamiento, gestion de viewport, configuracion de proxy, acceso CDP, despliegue en produccion en servidores Linux y resolucion de problemas comunes. Al final, tendras una configuracion funcional de Puppeteer + BotBrowser lista para uso en desarrollo y produccion.
Impacto en la privacidad: por que Puppeteer + BotBrowser
Puppeteer estandar lanza un binario de Chromium basico que expone la huella digital real de la maquina host. Cada instancia de navegador comparte la misma GPU, fuentes, resolucion de pantalla y caracteristicas de plataforma. Los indicadores de automatizacion como navigator.webdriver tambien estan presentes, dejando claro que el navegador esta siendo controlado programaticamente.
Con BotBrowser, cada instancia de Puppeteer puede cargar un perfil de huella digital diferente, dandole una identidad de navegador unica. La huella digital se aplica a nivel del motor, antes de que cualquier pagina se cargue y antes de que cualquier JavaScript se ejecute. Tu codigo de automatizacion de Puppeteer no necesita cambiar en absoluto. El control de identidad ocurre a nivel de configuracion de lanzamiento.
Esto hace posible ejecutar multiples instancias concurrentes de Puppeteer, cada una con un perfil de huella digital distinto, proxy, zona horaria y configuracion regional, todo desde la misma maquina host. La separacion es limpia: Puppeteer controla lo que el navegador hace, BotBrowser controla lo que el navegador es.
Contexto tecnico
Por que puppeteer-core y no puppeteer
El paquete npm estandar puppeteer incluye su propio binario de Chromium. Durante la instalacion, descarga una version especifica de Chromium gestionada por el equipo de Puppeteer. Este binario no incluye las capacidades de control de huella digital de BotBrowser.
El paquete puppeteer-core proporciona la misma API sin navegadores incluidos. Requiere que especifiques un executablePath al lanzar, que es como apuntas Puppeteer al binario de BotBrowser.
# Instalar puppeteer-core, no puppeteer
npm install puppeteer-core
La configuracion defaultViewport
Puppeteer tiene un comportamiento predeterminado critico: establece un defaultViewport de 800x600 pixeles en cada nueva pagina. Esto sobreescribe cualquier dimension de viewport definida en el perfil de huella digital de BotBrowser, causando discrepancias entre el tamano de pantalla reportado (del perfil) y el tamano real del viewport (800x600 de Puppeteer).
Siempre establece defaultViewport: null para prevenir esta sobreescritura y dejar que el perfil de BotBrowser controle las dimensiones del viewport.
Acceso CDP
Puppeteer proporciona acceso directo a CDP a traves de objetos CDPSession. Esto es importante para BotBrowser porque algunas funciones avanzadas se controlan a traves de comandos CDP personalizados:
// Sesion CDP a nivel de navegador
const cdpSession = await browser.target().createCDPSession();
// Comandos CDP de BotBrowser
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'X-Custom': 'value' }
});
Ten en cuenta que los comandos CDP de BotBrowser deben enviarse a la sesion a nivel de navegador, no a una sesion a nivel de pagina. Usar page.createCDPSession() resultara en un error de "metodo no encontrado" para comandos especificos de BotBrowser.
Enfoques comunes y sus limitaciones
Uso del navegador incluido de Puppeteer
El Chromium incluido de Puppeteer funciona para automatizacion basica pero no proporciona control de huella digital. Cada instancia tiene la misma huella digital, y las senales de automatizacion son detectables.
Plugins stealth
El paquete puppeteer-extra-plugin-stealth parchea algunos indicadores de automatizacion a traves de inyeccion de JavaScript. Sin embargo, opera en el nivel incorrecto. La inyeccion de JavaScript ocurre despues de la creacion de la pagina y puede ser detectada a traves de analisis de tiempo, inspeccion de la cadena de prototipos y otras tecnicas. Tampoco controla senales a nivel de renderizado como la salida de Canvas, las cadenas de renderizado de WebGL o la disponibilidad de fuentes.
Configuracion manual de User-Agent
Puppeteer permite establecer un User-Agent personalizado con page.setUserAgent(). Esto cambia una senal pero deja todas las demas (plataforma, fuentes, GPU, metricas de pantalla) en sus valores reales. La inconsistencia entre el User-Agent y otras senales es en si misma una senal detectable.
Enfoque de BotBrowser
BotBrowser se integra con Puppeteer a traves del parametro estandar executablePath en puppeteer.launch(). No se necesitan plugins, parches ni middleware.
Integracion sin cambios de codigo
Agregar BotBrowser a un proyecto existente de Puppeteer requiere cambiar solo la configuracion de lanzamiento. Todo el codigo a nivel de pagina (selectores, navegacion, extraccion de datos) permanece exactamente igual.
Senales a nivel del motor
El perfil de huella digital se carga durante la inicializacion del navegador. Para cuando Puppeteer se conecta via CDP, todas las senales ya estan en su lugar. No hay condicion de carrera, no hay fase de configuracion y no hay riesgo de que la huella digital real se exponga durante el inicio.
Compatibilidad CDP completa
BotBrowser extiende el CDP estandar con comandos personalizados para funciones avanzadas como encabezados personalizados y configuracion por contexto. Todos los comandos CDP estandar continuan funcionando como estan documentados.
Configuracion y uso
Prerrequisitos
- Binario de BotBrowser (descargar desde GitHub)
- Un archivo de perfil de huella digital (formato
.enc) - Node.js 18+
npm install puppeteer-core
Asegurate de que el binario de BotBrowser tenga permisos de ejecucion:
chmod +x /path/to/botbrowser/chrome
Lanzamiento basico
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
defaultViewport: null, // Critico: dejar que el perfil controle el viewport
});
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log('Titulo de la pagina:', title);
await browser.close();
})();
Perfil + proxy + configuracion regional
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--proxy-server=socks5://user:pass@proxy:1080',
'--bot-config-timezone=Europe/London',
'--bot-config-locale=en-GB',
'--bot-config-languages=en-GB,en',
],
headless: true,
defaultViewport: null,
});
Configuracion completa de identidad
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--proxy-server=socks5://user:pass@us-proxy:1080',
'--bot-config-timezone=America/New_York',
'--bot-config-locale=en-US',
'--bot-config-languages=en-US,en',
'--bot-inject-random-history',
'--bot-bookmarks=[{"title":"Google","type":"url","url":"https://www.google.com"}]',
'--bot-cookies=@/path/to/cookies.json',
'--bot-always-active',
],
headless: true,
defaultViewport: null,
});
Multiples identidades
async function createSession(profilePath, proxyUrl, timezone) {
const args = [
`--bot-profile=${profilePath}`,
];
if (proxyUrl) args.push(`--proxy-server=${proxyUrl}`);
if (timezone) args.push(`--bot-config-timezone=${timezone}`);
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args,
headless: true,
defaultViewport: null,
});
return browser;
}
// Lanzar multiples identidades distintas
const sessions = await Promise.all([
createSession('/profiles/win11-us.enc', 'socks5://u:p@us:1080', 'America/New_York'),
createSession('/profiles/win11-de.enc', 'socks5://u:p@de:1080', 'Europe/Berlin'),
createSession('/profiles/android-jp.enc', 'socks5://u:p@jp:1080', 'Asia/Tokyo'),
]);
Intercepcion de red
const page = await browser.newPage();
// Habilitar intercepcion de solicitudes
await page.setRequestInterception(true);
page.on('request', request => {
if (request.resourceType() === 'image') {
request.abort();
} else {
request.continue();
}
});
await page.goto('https://example.com');
Captura de pantalla y PDF
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle0' });
// Captura de pantalla
await page.screenshot({ path: 'screenshot.png', fullPage: true });
// PDF
await page.pdf({ path: 'page.pdf', format: 'A4' });
Headless en Ubuntu
Para servidores Linux, establece la variable de entorno DISPLAY:
const puppeteer = require('puppeteer-core');
// Establecer DISPLAY antes de lanzar
process.env.DISPLAY = ':10.0';
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
defaultViewport: null,
});
O establecelo en la shell antes de ejecutar tu script:
DISPLAY=:10.0 node script.js
Verificacion
Verifica la integracion comprobando las senales de huella digital:
const page = await browser.newPage();
await page.goto('https://example.com');
const fingerprint = await page.evaluate(() => ({
userAgent: navigator.userAgent,
platform: navigator.platform,
languages: navigator.languages,
hardwareConcurrency: navigator.hardwareConcurrency,
deviceMemory: navigator.deviceMemory,
webdriver: navigator.webdriver,
screenWidth: screen.width,
screenHeight: screen.height,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
dpr: devicePixelRatio,
touchPoints: navigator.maxTouchPoints,
}));
console.log('Huella digital:', JSON.stringify(fingerprint, null, 2));
Mejores practicas
- Siempre establece
defaultViewport: null. Esta es la configuracion mas importante. Sin ella, Puppeteer sobreescribe el viewport del perfil a 800x600. - Usa
puppeteer-core, no el paquete completopuppeteer. El paquete completo descarga un binario de Chromium innecesario. - Usa rutas absolutas para
--bot-profiley otras banderas basadas en archivos. Las rutas relativas pueden resolverse incorrectamente. - Cierra las instancias del navegador cuando termines. Cada instancia es un proceso de Chrome. No cerrarlas desperdicia memoria y CPU.
- Establece
DISPLAY=:10.0en servidores Linux, incluso para el modo headless. - Maneja los errores con cuidado. Envuelve el lanzamiento y la navegacion en bloques try/catch. Los lanzamientos del navegador pueden fallar por dependencias faltantes o rutas incorrectas.
Preguntas frecuentes
¿Puedo usar el paquete completo puppeteer en lugar de puppeteer-core?
Tecnicamente si, pero descargara un binario de Chromium innecesario durante npm install. Usa puppeteer-core para ahorrar espacio en disco y dejar claro que estas usando un binario de navegador personalizado.
¿Necesito puppeteer-extra o plugins stealth?
No. BotBrowser maneja el control de huella digital a nivel del motor. Los plugins stealth agregan parches a nivel de JavaScript que son innecesarios con BotBrowser y pueden interferir con su operacion.
¿Por que mi viewport muestra 800x600?
Olvidaste establecer defaultViewport: null en las opciones de lanzamiento. Este es el comportamiento predeterminado de Puppeteer. Agrega defaultViewport: null para dejar que el perfil de BotBrowser controle el viewport.
¿Como manejo la autenticacion de proxy?
BotBrowser extiende --proxy-server para aceptar credenciales integradas: --proxy-server=socks5://user:pass@host:port. No uses page.authenticate() de Puppeteer para la autenticacion de proxy, ya que puede desactivar la geolocalizacion automatica de BotBrowser.
¿Puedo usar browser.createBrowserContext() de Puppeteer para proxy por contexto?
BotBrowser soporta proxy por contexto a traves de su propio mecanismo (ENT Tier1). Usar createBrowserContext({ proxyServer }) con sintaxis compatible con Playwright depende de tu version de Puppeteer y tu nivel de BotBrowser.
¿Como depuro si el perfil no se esta cargando?
Verifica estos problemas comunes:
- La ruta del perfil es absoluta y el archivo existe
- El binario de BotBrowser tiene permisos de ejecucion
- Usa las banderas
--bot-internal --v=1para habilitar el registro de depuracion - Verifica la salida de consola del navegador para errores de carga de perfil
¿Que version de Node.js se requiere?
Se recomienda Node.js 18 o superior. Puppeteer-core requiere un minimo de Node.js 16.
¿Puedo usar TypeScript?
Si. puppeteer-core incluye definiciones de tipos TypeScript:
import puppeteer, { Browser, Page } from 'puppeteer-core';
Resumen
Integrar BotBrowser con Puppeteer requiere instalar puppeteer-core, apuntar executablePath al binario de BotBrowser, agregar --bot-profile a los argumentos de lanzamiento y establecer defaultViewport: null. Todas las funciones estandar de Puppeteer funcionan sin modificacion.
Para temas relacionados, consulta Primeros pasos con Playwright para el equivalente con Playwright, Recetas CLI para combinaciones de banderas, Configuracion de servidor headless para despliegue en produccion, y Gestion de perfiles para organizar perfiles.
Artículos Relacionados
Lleva BotBrowser de la investigación a producción
Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.