Volver al Centro de conocimiento
Huella digital

Reproducibilidad de la semilla de ruido en ejecuciones repetibles

Cómo una semilla de ruido entera fija hace que Canvas, WebGL, Audio y las medidas de texto se repitan entre sesiones, reinicios y ejecuciones de CI, y cómo comprobarlo.

BotBrowser Team

Documentación

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.

Una semilla de ruido repetible hace comparables las ejecuciones de Canvas, WebGL, audio y texto. BotBrowser repite el mismo ruido con la misma semilla, el mismo perfil y la misma compilación; una coincidencia no demuestra que dos hosts sean el mismo dispositivo ni que un sitio vaya a tratarlos igual.

Resumen rápido

La semilla fija el ruido aplicado, no el host: el mismo fixture con la semilla 42 debe dar el mismo resumen tras reiniciar, y con la 43 debes registrar si cambia o colisiona. Asigna una semilla por identidad para no crear vínculos entre cuentas.

Contenido de esta guía

Por qué las semillas repetibles hacen comparables las ejecuciones

Una prueba de huella digital que da una respuesta distinta cada vez que se ejecuta es difícil de creer. El ruido de huella añade pequeñas variaciones a los píxeles de Canvas, a la lectura de WebGL, a las muestras de audio y a las medidas de texto, para que el navegador no presente la salida en bruto de una sola máquina. Si esa variación se genera de nuevo en cada arranque, no puedes saber si un resultado distinto procede de tu configuración, de la página que pruebas o del propio ruido. Una semilla de ruido fija elimina la tercera posibilidad. BotBrowser puede repetir la salida de Canvas, WebGL, audio y medición de texto para un perfil, una compilación y una semilla fijos en un contexto controlado; no puede hacer anónima esa salida ni garantizar el mismo resultado con otra compilación, otro perfil u otros argumentos.

Una semilla de ruido es un número entero que inicializa un generador de números pseudoaleatorios. El generador produce la misma secuencia a partir del mismo valor inicial, así que dos arranques con la misma semilla aplican la misma variación al mismo dibujo o a la misma medida, y una semilla distinta aplica otra variación igual de estable. Tú decides cuándo debe repetirse la salida y cuándo debe cambiar. Para saber cómo elegir semillas para identidades estables y verificar que una semilla se repite, consulta Modo determinista: huellas reproducibles del navegador, que cubre qué controla la semilla y cómo comprobar la reproducibilidad.

Cuatro tareas suelen justificar una semilla fija:

  • Continuidad de sesión. Volver a un servicio a lo largo de varios arranques presentando cada vez la misma salida de renderizado.
  • Identidades distintas y estables. Dar a cuentas, inquilinos o usuarios de prueba separados su propio patrón de ruido, que no cambia entre arranques.
  • Comparación entre ejecuciones. Quitar el ruido de renderizado como variable al comparar dos compilaciones, dos páginas o dos perfiles.
  • Reproducción en CI. Reconstruir las condiciones de una ejecución anterior para que una comparación fallida se pueda investigar en lugar de adivinar.

Una semilla entera alimenta un generador de ruido que determina la salida de lienzo 2D, WebGL, audio y medidas de texto; la misma semilla, perfil, compilación y argumentos repiten la salida, mientras que otra semilla la cambia

Las secciones siguientes siguen una semilla desde las superficies que toca, pasando por la asignación de semillas a identidades, hasta una comprobación tras reinicio y un registro para CI, y terminan en los límites que conviene indicar al informar de un resultado. Los valores de referencia proceden de la documentación pública de la semilla de ruido y de la referencia de parámetros de línea de comandos que figuran en las fuentes.

Qué repite la semilla y qué deja intacto

BotBrowser aplica ruido controlado a Canvas 2D, WebGL, WebGPU, AudioContext, ClientRects y TextRects. El parámetro --bot-noise-seed (ENT Tier2) hace que ese ruido sea determinista. Con el mismo perfil, la misma compilación y los mismos argumentos de arranque, una semilla fija da la misma lectura de Canvas, la misma lectura de WebGL y WebGPU, las mismas muestras de audio y las mismas medidas de texto y de elementos en cada sesión y tras cada reinicio.

La lectura es el punto donde una página ve el efecto. HTMLCanvasElement.toDataURL() devuelve una URL de datos con los píxeles que contiene el lienzo en ese momento, como PNG salvo que quien llama pida otro tipo, de modo que cualquier variación del renderizado aparece directamente en la cadena devuelta. Un OfflineAudioContext renderiza un grafo de nodos de audio en un búfer sin reproducirlo, y la página lee los valores de las muestras de ese búfer. Llamadas como measureText() y getBoundingClientRect() devuelven números en lugar de píxeles, pero se leen igual: la página pregunta, el navegador responde, y la respuesta coincide con la anterior o no coincide. La semilla actúa sobre la respuesta, no sobre la pregunta. Para ver cómo la salida de audio se convierte en una huella y cómo comprobar la coherencia del audio, consulta Huella de audio explicada: cómo AudioContext te rastrea, que explica por qué el audio funciona como señal de rastreo.

La repetición está ligada al contenido. Una página que dibuja la misma escena con la semilla 42 en dos sesiones lee los mismos píxeles, y la misma escena con la semilla 43 lee píxeles distintos que son igual de estables. Si la propia escena cambia entre ejecuciones, la salida cambia por motivos que nada tienen que ver con la semilla, así que cada comparación necesita una escena fija. Para ver por qué el mismo dibujo difiere entre dispositivos, consulta Huella de Canvas: cómo funciona y qué ayuda, que cubre qué mide la huella de Canvas y cómo comprobar la estabilidad.

El rango aceptado va de 1 a 4294967295, el mayor entero de 32 bits sin signo. El valor 0 conserva los valores predeterminados del perfil y no siembra el generador, así que no se garantiza la repetibilidad con 0 y no debes usarlo como base de comparación. Cuando importe la repetibilidad, pasa un entero positivo en cada arranque y comprueba que tu lanzador o tu framework de pruebas reenvía de verdad el argumento, porque un 0 accidental o un argumento perdido convierte sin avisar una configuración determinista en una que varía.

La semilla no decide qué tipo de dispositivo se presenta. El perfil define los valores de identidad del dispositivo, como la cadena de agente de usuario, las dimensiones de pantalla y la plataforma. La semilla solo da forma a la variación de renderizado y de medidas sobre esos valores. Dos sesiones con el mismo perfil y semillas distintas comparten los valores del perfil y difieren en el ruido, y una semilla no fusiona dos perfiles distintos en una sola identidad.

Cada canal de ruido tiene su propio interruptor en la referencia de parámetros: --bot-noise-canvas, --bot-noise-webgl-image, --bot-noise-audio-context, --bot-noise-client-rects y --bot-noise-text-rects. Cada uno acepta true o false. La semilla decide cómo es el ruido y los interruptores deciden qué superficies lo reciben, así que los dos controles responden a preguntas distintas. Desactivar un canal es un paso de diagnóstico útil cuando un resultado deja de repetirse, siempre que lo vuelvas a activar antes de apoyarte en la configuración.

Algunas cosas quedan fuera de la semilla. Las cookies, el almacenamiento y el estado de inicio de sesión viven en el directorio indicado con --user-data-dir, y una semilla no restaura una sesión iniciada. La temporización de ejecución tiene su propio control: --bot-time-seed toma un entero de 1 a 4294967295 para una política de temporización reproducible, y 0 la desactiva. Una semilla de ruido por sí sola no hace que la temporización se repita, y una semilla de temporización no cambia la salida de Canvas. Cuando una prueba necesite que se repitan tanto el renderizado como la temporización, establece ambos valores a propósito y registra los dos.

Asignar semillas a identidades sin crear vínculos

Trata la semilla como configuración propia de cada identidad. Un perfil con la semilla 100 es una huella estable. El mismo perfil con la semilla 200 es una segunda, con su propio patrón de ruido. Esa separación es el motivo para tener una semilla por cuenta, inquilino o usuario de prueba, y es lo que permite que cada identidad presente la misma salida de renderizado en su siguiente visita.

El caso inverso es el que hay que vigilar. Si dos identidades usan el mismo perfil y la misma semilla, producen una salida de renderizado idéntica, y esa salida compartida puede vincularlas. Una semilla es configuración, no un secreto que impida la correlación: cualquiera que tenga la misma compilación, el mismo perfil y la misma semilla reproduce la misma salida. Lo que protege a identidades separadas es que no haya dos que compartan perfil y semilla.

Guarda en el control de versiones una tabla de semilla a identidad junto a los nombres de los archivos de perfil. Cada fila debe contener la identidad, el nombre del archivo de perfil, la semilla y la fecha en que se creó el par.

[
  { "identity": "tenant-a", "profile": "profile-a.enc", "seed": 1001 },
  { "identity": "tenant-b", "profile": "profile-a.enc", "seed": 1002 },
  { "identity": "tenant-c", "profile": "profile-b.enc", "seed": 1003 }
]

En esta tabla, el inquilino A y el inquilino B comparten perfil pero tienen semillas distintas, así que sus patrones de ruido difieren. El inquilino C usa otro perfil. Si el inquilino B pasara a la semilla 1001, dos identidades tendrían el mismo perfil y la misma semilla, y ese es el patrón que hay que notificar como riesgo de vinculación y corregir antes de la siguiente ejecución asignando una semilla nueva a una de ellas.

Genera cada semilla una sola vez y guárdala. No derives una semilla de una marca de tiempo ni de un contador que se reinicia, porque eso convierte sin avisar una configuración determinista en un valor distinto en cada arranque. La semilla no se puede recuperar a partir de la salida, así que la tabla es el único registro. Sirve cualquier entero positivo del rango válido, y no hay ventaja en usar valores grandes, primos o con algún patrón. Los valores consecutivos están bien, siempre que la tabla indique quién tiene cada uno.

Cuando un solo proceso del navegador tiene que llevar varias identidades, la huella por contexto (ENT Tier3) permite que cada BrowserContext tenga su propio --bot-noise-seed. La documentación establece los parámetros de un contexto antes de crear su primera página, de modo que el renderizador arranque con los valores correctos. Un segundo contexto con otra semilla produce un patrón distinto que es igual de reproducible.

Comprobar la misma semilla tras reinicios

La comprobación siguiente confirma que una semilla se repite y que otra semilla cambia la salida. Necesita una página que controles tú, o una página de pruebas de la que te fíes para dibujar la misma escena cada vez. La página debe dibujar una escena fija de Canvas y leerla con toDataURL(), leer una escena fija de WebGL, renderizar un búfer de audio sin conexión fijo y medir una cadena fija. Registra cada valor, o un resumen corto de él, para que las comparaciones sean exactas. Carga la página siempre del mismo modo, con el mismo tamaño de ventana y el mismo orden de carga, para que la semilla sea la única diferencia deliberada entre ejecuciones.

Un directorio de datos de usuario nuevo deja fuera de la comparación el estado antiguo del navegador:

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

Ejecuta la comprobación en este orden:

  1. Arranca con el perfil y --bot-noise-seed=42, carga la página y registra los valores de Canvas, WebGL, Audio y texto.
  2. Cierra el navegador, vuelve a arrancar con el mismo perfil y la misma semilla, y carga la misma página. Todos los valores registrados deben coincidir con los de la primera ejecución.
  3. Cambia la semilla a 43 y ejecuta la página por tercera vez. Registra si cada valor difiere o colisiona con el primero: un cambio muestra que la semilla afecta a esa superficie, mientras que una colisión muestra que un entero nuevo no garantiza unicidad.
  4. Arranca dos veces con --bot-noise-seed=0. La repetibilidad con 0 no está garantizada, así que no uses estos valores como base de comparación, porque 0 no siembra el generador.
  5. Guarda la compilación, el archivo de perfil, el sistema operativo del anfitrión y la lista completa de argumentos junto a los resultados.

El quinto paso es el que más se omite, y es el que explica un desajuste posterior. Un resultado solo es comparable con otro cuando la compilación, el perfil, la semilla y los argumentos de arranque son los mismos.

Cuando la segunda sesión no coincide con la primera, descarta las causas habituales antes de sospechar de la semilla:

  • La escena cambió: el texto, el tamaño del lienzo o el orden de dibujo difieren entre ejecuciones.
  • La semilla no llegó: un lanzador descartó el argumento, o el valor es 0.
  • Se cargó otro archivo de perfil u otra versión del perfil.
  • Se usó otra compilación de BotBrowser u otro sistema operativo de destino del anfitrión.
  • Un framework o un script envoltorio añadió argumentos adicionales.
  • Un canal de ruido se desactivó en una ejecución y se dejó activado en la otra.

La documentación da el mismo consejo para una configuración que se comporta de forma distinta en otra máquina: comparar la compilación de BotBrowser, la versión del perfil, el sistema operativo de destino del anfitrión y los argumentos de arranque completos. También aconseja mantener estables la ruta de red, la configuración regional y la zona horaria, y la carga de la máquina mientras comparas ejecuciones, porque pueden cambiar lo que hace una página aunque la semilla no haya cambiado.

Un desajuste es un hallazgo, no ruido que haya que promediar. Notifícalo como una diferencia de compilación, de perfil o de argumentos mientras no demuestres lo contrario, y conserva ambos conjuntos de resultados con sus registros. Repetir la ejecución hasta que los valores coincidan por casualidad oculta la causa y deja la siguiente ejecución igual de incierta.

Acotar una discrepancia sin adivinar

PasoQué comparar primeroQue coincida aquí significa
1La lista completa de argumentosLa semilla y los interruptores de canal llegaron
2El resumen del archivo de perfilSe cargaron los mismos bytes de perfil
3La cadena de compilaciónEl mismo binario produjo ambas ejecuciones
4Las entradas de la escenaLa página dibujó lo mismo dos veces

Las seis causas anteriores son fáciles de enumerar y difíciles de separar, porque todas producen el mismo síntoma: dos registros que difieren. Recorrer las cuatro entradas en este orden cuesta una comparación cada una y descarta las explicaciones baratas antes de tocar la página.

Compara primero la lista de argumentos, y compárala como texto en lugar de hacerlo de memoria. Un lanzador que descarta una marca, un envoltorio que añade la suya y un shell que expandió una variable de otra forma dejan la misma huella: la ejecución que produjo los valores discrepantes nunca tuvo la semilla que crees. Imprime los argumentos efectivos de ambas ejecuciones y compáralos.

Después compara el archivo de perfil, por resumen y no por nombre. Dos archivos con el mismo nombre en directorios distintos, o un archivo reemplazado durante una actualización de perfil, producen una discrepancia que parece un problema de semilla y es un problema de perfil. La comparación de resúmenes lo convierte en una respuesta de sí o no.

Luego la cadena de compilación, completa y no solo la versión mayor. Una actualización menor dentro de la misma versión mayor puede cambiar una ruta de dibujo mientras todos los números visibles siguen pareciendo familiares. Si la compilación difiere, deja de tratar los dos registros como comparables y conserva ambos como líneas base separadas.

Solo cuando esas tres coinciden vale la pena revisar la escena. Compara las dimensiones del lienzo, la cadena de texto, el orden de dibujo y los parámetros del búfer de audio, porque cualquiera de ellos cambia la entrada que recibe el generador y por tanto la salida que produce con la misma semilla. Un cambio de escena es la única causa en la que la semilla funciona correctamente y el resultado aún difiere.

Para aislar una superficie que deja de repetirse, desactiva un canal cada vez, compara y vuelve a activarlo:

chromium-browser \
  --bot-profile="path/to/profile.enc" \
  --bot-noise-seed=42 \
  --bot-noise-canvas=false

Si las demás superficies se repiten con el ruido de Canvas desactivado, lo que varía es la escena de Canvas o su lectura. Restablece el interruptor y guarda en tus notas la línea de comandos final, para poder pegar los mismos argumentos en la siguiente sesión.

Reproducir resultados en CI

Un trabajo de CI es un arranque que nadie vigila, así que necesita el registro que una persona llevaría en la cabeza. Fija en la configuración del trabajo la compilación de BotBrowser, el archivo de perfil, la semilla y los argumentos de arranque completos, y escríbelos en la salida del trabajo junto con los valores que informó la página de comprobación. Cuando una comparación falle semanas después, esa salida te permitirá reproducir la ejecución en otra máquina en lugar de adivinar.

Un registro útil tiene unos pocos campos por cada semilla:

  • El valor de la semilla y la identidad o el caso de prueba al que pertenece.
  • El nombre del archivo de perfil y su versión.
  • La compilación de BotBrowser.
  • El sistema operativo de destino del anfitrión y el tipo de máquina.
  • La lista completa de argumentos, incluida cualquier semilla de temporización.
  • Los valores que informó la página de comprobación, con la fecha de la ejecución.

Usa un directorio de datos de usuario nuevo en cada ejecución de CI, como en el arranque anterior, para que las cookies y el almacenamiento antiguos no influyan en la comparación. Guarda la semilla en la configuración del trabajo en lugar de elegirla dentro del trabajo, ya que una semilla elegida en tiempo de ejecución es un valor distinto en cada ejecución.

Ejecuta la página de comprobación como primer paso del trabajo, antes de las pruebas que dependen de ella. Si informa de valores que coinciden con la línea base guardada, continúa. Si informa de valores distintos, detente e indica cuál de estos elementos cambió: la compilación, el perfil, la semilla o los argumentos, en lugar de dejar que las pruebas posteriores fallen por un motivo difícil de ver.

Las actualizaciones son el otro momento para volver a comprobar. Después de actualizar BotBrowser, sustituir un archivo de perfil, pasar a otro ejecutor o editar los argumentos, ejecuta la página una vez con la semilla guardada y compárala con los valores guardados. Si coinciden, sigue adelante. Si difieren, trata los valores nuevos como una nueva línea base, anota la compilación que los produjo y no edites la semilla para recuperar la salida anterior, porque la semilla no fue lo que cambió.

A veces lo que quieres es precisamente un patrón nuevo, por ejemplo cuando retiras una identidad de prueba y empiezas otra. Cambia la semilla a propósito, actualiza la tabla y la línea base en la misma confirmación y conserva la fila antigua con su número de compilación. La semilla antigua sigue siendo una descripción correcta de lo que esa compilación produjo para ese perfil.

La repetibilidad entre máquinas y entre sistemas operativos sigue la misma regla. Ejecuta la página en cada ejecutor con la misma compilación, el mismo perfil y los mismos argumentos, y compara los valores. Una coincidencia es evidencia para esas máquinas. Una diferencia se notifica como un desajuste de compilación, de perfil o de argumentos que hay que rastrear, no se ignora.

Separar un desajuste de semilla de una deriva del fixture

Un fallo repetido es la única forma de distinguir un cambio de semilla de un cambio de fixture, y la comparación solo es válida mientras la escena, el build y el perfil permanezcan fijos. Las mediciones siguientes provienen de una página de prueba en una sola máquina: build Chromium 144.0.7559.97, un perfil Windows 10, un host Linux headless, un dibujo de canvas fijo de 220×60, un clear WebGL fijo de 64×64 y un búfer de audio offline fijo. El resumen son los primeros 32 caracteres hexadecimales del SHA-256 de canvas.toDataURL().

SemillaResumen de canvasEmparejamientoLectura
42fd0881c19451370e66313f61e760c77cejecutada dos veces, idénticala misma semilla se repite
43fd0881c19451370e66313f61e760c77ccoincide con la semilla 42una semilla distinta puede reproducir una salida anterior
4406ff31e59678fe4d923a85d73479fe2esalida nuevauna semilla distinta puede producir una salida nueva
4506ff31e59678fe4d923a85d73479fe2ecoincide con la semilla 44la colisión no es un accidente aislado
465877be94c6969400c80033f0a2f4528dsalida nuevauna tercera salida distinta
778138eccb72cb091408fc684572c3504asalida nuevaconfirma que el resumen responde a la semilla
123455877be94c6969400c80033f0a2f4528dcoincide con la semilla 46una segunda colisión

Se siguen dos conclusiones, y ambas son más estrechas de lo que parecen a primera vista.

La misma semilla se repite exactamente, que es la garantía de la opción. Pero dos semillas distintas también pueden producir la misma salida: en esta ejecución tres de las siete semillas colisionaron con una anterior. Cambiar la semilla no es, por tanto, una forma fiable de obtener una huella distinta. Trate la semilla como una entrada de una asignación finita y no como un identificador único, y cuando dos identidades no deban compartir salida de renderizado, verifique la salida en lugar de suponer que un entero nuevo basta.

La misma ejecución dejó sin cambios el resumen de WebGL, las muestras de audio y el ancho de texto en todas las semillas, así que solo se movió el resumen de Canvas. Es una observación bajo un build, un perfil y un host, no una afirmación sobre qué superficies cubre la opción en cada plataforma; los interruptores de canal de ruido son controles separados y esta prueba no los alternó. Repetir la prueba con pantalla headful, con un perfil macOS y con el canal de ruido WebGL activado mostraría si la misma separación se mantiene en otro entorno.

Qué demuestra y qué no demuestra un resultado coincidente

Una comprobación superada respalda una afirmación acotada: una compilación, un perfil y una semilla concretos repitieron la misma salida de Canvas, WebGL, Audio y medidas de texto en una máquina concreta, mientras que otra semilla cambió o colisionó en las superficies medidas. No respalda la afirmación de que el mismo resultado se mantenga en todas las máquinas, tras cada actualización o en todas las páginas. Escribe los resultados de la primera forma y el registro seguirá siendo exacto meses después.

Una huella repetible implica un compromiso. Presentar la misma salida en cada visita es lo que da continuidad de sesión, y es también lo que permite reconocer las visitas repetidas como repetidas. Una semilla fija no hace que una huella sea anónima ni única, y no dice nada sobre cómo la tratará un sitio concreto. El renderizado es solo un grupo de señales. La identidad del dispositivo que viene del perfil, la ruta de red, la temporización y lo que un sitio hace con la visita son controles distintos.

BotBrowser soporta un --bot-noise-seed entero fijo, de 1 a 4294967295, que hace que la salida de Canvas, WebGL, AudioContext y medidas de texto se repita para el mismo perfil entre sesiones y reinicios, de modo que los equipos pueden comparar ejecuciones, reproducir resultados de CI y mantener una línea base de renderizado estable para cada identidad. BotBrowser no puede hacer que la salida con semilla sea anónima ni inmune a las comprobaciones propias de un sitio, no garantiza resultados idénticos con otra compilación, otro perfil u otros argumentos de arranque, y no sustituye la asignación de semillas por identidad ni los controles de red o del lado del sitio.

Para más contexto, consulta Modo determinista, Huella de Canvas, Protección de la huella de audio y Gestión de perfiles.

Qué añade frente a la página de referencia

La página de referencia enumera la opción de semilla, su rango y las superficies afectadas. Mantén fijos el perfil, la compilación, los argumentos de arranque y la escena de prueba; compara dos arranques con la semilla 42 y después uno con la 43. Es un método para ejecutar, no un resultado que se afirme aquí. Si hay diferencias, sigue los pasos de diagnóstico anteriores para separar un cambio de escena o de argumentos de una diferencia de perfil, compilación o host antes de cambiar la semilla.

Fuentes

Conclusión práctica

Cambia la semilla solo cuando quieras una identidad distinta, no para corregir una diferencia de host. Si con la misma semilla, el mismo perfil y la misma compilación el resumen cambia, anota esa diferencia como dependiente del host.

#Noise-Seed#Deterministic#fingerprinting#Reproducibility#privacidad#Ci-Cd

Este artículo forma parte de la guía: ¿Qué es la huella digital del navegador?

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.