Huella digital

Modo determinista: huellas reproducibles del navegador

Cómo producir huellas de navegador idénticas entre sesiones usando control de semilla de ruido para salida consistente de Canvas, WebGL y Audio.

Documentación

Quieres la documentación estructurada de Huella digital?

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.

Introducción

La huella del navegador depende de señales que son estables dentro de una sesión pero varían entre dispositivos. El otro lado de este problema es la reproducibilidad: cuando necesitas que múltiples sesiones del navegador presenten la misma identidad, o cuando necesitas verificar que tu protección de privacidad funciona correctamente, necesitas un comportamiento determinista. Un navegador que produce hashes de Canvas, huellas de audio o salida WebGL ligeramente diferentes cada vez que se lanza hace imposible mantener una identidad estable o probar tu configuración de manera fiable. El modo determinista de BotBrowser, habilitado a través del flag --bot-noise-seed, te da control completo sobre todas las fuentes de variación de huella. La misma combinación de perfil y semilla siempre produce la misma huella, entre sesiones, entre máquinas y entre sistemas operativos.

Impacto en la privacidad

La necesidad de un comportamiento determinista del navegador proviene de una tensión fundamental en la protección de huellas. El ruido es importante para la privacidad. Añadir variación controlada a la salida de Canvas, procesamiento de audio y renderizado WebGL previene que las huellas se vinculen trivialmente a un solo perfil. Pero el ruido no controlado, donde cada sesión produce una huella diferente, crea un problema diferente: cada sesión aparece como un usuario único, que es lo opuesto a pasar desapercibido.

La investigación del equipo de privacidad de INRIA ha demostrado que la inestabilidad de huellas (huellas que cambian entre sesiones) es en sí misma una señal de rastreo. Si una huella cambia en cada visita pero otras señales (IP, estado de login, patrones de comportamiento) permanecen estables, la huella cambiante se convierte en un marcador en lugar de un escudo.

El modo determinista resuelve esto dándote control explícito. Tú eliges cuándo las huellas deben permanecer iguales (misma semilla) y cuándo deben diferir (diferente semilla). Esto es particularmente importante para:

  • Continuidad de sesión. Volver a un sitio web a través de múltiples sesiones con la misma huella.
  • Coordinación multi-instancia. Ejecutar múltiples instancias del navegador que necesitan identidades distintas pero estables.
  • Pruebas y verificación. Confirmar que tu protección de huellas produce los resultados esperados.
  • Reproducibilidad de investigación. Ejecutar experimentos controlados donde la variación de huellas debe eliminarse como variable.

Antecedentes técnicos

Fuentes de variación de huellas

La protección moderna de huellas implica añadir ruido controlado a varios pipelines de renderizado y procesamiento:

  • Canvas 2D. El renderizado de texto, dibujo de formas y manipulación de imágenes producen salida de píxeles específica del dispositivo. El ruido añade variación a nivel de subpíxel para prevenir coincidencias exactas.
  • WebGL/WebGPU. La ejecución de shaders, muestreo de texturas y lectura de framebuffer producen salida específica de la GPU. El ruido modifica los valores de píxeles en la salida renderizada.
  • Audio. El renderizado de OfflineAudioContext y los datos de frecuencia de AnalyserNode producen valores float específicos de la plataforma. El ruido varía la salida del procesamiento.
  • Métricas de texto. measureText(), getBoundingClientRect() y getClientRects() devuelven dimensiones que dependen del renderizado de fuentes. El ruido añade variación a nivel de subpíxel a las mediciones.

Sin una semilla, cada una de estas fuentes de ruido genera variación aleatoria nueva en cada lanzamiento del navegador. Con una semilla, el generador de números aleatorios se inicializa a un estado conocido, produciendo patrones de variación idénticos cada vez.

Cómo funcionan las semillas de ruido

Una semilla de ruido es un único entero que inicializa un generador de números pseudoaleatorios determinista (PRNG). El PRNG produce una secuencia de valores que parece aleatoria pero está completamente determinada por la semilla. Dos sesiones con la misma semilla producen la misma secuencia, y por lo tanto el mismo ruido aplicado a cada superficie de huella.

La semilla de ruido de BotBrowser (establecida vía --bot-noise-seed) controla:

  • Ruido de imagen Canvas 2D
  • Ruido de imagen WebGL
  • Ruido de renderizado WebGPU
  • Variación del procesamiento de contexto de audio
  • Variación de métricas de texto (client rects, text rects)
  • Variación de diseño de texto

La semilla no afecta propiedades que no son de ruido como navigator.hardwareConcurrency, screen.width o cadenas de user agent. Estas provienen directamente del perfil y siempre son deterministas.

Determinismo de timing

Más allá del ruido de huella, BotBrowser ofrece controles adicionales de timing:

  • --bot-time-seed - Controla la diversidad de timing de ejecución a través de 27 operaciones del navegador. Cada semilla produce un perfil de rendimiento único y estable. Esto cubre intervalos de performance.now(), performance.getEntries(), timing de navegación y más.
  • --bot-time-scale - Escala los intervalos de performance.now() para normalizar las diferencias de timing causadas por cargas variables del servidor.

Juntos, las semillas de ruido y las semillas de timing proporcionan control determinista integral sobre todas las salidas variables del navegador.

Enfoques comunes de protección y sus limitaciones

Sin ruido en absoluto significa que tu huella refleja directamente los valores base del perfil. Esto es determinista pero elimina el beneficio de privacidad de la variación. Múltiples sesiones con el mismo perfil tienen exactamente la misma huella, lo que significa que son vinculables por definición.

Ruido aleatorio sin semilla proporciona variación pero a costa de la reproducibilidad. Cada sesión tiene una huella única. No puedes mantener una identidad estable, no puedes verificar tu configuración de manera fiable, y no puedes coordinar múltiples instancias.

Ruido basado en sesión (generar una semilla aleatoria por sesión y almacenarla) es una solución manual que añade complejidad. Necesitas gestionar valores de semilla, asociarlos con sesiones y asegurar que se apliquen consistentemente. BotBrowser elimina esta sobrecarga aceptando la semilla como flag CLI.

Ruido basado en extensiones típicamente aplica ruido aleatorio a nivel de JavaScript sin ningún mecanismo de semilla. Cada carga de página produce resultados diferentes. El ruido no es determinista, no es controlable y no es consistente entre superficies de API.

Enfoque a nivel del motor de BotBrowser

El modo determinista de BotBrowser opera a nivel del motor de renderizado, asegurando que el ruido se aplique consistentemente en todas las superficies de API desde un único valor de semilla.

Una semilla, cobertura completa

El flag --bot-noise-seed acepta un entero de 1 a 4294967295 (UINT32_MAX). Este único valor controla todas las fuentes de ruido simultáneamente:

  • Canvas 2D toDataURL(), toBlob() y getImageData() producen salida idéntica para la misma semilla.
  • WebGL readPixels() devuelve los mismos datos de framebuffer para la misma escena dibujada y semilla.
  • OfflineAudioContext renderiza el mismo búfer para el mismo grafo de audio y semilla.
  • measureText() y getClientRects() devuelven las mismas mediciones para el mismo contenido y semilla.

Reproducibilidad entre máquinas

Debido a que el ruido se deriva de la semilla y se aplica a nivel del motor, la misma combinación de perfil + semilla produce la misma huella independientemente del hardware subyacente, sistema operativo o GPU. Una sesión en un servidor Linux con GPU NVIDIA y una sesión en un portátil Mac con Apple Silicon producen huellas idénticas cuando usan el mismo perfil y semilla.

Semilla como identidad

En la práctica, puedes pensar en cada semilla como definiendo una sub-identidad única dentro de un perfil. El perfil A con semilla 42 es una identidad estable y reproducible. El perfil A con semilla 43 es una identidad estable y reproducible diferente. El perfil define la clase de dispositivo (SO, navegador, hardware), y la semilla define al individuo dentro de esa clase.

Este modelo mapea naturalmente a flujos de trabajo multi-cuenta o multi-sesión:

  • Sesión 1: perfil A, semilla 100
  • Sesión 2: perfil A, semilla 200
  • Sesión 3: perfil B, semilla 100

Las sesiones 1 y 2 aparecen como diferentes usuarios con hardware similar. La sesión 3 aparece como un usuario diferente en hardware diferente.

Determinismo de timing

Con --bot-time-seed, el timing de ejecución se vuelve reproducible también. Las mediciones de rendimiento, timing de navegación y timing de recursos siguen un patrón determinista para una semilla dada. Combinado con --bot-noise-seed, esto proporciona control completo sobre todas las salidas variables del navegador.

Modo determinista: La semilla controla todas las fuentes de ruido --bot-noise-seed=42 PRNG determinista Ruido Canvas Ruido WebGL Ruido Audio Métricas texto Misma semilla = Misma huella cada vez

Configuración y uso

Modo determinista básico

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --user-data-dir="$(mktemp -d)"

Control determinista completo

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --bot-time-seed=42 \
       --bot-stack-seed=profile \
       --user-data-dir="$(mktemp -d)"

Multi-instancia con semillas distintas

# Instance 1 - stable identity A
chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=1001 \
       --user-data-dir="/tmp/session-a" &

# Instance 2 - stable identity B
chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=1002 \
       --user-data-dir="/tmp/session-b" &

Integración con Playwright

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-noise-seed=42',
    '--bot-time-seed=42'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

// This canvas fingerprint will be identical on every run
const hash = await page.evaluate(() => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.fillText('deterministic test', 10, 10);
  return canvas.toDataURL();
});
console.log(hash);

Integración con Puppeteer

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-noise-seed=42',
    '--bot-time-seed=42'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

Desactivar canales de ruido específicos

Si necesitas salida determinista para algunas señales pero salida nativa para otras:

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --bot-config-noise-canvas=false \
       --bot-config-noise-audio-context=false

Verificación

Reproducibilidad entre sesiones. Ejecuta la misma prueba de huella en dos sesiones separadas con el mismo perfil y semilla. Compara hashes de Canvas, huellas de audio, salida WebGL y métricas de texto. Todos los valores deberían ser idénticos.

Reproducibilidad entre máquinas. Ejecuta la misma prueba en una máquina diferente con el mismo perfil y semilla. La huella debería coincidir exactamente.

Variación de semilla. Cambia la semilla y ejecuta la prueba de nuevo. La huella debería ser diferente, confirmando que la semilla realmente está influyendo en la salida.

Comportamiento con semilla 0. Usar --bot-noise-seed=0 mantiene el ruido activo con los valores predeterminados del perfil pero sin siembra determinista. Verifica que esto produce una salida que varía entre sesiones.

Mejores prácticas

  • Usa una semilla única por identidad. Cada semilla define una sub-identidad estable. No reutilices la misma semilla para sesiones que deberían aparecer como usuarios diferentes.
  • Almacena los valores de semilla. Si necesitas volver a una sesión, necesitas el mismo perfil y semilla. Almacena la asociación entre la identidad de sesión y el valor de semilla.
  • Combina --bot-noise-seed con --bot-time-seed. La semilla de ruido controla la salida de renderizado. La semilla de tiempo controla el timing de rendimiento. Ambos contribuyen a una huella completa. Usa ambos para determinismo total.
  • Evita el valor de semilla 0. Cero mantiene el ruido activo con variación no determinista. Usa cualquier entero positivo para comportamiento determinista.
  • Prueba tus asignaciones de semilla. Antes de desplegar, verifica que diferentes semillas produzcan diferentes huellas y que la misma semilla produzca huellas idénticas.

Preguntas frecuentes

P: ¿Cuál es el rango válido para --bot-noise-seed? R: Cualquier entero de 1 a 4294967295 (UINT32_MAX). El valor 0 mantiene el ruido activo pero no determinista.

P: ¿La semilla de ruido afecta el rendimiento del navegador? R: No. Las operaciones de ruido son extremadamente ligeras. El cómputo del PRNG añade una sobrecarga insignificante.

P: ¿Pueden dos perfiles diferentes con la misma semilla producir la misma huella? R: No. El perfil define la huella base (GPU, pantalla, navigator, etc.), y la semilla define la variación de ruido. Diferentes perfiles con la misma semilla producen diferentes huellas porque los valores base difieren.

P: ¿Qué pasa si no establezco --bot-noise-seed? R: El ruido se aplica con una semilla aleatoria en cada lanzamiento. Cada sesión tiene una huella diferente. Las propiedades base del perfil (navigator, pantalla, etc.) permanecen iguales.

P: ¿El modo determinista afecta las cookies o el almacenamiento local? R: No. El modo determinista controla la salida de renderizado relevante para huellas. El almacenamiento, cookies y estado de sesión se gestionan a través de --user-data-dir y --bot-cookies.

P: ¿Puedo usar la misma semilla con diferentes versiones de BotBrowser? R: El algoritmo de ruido puede cambiar entre versiones mayores. Para reproducibilidad exacta, usa la misma versión de BotBrowser. Dentro de una versión, el comportamiento de la semilla es estable garantizado.

P: ¿Cómo difiere --bot-time-seed de --bot-noise-seed? R: --bot-noise-seed controla el ruido de renderizado (Canvas, WebGL, audio, métricas de texto). --bot-time-seed controla la diversidad de timing de ejecución (patrones de performance.now(), timing de navegación). Son independientes y pueden establecerse a valores diferentes.

Resumen

El comportamiento determinista del navegador es esencial para mantener identidades de huella estables, coordinar flujos de trabajo multi-sesión y verificar la protección de privacidad. El flag --bot-noise-seed de BotBrowser proporciona control completo sobre todas las fuentes de variación de huella, produciendo una salida idéntica para la misma combinación de perfil y semilla independientemente del hardware subyacente. Combinado con --bot-time-seed para determinismo de timing y --bot-stack-seed para control de profundidad de pila, BotBrowser ofrece un modo determinista integral que cubre cada salida variable del navegador.

Para temas relacionados, consulta Qué es la huella del navegador, Protección de huella de audio, Huella Canvas y Reproducibilidad de semilla de ruido.

#Deterministic#Noise-Seed#Reproducibility#fingerprinting#Privacy

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.