Volver al Blog
Despliegue

Señales de automatización y coherencia en Playwright

Qué señales de automatización pueden exponer Playwright y Puppeteer, por qué los parches tardíos de JavaScript son frágiles y cómo verificar tu configuración con BotBrowser.

BotBrowser Team

Documentación

Quieres la documentación estructurada de Despliegue?

Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.

Las sesiones de Playwright y Puppeteer pueden mostrar a una página varias señales relacionadas con la automatización: el indicador navigator.webdriver, los enlaces del framework en el contexto de la página, los efectos secundarios del Chrome DevTools Protocol (CDP) y las diferencias entre ejecuciones headless y con ventana. Con un perfil cargado, BotBrowser controla navigator.webdriver y, en ENT Tier1, evita que los eventos CDP protegidos de consola y ejecución cambien lo que la página puede observar. Tu propio código de prueba sigue siendo responsable de los enlaces del framework, de la configuración del viewport y de mantener coherentes el proxy, el perfil y el comportamiento del tráfico. Las secciones siguientes describen cada categoría de señal, explican por qué los parches aplicados después de cargar la página son más débiles que el control en el propio navegador y muestran cómo verificar el resultado en tu entorno de pruebas.

Dos columnas que muestran qué controla un perfil cargado de BotBrowser en las señales de automatización y qué debe resolver el código de prueba y su configuración.

Qué señales de automatización puede ver una página

Un framework de automatización necesita puntos de enganche en el navegador para funcionar. Esos puntos viven en el mismo navegador que muestra la página, así que parte de ellos puede leerse con el JavaScript que se ejecuta allí. En la práctica importan cuatro categorías, y cada una tiene un responsable distinto cuando quieres una configuración de pruebas coherente.

El indicador navigator.webdriver

La especificación W3C WebDriver define navigator.webdriver como una forma de que la página sepa que el navegador está bajo control automatizado. Se diseñó como mecanismo de transparencia, por lo que una sesión automatizada de Chromium estándar normalmente devuelve true. Es una de las señales más fáciles de leer, porque una sola expresión la devuelve. Por eso es también el primer valor que conviene revisar cuando un entorno de pruebas se comporta de forma inesperada.

Enlaces del framework

Playwright añade al contexto de la página nombres auxiliares como __playwright__binding__ y __pwInitScripts para que el framework pueda comunicarse con ella. Estos nombres existen por la forma en que el framework se comunica con el navegador. Son requisitos de diseño, no defectos. Puppeteer no inyecta los mismos enlaces, así que su principal punto de coherencia es otro: si su viewport predeterminado sigue activo, las dimensiones de la ventana dejan de coincidir con el perfil.

Efectos secundarios de CDP

Playwright y Puppeteer controlan Chromium mediante CDP. Algunas comprobaciones de coherencia en tiempo de ejecución pueden deducir una conexión CDP a partir de cambios que la automatización puede provocar en el comportamiento de la consola o de las excepciones, por ejemplo cuando un cliente activa los dominios Console o Runtime. Esta señal es de comportamiento y no una propiedad visible, así que una comprobación limpia de propiedades no la descarta.

De la protección que se describe más adelante se deriva una consecuencia práctica: cuando la supresión de consola está activa, tu cliente de automatización no recibe los mensajes de consola de la página. Los equipos que dependen de un controlador de eventos de consola en sus propios scripts deben prever esto antes de la primera ejecución en producción.

Diferencias entre headless y con ventana

Una sesión headless y una sesión con ventana pueden diferir en geometría de pantalla, listas de plugins y comportamiento gráfico. Un perfil aporta los mismos valores previstos a ambos modos, pero el servicio de pantalla del host y el backend gráfico siguen influyendo en lo que mide una página. Compara los modos que realmente usas en tu propio entorno en lugar de suponer que coinciden. La guía sobre coherencia de perfiles entre headless y con ventana describe un método de revisión para esto.

Por qué es frágil parchear después de cargar la página

Un enfoque habitual es un plugin de la comunidad que se ejecuta dentro de la página y cambia valores después de que el navegador ha arrancado. Sustituye navigator.webdriver por un getter de JavaScript, elimina nombres del framework del ámbito global y ajusta otras propiedades. Este enfoque tiene límites que importan para la coherencia.

Primero, trabaja en el mismo mundo JavaScript que la página. Lo que el navegador informaba antes de que se ejecutara el script se reemplaza por un valor definido desde un script, y el reemplazo puede tener una forma distinta de la implementación propia del navegador. Una propiedad que el navegador nunca definió y una propiedad que un script eliminó no siempre se ven igual para el código posterior.

Segundo, hay que volver a aplicarlo en cada página, marco y contexto nuevos, y un parche puede no llegar a todos los contextos de ejecución. Cada capa adicional es algo más que mantener sincronizado tras actualizar el framework o el navegador. Cuando la lista de parches crece, el riesgo no es solo que uno falle. La combinación de parches puede dejar una sesión que ya no se comporta como ningún navegador real.

Tercero, un parche que cambia una propiedad no resuelve las demás. Cambiar la cadena User-Agent, por ejemplo, no afecta a navigator.webdriver, a los enlaces del framework ni al comportamiento de CDP, y puede crear una discrepancia entre la identidad de navegador que presentas y el entorno que realmente se ejecuta.

Algunos equipos responden compilando su propia versión de Chromium sin los parámetros de automatización. Eso elimina una categoría de señales en el origen, pero implica mantener una bifurcación: reajustar el código en cada versión de Chrome, resolver conflictos y asumir compilaciones largas. Para la mayoría de los equipos, esa inversión es difícil de justificar frente a un navegador mantenido que documenta lo que controla.

Queda un caso acotado de parche tardío que sigue siendo razonable. La limpieza con addInitScript de los dos nombres de Playwright se ejecuta antes de cualquier script de la página y elimina solo lo que añadió el framework. Es un paso pequeño y documentado, no una capa grande de sustituciones, y la documentación de BotBrowser lo mantiene como parte de la configuración recomendada.

Qué documenta BotBrowser sobre la coherencia de la automatización

BotBrowser documenta los siguientes controles para configuraciones de automatización. Cada fila indica el comportamiento documentado y el nivel en el que se aplica, para que puedas decidir cuáles incluir en tu configuración.

ControlComportamiento documentadoNivel
Perfil cargado (--bot-profile)navigator.webdriver se controla automáticamente; no hace falta ningún flag adicionalCore
--bot-disable-console-messageEvita que los eventos protegidos de consola y ejecución cambien el comportamiento visible para la página mientras CDP está conectado; activo por defectoENT Tier1
--bot-disable-debuggerIgnora las instrucciones debugger de JavaScript para que la ejecución no se detengaCore
--bot-always-activeMantiene activas las ventanas y pestañas sin foco; activo por defectoPRO
--bot-port-protectionImpide que las páginas remotas detecten qué servicios se ejecutan en puertos de localhostPRO
--bot-scriptEjecuta tu script en un contexto de página aislado y con privilegios, sin enlaces de framework externos ni cliente CDP aparteCore

El flag de consola merece una lectura precisa. Protege las rutas de eventos de consola y de ejecución. No desactiva el dominio CDP Runtime, de modo que la evaluación normal y el manejo de excepciones siguen disponibles para tu automatización. Las sesiones de diagnóstico que desactivan la protección a propósito con --bot-disable-console-message=false cambian el comportamiento de CDP, así que trátalas como una ejecución de compatibilidad aparte y no compares sus resultados con los de producción.

--bot-script es la opción con la menor huella de framework porque no necesita ni Playwright ni Puppeteer. Si tu flujo puede expresarse como un script que se ejecuta dentro del navegador, evita por completo los enlaces del framework. Usa --bot-title cuando el título de la página muestre el nombre de la extensión.

Configurar Playwright y Puppeteer

Instala playwright-core o puppeteer-core en lugar de los paquetes completos. Los paquetes completos incluyen su propia descarga de Chromium, que no necesitas cuando lanzas BotBrowser por ruta. Guarda el perfil, la ruta del binario y el proxy en variables de entorno o en la configuración para que cada ejecución registre las mismas entradas.

import { chromium } from 'playwright-core';
const browser = await chromium.launch({
  executablePath: process.env.BOTBROWSER_EXEC_PATH,
  headless: true,
  args: [
    '--disable-audio-output',
    `--bot-profile=${process.env.BOT_PROFILE_PATH}`,
    '--proxy-server=socks5://user:pass@proxy.example.com:1080',
  ],
});
const page = await browser.newPage();
await page.addInitScript(() => {
  delete window.__playwright__binding__;
  delete window.__pwInitScripts;
});
await page.goto('https://example.com');

Crea primero la página, registra la limpieza y solo después navega. El script de inicio debe estar registrado antes del primer goto, o la página puede ejecutarse antes de que se eliminen los nombres. Tampoco establezcas opciones de viewport en Playwright, porque el perfil debe controlar las dimensiones.

import puppeteer from 'puppeteer-core';
const browser = await puppeteer.launch({
  executablePath: process.env.BOTBROWSER_EXEC_PATH,
  headless: true,
  defaultViewport: null,
  args: [
    '--disable-audio-output',
    `--bot-profile=${process.env.BOT_PROFILE_PATH}`,
    '--proxy-server=socks5://user:pass@proxy.example.com:1080',
  ],
});
const page = await browser.newPage();
await page.goto('https://example.com');

En Puppeteer, defaultViewport: null es la línea importante. Sin ella, Puppeteer aplica su propio viewport y sobrescribe las dimensiones de pantalla que aporta el perfil, y un viewport que no coincide es un problema de coherencia que has creado tú mismo.

Configura el proxy con --proxy-server (o con la opción de proxy por contexto), no con ajustes de proxy exclusivos del framework. BotBrowser alinea la zona horaria, la configuración regional y los idiomas con la región del proxy solo cuando es él quien enruta el tráfico. Un valor manual de --bot-timezone, --bot-locale o --bot-languages sustituye esa correspondencia, mientras que los valores que se dejan en auto siguen al proxy. Si cargas perfiles desde un directorio con --bot-profile-dir, BotBrowser elige un perfil en cada arranque, y la opción de directorio no puede combinarse con --bot-profile (si se indican ambas, prevalece el directorio).

En un servidor Linux, BotBrowser sigue necesitando una pantalla virtual como Xvfb aunque lo inicies con --headless, y la variable DISPLAY debe estar definida para cada ejecución de BotBrowser. Hay dos flags PRO útiles para trabajos de larga duración. --bot-always-active viene activado por defecto y mantiene las ventanas y pestañas en estado activo cuando no tienen foco, lo que coincide con el comportamiento de un navegador principal. --bot-port-protection impide que las páginas remotas averigüen qué servicios se ejecutan en puertos locales, como el escritorio remoto o los servidores de desarrollo. Ninguno de los dos flags cambia la forma en que Playwright o Puppeteer se conectan, así que puedes añadirlos a los argumentos de lanzamiento cuando las comprobaciones básicas ya pasen.

Verificar la configuración en tu propio entorno de pruebas

La verificación es una comprobación de regresión de tu propia configuración. Te dice si un lanzamiento coincide hoy con el comportamiento documentado y si sigue coincidiendo después de actualizar BotBrowser, el perfil o el framework. No predice cómo tratará una sesión ningún sitio de terceros.

Empieza registrando las entradas: versión de BotBrowser, archivo de perfil, argumentos de lanzamiento, versión del framework, modo headless o con ventana y región del proxy. Sin ese registro, una diferencia posterior no puede atribuirse a un cambio concreto.

Después usa una página que controles para leer un pequeño conjunto de valores y compáralos con lo que deben producir el perfil y tus ajustes de lanzamiento:

  1. navigator.webdriver debería ser false una vez cargado un perfil.
  2. Los dos nombres de enlaces de Playwright deberían estar ausentes si el script de inicio se ejecutó antes de la navegación.
  3. Las dimensiones de ventana y pantalla deberían coincidir con el perfil, y las entradas de idioma y plugins deberían coincidir con la configuración regional prevista.
  4. El comportamiento de la consola debería coincidir con lo que quieres: con los valores por defecto de ENT Tier1, el controlador de eventos de consola de tu cliente no debería recibir nada de la página.
  5. La zona horaria y los idiomas deberían seguir la región del proxy o tus valores explícitos.

Cuando un valor difiere, la documentación señala una causa concreta para cada caso:

ObservaciónCausa probableQué cambiar
navigator.webdriver devuelve trueEl perfil no se cargóRevisa la ruta y el archivo de --bot-profile
Los nombres de enlaces de Playwright siguen presentesEl script de inicio se ejecutó demasiado tardeRegistra addInitScript antes del primer goto
Los eventos de consola siguen llegando a tu clienteLa supresión está desactivada o el nivel no la incluyeRevisa el valor del flag y el nivel de suscripción
El viewport no coincide con el perfilHay una sobrescritura de viewport del frameworkUsa defaultViewport: null en Puppeteer y evita opciones de viewport en Playwright
La zona horaria no coincide con la región del proxyEl proxy se definió solo con opciones del frameworkPasa el proxy con --proxy-server o con el proxy por contexto

Una página que controles puede servir como segunda opinión sobre la misma sesión. Lee su resultado como información sobre tu propio entorno, no como un veredicto de un tercero. Los hallazgos que apuntan a una incoherencia entre perfil, proxy y configuración regional merecen corregirse aunque ningún sitio se queje nunca.

En un flujo de integración continua, convierte la lista en aserciones que hagan fallar la compilación cuando cambie un valor esperado. Ejecútalas en el mismo modo que usa tu trabajo de producción. Si operas trabajos headless y con ventana, ejecuta ambos. Guarda el registro de versiones junto al resultado, para que un fallo tras una actualización se pueda atribuir fácilmente al componente que cambió.

Revisión práctica de una ejecución fallida

Supón que un trabajo nocturno empieza a informar de que la lista de idiomas de tu página de prueba ya no coincide con la configuración regional del perfil. Empieza por el registro, no por los flags. Compara la versión de BotBrowser, el archivo de perfil, los argumentos de lanzamiento y la región del proxy con la última ejecución correcta. En este ejemplo solo cambió la región del proxy, porque el equipo trasladó el trabajo a otra ubicación de salida.

La documentación explica el siguiente paso. Los valores que se dejan en auto siguen al proxy, así que la lista de idiomas cambió junto con la región. Si el equipo quiere una configuración regional fija con independencia de la ubicación de salida, establece --bot-locale o --bot-languages de forma explícita y deja la zona horaria en auto. Tras ese cambio, la ejecución repite las mismas cinco comprobaciones y se actualiza el registro. El resultado es una decisión documentada sobre qué valores siguen al proxy y cuáles quedan fijos, en lugar de una sorpresa descubierta más tarde.

Mantener coherentes el proxy, el perfil y el tráfico

Las señales de automatización son solo una parte de una sesión coherente. Un perfil de Chrome en Windows combinado con un proxy de un país y una configuración regional de otro produce una discrepancia, salvo que fijes la configuración regional o cambies la ruta. Decide qué atributos deben seguir a la ruta y cuáles deben quedar fijos, deja esa decisión por escrito y compruébala con la misma rutina que usas para navigator.webdriver.

El comportamiento del tráfico forma parte de la misma revisión. Un script que abre muchas páginas a un ritmo que ninguna persona usaría, o que repite la misma navegación con un ritmo fijo, es un patrón de comportamiento que ningún ajuste del navegador puede cambiar. BotBrowser no sustituye esa disciplina. Mantén el volumen de solicitudes, los tiempos y el uso de cuentas dentro de las reglas de los sitios con los que trabajas, y ejecuta solo automatización que estés autorizado a ejecutar.

Por último, usa más de un perfil cuando el trabajo requiera entornos separados. Reutilizar un único perfil en todas las instancias significa que todas informan del mismo entorno. --bot-profile-dir elige un archivo de un directorio en cada arranque, lo que da a cada lanzamiento un perfil distinto sin código adicional, y aun así puedes registrar qué archivo cargó cada ejecución.

Límites, Selenium y preguntas prácticas

En tus propias páginas de prueba con Playwright o Puppeteer, BotBrowser controla navigator.webdriver automáticamente al cargar un perfil y, con --bot-disable-console-message (un flag ENT Tier1, activado por defecto), evita que los eventos CDP protegidos de consola y ejecución cambien lo que la página puede observar, de modo que puedes verificar tú mismo estas señales de automatización con las comprobaciones de arriba. El comportamiento documentado está descrito en consistencia de automatización. Los límites son explícitos: BotBrowser no puede garantizar cómo clasifica una sesión cualquier sitio de terceros, no desactiva el dominio CDP Runtime, no elimina por ti los enlaces del framework (mantén la limpieza con addInitScript) y no sustituye un proxy, un perfil y un comportamiento de tráfico coherentes.

¿Funciona BotBrowser con Selenium? Las configuraciones documentadas usan Playwright y Puppeteer. Selenium se comunica mediante el protocolo WebDriver, que puede exponer señales adicionales fuera de las protecciones CDP descritas aquí. BotBrowser sigue controlando navigator.webdriver cuando se carga un perfil, pero la protección de consola y ejecución se limita a las rutas de CDP.

¿Necesito un plugin de parches encima? La documentación no describe ninguno como parte de la configuración recomendada. Un plugin que sustituye las mismas propiedades añade una segunda fuente de valores, y es un motivo para probar primero sin él. Añade uno solo cuando quede una carencia concreta y verificada.

¿--bot-disable-debugger cambia mi depuración? Sí. Las instrucciones debugger del JavaScript de la página se ignoran, de modo que la ejecución no se detiene en ellas. Deja el flag fuera de una sesión en la que quieras esa pausa y úsalo en ejecuciones desatendidas.

¿Y si necesito la salida de consola en producción? Registra a nivel de aplicación, en archivos o en un servicio externo, en lugar de depender del reenvío de consola por CDP. Para depuraciones breves, establece --bot-disable-console-message=false en una sesión aparte.

¿Cómo mantengo estables los resultados entre actualizaciones? Guarda el binario de BotBrowser, el perfil y la versión del framework en un mismo registro de versión. Repite las comprobaciones de arriba cuando cambie cualquiera de ellos. Revisa la documentación de los flags que usas en cada actualización, porque los valores por defecto y los niveles pueden cambiar entre versiones.

Para guías de configuración, consulta Primeros pasos con Playwright y Primeros pasos con Puppeteer. Para organización de perfiles, consulta Gestión de perfiles.

Fuentes públicas

#automatización#Webdriver#Playwright#Puppeteer#headless#Cdp#despliegue#privacidad

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.