Cómo detectar navegadores headless y automatización en tu página de registro
Las señales del navegador que delatan registros hechos con Puppeteer, Playwright y Selenium, por qué cada una puede falsificarse por sí sola y cómo combinarlas sin bloquear a personas reales.
Por qué los bots usan ahora navegadores reales
Hace unos años, la mayoría de los bots de registro eran scripts HTTP simples que enviaban tu formulario directamente. Esos son fáciles de frenar: no ejecutan JavaScript, así que nada de lo que tu página calcula en el navegador llega. Hoy, la mayoría de los bots serios controlan un navegador real con Puppeteer, Playwright o Selenium, a menudo headless, a veces a través de un navegador antidetección que disfraza su huella. Ejecutan tu JavaScript, renderizan tu página y rellenan el formulario como lo haría una persona.
Detectarlos significa buscar los puntos en los que un navegador automatizado se diferencia de uno que usa una persona. Ninguna de las señales siguientes es prueba por sí sola — un operador decidido puede corregir cada una —, pero son baratas de recoger y se suman.
Señal 1: la marca de WebDriver
Los navegadores bajo automatización tipo WebDriver ponen navigator.webdriver en true. Forma parte, a propósito, del estándar WebDriver, y las configuraciones por defecto de Selenium, Puppeteer y Playwright la exponen.
const automated = navigator.webdriver === true;
Los plugins “stealth” la borran o la sobrescriben, así que su ausencia no prueba nada. Su presencia, en cambio, es casi concluyente: los usuarios reales prácticamente nunca la tienen.
Señal 2: el user agent headless
Chrome headless se identifica como HeadlessChrome en su user agent salvo que el operador lo sobrescriba. Compruébalo también en el servidor, desde la cabecera de la petición, porque el user agent que el navegador informa en JavaScript puede diferir del que envía.
Señal 3: un cliente del protocolo DevTools conectado
Puppeteer y Playwright controlan Chrome a través del protocolo DevTools. Cuando un cliente del protocolo escucha los eventos de consola, registrar un objeto hace que el navegador lo serialice, leyendo incluso propiedades que una página normal nunca tocaría. Un getter que anota si fue leído es una forma conocida de notarlo:
function devtoolsProtocolAttached() { let read = false; const e = new Error(); Object.defineProperty(e, "stack", { get() { read = true; return ""; } }); console.debug(e); return read; }
También salta cuando un desarrollador tiene DevTools abierto, así que dale un peso moderado en lugar de tratarlo como veredicto.
Señal 4: renderizado por software y ventanas raras
Los navegadores headless en servidores no tienen GPU, así que WebGL recurre a un renderizador por software como SwiftShader o llvmpipe. Puedes leer el nombre del renderizador mediante la extensión WEBGL_debug_renderer_info cuando el navegador la expone. Algunas configuraciones headless también informan una ventana de ancho o alto cero. Las máquinas virtuales y los escritorios remotos comparten estos rasgos, así que por sí solas son señales débiles.
Señal 5: una huella que se contradice
Los navegadores antidetección existen para parecer muchos navegadores reales distintos. Lo consiguen sobrescribiendo propiedades, y las sobrescrituras rara vez son perfectamente coherentes. Vale la pena comparar:
- El sistema operativo del user agent frente a
navigator.platformy los User-Agent Client Hints. - La familia de navegador del user agent frente a funciones que solo tiene ese motor.
- Las fuentes instaladas frente a las que trae ese sistema operativo.
- Un canvas dibujado dos veces seguidas que produce dos imágenes distintas: señal de ruido inyectado.
Notification.permissiondiciendo “denied” mientras la Permissions API dice “prompt”.
Cada contradicción es débil por sí sola, porque las extensiones de privacidad y las configuraciones poco comunes producen algunas. Dos o tres juntas son un patrón fuerte.
Señal 6: el token que nunca volvió
Una técnica sencilla y robusta: haz que el script de la página de registro pida un token de vida corta y un solo uso, ponlo en un campo oculto del formulario y verifícalo en el servidor. Un bot que se salta tu JavaScript llega sin token válido; uno que reutiliza un token antiguo llega con uno ya usado. No necesitas saber cómo funciona el bot para notar que nunca ejecutó bien tu página. Mantén el token de un solo uso, vinculado a tu sitio, y haz que caduque en minutos.
Señal 7: el comportamiento, no la huella
La huella se puede falsificar; el comportamiento cuesta más. Una persona lee el formulario, mueve el puntero y teclea. Un script rellena los campos y envía a los pocos cientos de milisegundos de cargar la página, sin ningún evento de entrada de confianza.
La medición fiable no necesita software extra: tu agente emite el token del visitante al cargar la página y tu servidor compara esa marca de tiempo con el momento de la comprobación. Menos de un segundo entre cargar y registrarse es un script. Cuando el agente además informa eventos de entrada de confianza, un envío instantáneo sin eventos de puntero, tecla ni toque es una segunda confirmación independiente.
Una advertencia sobre la señal 3: en Chrome actual el truco de DevTools solo se activa cuando el cliente de automatización se suscribe a los eventos de consola, así que trátalo como un extra y no como el detector principal.
Combina; no bloquees por una sola señal
Trata cada señal como puntos de una puntuación y decide por el total. Una ponderación razonable para empezar, de la más fuerte a la más débil:
| Señal | Peso | Por qué |
|---|---|---|
navigator.webdriver true | alto | Casi nunca es true para usuarios reales |
| User agent HeadlessChrome | alto | Solo lo envían las versiones headless |
| Token ausente o reutilizado | alto | El script de la página no se ejecutó, o se ejecutó una vez para muchos registros |
| Protocolo DevTools conectado | medio | Los desarrolladores con DevTools abierto también lo activan |
| Contradicciones de SO o navegador | medio | Sobrescrituras antidetección, pero también algunas extensiones |
| Renderizado por software, ventana cero | bajo | Las VM y los escritorios remotos también los tienen |
Combina las señales del navegador con las del servidor — registros desde rangos IP de nube, ráfagas desde una subred, cuentas vinculadas al mismo dispositivo — y muy pocos bots parecerán limpios en todas a la vez.
Lo que no hay que hacer
- No bloquees solo por la ausencia de plugins o idiomas. Los navegadores reforzados para la privacidad los eliminan.
- No publiques tu lógica de detección como comprobaciones con nombres obvios que un operador pueda buscar y parchear de golpe; recoge datos en bruto en el navegador y decide en el servidor.
- No confíes a ciegas en nada que informe el navegador. El cliente está bajo control del bot. La verificación ocurre en tu servidor, con tu secreto.
Cómo lo hace Attrelix
El agente de Attrelix recoge estos datos del navegador y un token de visitante de un solo uso en tu página de registro; el servidor los combina con señales de red, buzón y cuentas vinculadas en una sola puntuación. Todos los pesos son públicos en la documentación, y ninguna señal débil por sí sola puede enviar un registro a revisión.
Resumen
- Los bots modernos usan navegadores reales; busca dónde la automatización se diferencia de una persona.
- WebDriver, el user agent headless y los tokens ausentes son fuertes; el resto es débil pero suma.
- Decide en el servidor, con una puntuación, nunca por una sola marca del navegador.