Volver al Centro de conocimiento
Huella digital

Fingerprinting del Navigator: fugas del navegador

Cómo valores de navigator como platform, hardwareConcurrency, deviceMemory, languages y userAgentData forman una señal de huella y cómo comprobar que siguen siendo coherentes.

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 página puede leer navigator.platform, navigator.hardwareConcurrency, navigator.deviceMemory, navigator.languages y navigator.userAgentData antes de pedir un solo permiso, y un script que anota todos esos valores obtiene una descripción compacta de la máquina que hay detrás de la petición. BotBrowser carga esos valores desde un perfil en un contexto controlado, de modo que el hilo principal, un Web Worker y las cabeceras Sec-CH-UA describen el mismo dispositivo. Lo que sigue explica cómo se combinan estos valores en una señal de huella, dónde empieza un valor modificado a contradecir a sus vecinos y cómo comprobar la coherencia antes de que lo haga un sitio.

Resumen

  • Los valores de navigator se leen sin ningún aviso de permiso y se juzgan en conjunto, así que un valor común en compañía improbable pesa más que cualquier lectura suelta.
  • userAgent, platform, vendor, userAgentData y la cabecera Sec-CH-UA responden dos veces a las mismas preguntas; si el cambio se aplica a uno solo, queda un desacuerdo visible.
  • Un cambio hecho en el script de la página no llega a un Web Worker ni a una cabecera de petición, porque ambos leen desde otro ámbito.
  • BotBrowser toma los valores de navigator del perfil cargado, --bot-network-info-override cubre navigator.connection, y cambiar de perfil es mejor respuesta que corregir un campo suelto.

Contenido

Qué valores de navigator forman la señal

El objeto navigator es el lugar más básico donde una página averigua en qué navegador se está ejecutando. No pide ningún aviso de permiso, está disponible en cuanto empieza un script, y buena parte del código web corriente lo lee por motivos legítimos, como elegir un diseño, dimensionar un conjunto de workers o escoger un idioma para mostrar. Esa misma disponibilidad lo convierte en una entrada habitual para la creación de huellas. Ninguna propiedad identifica por sí sola a una persona. La señal surge de la combinación: un script lee muchos valores, los une en un solo registro y compara ese registro con los que ya ha visto. BotBrowser puede cargar los valores de navigator de un perfil coherente en un contexto controlado; no puede cambiar cómo un sitio combina o evalúa esos valores.

La guía del W3C sobre cómo mitigar la creación de huellas en las especificaciones web describe este patrón de forma directa. Cada capacidad del navegador añade un poco más de variación que un script puede leer, y muchas diferencias pequeñas juntas pueden bastar para distinguir navegadores aunque ningún valor concreto parezca raro. Por ese motivo, las secciones siguientes no citan una cifra fija de unicidad para los valores de navigator. Lo identificativa que resulta una combinación depende de la población de navegadores que ve realmente un sitio, y una cifra medida en una audiencia no se traslada a otra.

Un perfil cargado alimenta el hilo principal, un Web Worker y las cabeceras Sec-CH-UA, que informan la misma plataforma, número de núcleos, nivel de memoria, idiomas y marca. Abajo, una cadena UA que dice macOS junto a un valor de platform que sigue diciendo Win32 produce un desajuste.

El diagrama muestra las dos mitades del tema. Cuando una misma descripción del dispositivo alimenta todos los lugares que responden una pregunta sobre navigator, las respuestas coinciden. Cuando solo se cambia un valor, los valores relacionados siguen describiendo el dispositivo original, y el desacuerdo se convierte en una señal por sí mismo.

Valores de identidad: userAgent, platform y vendor

navigator.userAgent es el valor más antiguo y el que se lee con más frecuencia. Contiene el nombre del navegador, una versión y un token del sistema operativo. Los navegadores basados en Chromium reducen ahora el detalle de esta cadena, de modo que la versión del sistema operativo y la versión menor del navegador ya no aparecen escritas, y los detalles más finos pasaron a las User-Agent Client Hints. navigator.platform es una cadena corta como "Win32", "MacIntel" o "Linux x86_64". MDN la marca como obsoleta, pero los navegadores actuales siguen devolviendo un valor y los scripts siguen leyéndolo. navigator.vendor devuelve una cadena de proveedor que difiere entre familias de navegadores.

Estos tres valores describen los mismos dos hechos, qué navegador es y en qué sistema operativo se ejecuta, así que un script puede comprobar que concuerdan entre sí. Un navegador sin modificar supera esa comprobación sin esfuerzo, porque todos los valores salen de la misma instalación. Un navegador modificado la supera solo si todos los valores relacionados se modificaron a la vez.

Valores de hardware, idioma y conexión

navigator.hardwareConcurrency devuelve el número de procesadores lógicos disponibles para ejecutar hilos. Los navegadores pueden informar un número menor o redondeado respecto al que tiene realmente la máquina, así que conviene tratarlo como una pista que depende del hardware y del navegador, no como un inventario preciso. navigator.deviceMemory es una aproximación de la RAM del dispositivo en gigabytes. Solo existe en navegadores basados en Chromium, solo está disponible en contextos seguros y el valor informado tiene un tope de 8, de modo que una máquina con más memoria sigue informando 8. Ambos valores pueden leerse dentro de un Web Worker además de en la página principal, algo que importa para las comprobaciones que aparecen más adelante en este artículo.

navigator.language devuelve el idioma preferido y navigator.languages devuelve la lista ordenada de idiomas preferidos, por ejemplo en-US seguido de en. La lista y la cabecera de petición Accept-Language suelen derivar del mismo ajuste del navegador, así que el valor que lee una página y el que recibe un servidor describen las mismas preferencias. Una lista inusualmente larga, inusualmente corta o poco probable para la región indicada hace que la combinación sea más fácil de distinguir.

navigator.connection expone effectiveType, downlink, rtt y saveData en los navegadores basados en Chromium. Estos valores describen las condiciones de la red y no el hardware, y las cabeceras de Client Hints correspondientes pueden llevar la misma información en las peticiones. La compatibilidad difiere entre navegadores y las lecturas pueden cambiar con la red, de modo que se comportan de forma distinta a los valores de hardware anteriores. Aun así forman parte del mismo registro que ensambla un script.

Client Hints y userAgentData

navigator.userAgentData es la contrapartida estructurada de la cadena User-Agent en los navegadores basados en Chromium. Expone directamente la lista de marcas del navegador, un indicador de móvil y el nombre de la plataforma. Su método getHighEntropyValues() devuelve más detalle bajo petición, como la versión de la plataforma, la arquitectura, los bits, el modelo y la lista completa de versiones. La misma información viaja en las cabeceras de petición Sec-CH-UA. La lista de marcas, el indicador de móvil y la plataforma se envían por defecto, mientras que los valores de mayor entropía se envían solo después de que el servidor los solicite en una cabecera de respuesta Accept-CH.

Así, tres lugares responden preguntas sobre el mismo navegador: la cadena User-Agent, el objeto userAgentData y las cabeceras de Client Hints. Un navegador coherente da la misma respuesta en los tres, y un script o un servidor que los compare necesita solo unas pocas líneas de código para hacerlo.

Las configuraciones comunes las comparten muchísimos navegadores, y las inusuales las comparten muy pocos. Un número de núcleos típico de un portátil, una cadena de plataforma habitual y una lista de idiomas muy extendida dicen poco por sí solos. Un número de núcleos muy distinto de lo que suelen informar los dispositivos de consumo, un nivel de memoria rara vez visto o una lista de idiomas poco habitual reducen el grupo de navegadores que podrían haber producido ese registro. El efecto exacto depende de la audiencia del sitio que lo recoge, por lo que aquí no se da una cifra única.

Por qué un solo valor modificado crea una incoherencia

La lección práctica es que los valores de navigator no son independientes. Describen una sola máquina, y un sitio puede comprobar que describen la misma. Cuando solo cambia un valor, los demás siguen describiendo la máquina original, y la diferencia entre ellos es una señal por sí misma.

Una cadena User-Agent modificada

Sustituir la cadena User-Agent es el enfoque más antiguo. Supón que una extensión cambia navigator.userAgent por una cadena de macOS mientras navigator.platform sigue devolviendo "Win32". Los dos valores nombran ahora sistemas operativos distintos. El mismo problema aparece cuando navigator.userAgentData sigue informando la plataforma original, o cuando las cabeceras de Client Hints se generan a partir de ajustes distintos de los valores de JavaScript.

Un sitio no necesita saber cuál de los valores es cierto. Solo necesita ver que se contradicen, y una contradicción es más distintiva que cualquiera de los valores por separado.

Valores aleatorizados

La aleatorización tiene una debilidad parecida. Elegir un número de núcleos y un valor de memoria al azar para cada sesión produce combinaciones que pocos dispositivos reales tienen, por ejemplo una cadena de plataforma móvil junto a un número de núcleos propio de un equipo de escritorio, o un valor de memoria que no encaja con el resto del hardware informado.

Un valor que cambia en cada visita tampoco supera la prueba de estabilidad más sencilla, porque un navegador real informa los mismos números de hardware la vez siguiente. Los valores que son a la vez inusuales e inestables resultan más distintivos que los valores reales a los que sustituyeron.

Cambios hechos en el lugar equivocado

El lugar donde se hace un cambio importa tanto como lo que se cambia. Un script inyectado en la página solo puede afectar a lo que lee el hilo principal. Un Web Worker tiene su propio ámbito global y su propio navigator, así que un cambio a nivel de página que no llegue a los workers deja allí visibles los valores originales. Las cabeceras de petición las produce el código de red del navegador y no el script de la página, de modo que un cambio a nivel de página nunca las modifica. El resultado son tres respuestas donde debería haber una.

Otras medidas habituales tampoco resuelven esta señal. Una VPN cambia la dirección de red y deja los valores de navigator como estaban. La navegación privada mantiene los mismos valores de hardware e idioma. Borrar las cookies elimina el estado almacenado, pero no altera lo que el navegador informa sobre sí mismo.

Un conjunto breve de reglas describe qué significa coherencia en la práctica:

  • El sistema operativo de la cadena User-Agent coincide con navigator.platform y con la plataforma de navigator.userAgentData.
  • La marca y la versión principal del navegador coinciden entre la cadena User-Agent, la lista de marcas de userAgentData y la cabecera Sec-CH-UA.
  • El número de núcleos y el nivel de memoria son verosímiles para la clase de dispositivo que implica la plataforma.
  • navigator.languages es verosímil para la configuración regional indicada y coincide con la cabecera Accept-Language.
  • Cada uno de estos valores es el mismo en el hilo principal, en los workers y entre sesiones repetidas.

Verificar la coherencia entre hilos y cabeceras

El objetivo de la verificación no es encontrar un número correcto. Es confirmar que cada lugar que responde una pregunta sobre navigator da la misma respuesta. Las comprobaciones siguientes solo necesitan un navegador y una página de prueba que controles tú, y no exigen visitar ningún sitio de terceros.

Hilo principal y Web Worker

Abre una página que controles y lee los valores en el hilo principal: la cadena User-Agent, la plataforma, el proveedor, el número de procesadores lógicos, la memoria del dispositivo, la lista de idiomas, y la lista de marcas y la plataforma de navigator.userAgentData. Anótalos. Después inicia un Web Worker dedicado desde la misma página, haz que lea las mismas propiedades desde su propio navigator y que devuelva el resultado a la página.

Compara los dos registros campo por campo. Deberían ser idénticos. Una diferencia suele significar que un valor lo estableció el script de la página, o que el worker lee de una fuente distinta a la de la página. Un worker dedicado es lo más sencillo de probar, y los workers compartidos y los service workers pueden añadirse a la misma comparación.

Cabeceras de Client Hints

A continuación, compara la salida de getHighEntropyValues() con lo que recibe un servidor. El método devuelve una promesa con los valores que indiques, por ejemplo la versión de la plataforma, la arquitectura, los bits y la lista completa de versiones. En el lado del servidor, las cabeceras de mayor entropía llegan solo después de que una respuesta anterior incluyera una cabecera Accept-CH que las solicite. Por eso la página de prueba necesita un servidor que controles, que envíe Accept-CH y que registre las cabeceras de petición que recibe.

Compara la lista de marcas y la plataforma de Sec-CH-UA y Sec-CH-UA-Platform con el objeto userAgentData, y compara las cabeceras de versión de la plataforma y de arquitectura con el resultado de alta entropía. Todas deberían describir el mismo navegador y la misma plataforma que la cadena User-Agent.

Sesiones repetidas

Cierra el navegador, inicia una sesión nueva con el mismo perfil y la misma configuración, y vuelve a ejecutar las mismas comprobaciones. Los valores que describen la plataforma y el hardware deberían ser los mismos en cada sesión. Si quieres confirmar que los valores cambian juntos, ejecuta una sesión más con un perfil distinto y comprueba que todas las vistas pasan a la nueva descripción del dispositivo a la vez.

Mantén fijas la versión del navegador y la del perfil durante una comparación. Un cambio de versión modifica legítimamente los valores de marca y de versión, y mezclar ese cambio en la comparación oculta el resultado que buscas.

La lista de comprobación completa, en orden:

  1. Anota los valores de navigator en el hilo principal.
  2. Anota los mismos valores dentro de un Web Worker y compáralos campo por campo.
  3. Solicita valores de alta entropía y compáralos con la lista de marcas y la plataforma de userAgentData.
  4. Captura las cabeceras de Client Hints en un servidor que controles y compáralas con los valores de JavaScript.
  5. Repite todo en una sesión nueva con el mismo perfil y compara los registros.
  6. Cambia un solo ajuste cada vez y repite la comparación después de cada cambio.

Trata el primer desacuerdo como el hallazgo. Anota qué dos vistas discrepan y vuelve a la configuración en lugar de añadir otro cambio encima, porque cada cambio adicional añade un lugar más que puede discrepar.

Iniciar con un perfil

Con BotBrowser, los valores de navigator provienen del perfil cargado, así que el inicio más sencillo es un perfil y un directorio de datos de usuario temporal:

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

La documentación de BotBrowser describe el perfil como la fuente de los valores de identidad, hardware, configuración regional, red y dispositivos multimedia, y indica que los valores de JavaScript, las cabeceras HTTP y los contextos de Worker devuelven valores coherentes a partir de él. Empieza con esta base y ejecuta las comprobaciones anteriores antes de añadir cualquier otro parámetro. Sin un perfil, los valores de navigator reflejan la máquina en la que realmente te estás ejecutando.

El idioma y la configuración regional pueden establecerse de forma explícita con --bot-languages y --bot-locale. Para la información de red, --bot-network-info-override controla los valores de navigator.connection y las cabeceras de Client Hints correspondientes, y la documentación limita la política resultante al BrowserContext. Configúralo antes de crear la primera página de ese contexto, para que todas las páginas y workers del contexto vean los mismos valores.

chrome --bot-profile="path/to/profile.enc" \
       --bot-languages="en-US,en" \
       --bot-locale="en-US" \
       --bot-network-info-override \
       --user-data-dir="$(mktemp -d)"

Es preferible elegir otro perfil antes que sobrescribir valores sueltos encima de uno. Un perfil está construido para que los valores relacionados coincidan, y cambiar uno de ellos, el número de núcleos por ejemplo, deja sin cambiar los valores que dependen de él. El control personalizado de User-Agent, los parámetros de idioma y configuración regional y algunos parámetros de identidad, como la marca y la versión del navegador, están limitados por nivel de licencia en la documentación, así que confirma qué incluye tu licencia antes de planificar en torno a ellos.

Qué controla BotBrowser y qué no

BotBrowser deriva los valores de navigator (userAgent, platform, hardwareConcurrency, deviceMemory, languages y userAgentData) del perfil cargado, de modo que el hilo principal, los workers y las cabeceras de Client Hints devuelven un único conjunto coherente, y el parámetro --bot-network-info-override controla los valores de navigator.connection y los Client Hints correspondientes, lo que te da una configuración repetible para ejecutar las comprobaciones de coherencia anteriores. BotBrowser no puede impedir que los sitios recojan los valores de navigator ni que los correlacionen con otras señales, no puede garantizar que un perfil coincida con el hardware real o con lo que espera un sitio, y no sustituye la coherencia de red, de cuenta ni de comportamiento; el control personalizado de User-Agent depende del nivel de licencia.

Conviene detallar los límites, porque un conjunto coherente de valores de navigator responde solo a una de las preguntas que puede hacer un sitio.

  • Un sitio puede seguir leyendo los valores de navigator y combinarlos con señales de canvas, WebGL, fuentes y pantalla. Cada una de esas superficies necesita su propia revisión.
  • Un perfil describe un dispositivo y no es ese dispositivo. Un sitio puede tener expectativas sobre hardware o software que ningún perfil puede conocer de antemano.
  • La ubicación de red, el historial de la cuenta, la reputación y el comportamiento son entradas distintas. Unos valores de navigator coherentes no cambian ninguna de ellas.
  • El comportamiento documentado se aplica a un perfil válido cargado en una configuración compatible, así que verifícalo en tu propia configuración con la lista de comprobación anterior.

Trata la coherencia de navigator como una parte de una configuración consistente. La lista de comprobación te dice si esa parte se sostiene, y no dice nada sobre cómo tratará un sitio concreto una sesión.

Preguntas sobre los valores de navigator

P: ¿Basta hardwareConcurrency para identificar a alguien? R: No. Es una entrada entre muchas. Los valores comunes los comparten muchos navegadores y los poco frecuentes reducen más el grupo, pero la señal útil surge de la combinación con la plataforma, la memoria, el idioma y las demás superficies.

P: ¿Por qué deviceMemory se detiene en 8? R: El valor es una aproximación, y los navegadores basados en Chromium le ponen un tope para limitar con qué precisión describe la máquina. Otras familias de navegadores no exponen la propiedad en absoluto, de modo que allí su ausencia es normal.

P: ¿Sirve de algo cambiar solo la cadena User-Agent? R: No, cuando navigator.platform, navigator.userAgentData o las cabeceras de Client Hints siguen describiendo el navegador original. Los valores relacionados deben cambiar juntos.

P: ¿Cambian los valores de navigator con una VPN o con la navegación privada? R: No. Los valores provienen del navegador y del sistema operativo, no de la ruta de red ni del modo de navegación.

P: ¿Por qué comparar un Web Worker con el hilo principal? R: Un worker tiene su propio navigator. Un valor que se cambió solo en el script de la página permanece sin cambiar allí, por lo que el worker es el lugar más rápido para encontrar una laguna.

P: ¿BotBrowser hace que un perfil sea igual al hardware real? R: No. El perfil define los valores que informa el navegador y los mantiene coherentes entre contextos. No convierte la máquina en el dispositivo que describe el perfil.

Para temas relacionados, consulta Client Hints, el número de núcleos de CPU, zona horaria, configuración regional e idioma e información de red. El conjunto completo de controles está en la página de funciones, y puedes verificar tú mismo la coherencia de navigator en el Centro de pruebas.

Conclusión práctica

Empieza por un perfil en lugar de una lista de sustituciones. Carga un perfil, lee los siete valores que concentran la mayor parte de la señal (navigator.userAgent, navigator.platform, navigator.vendor, navigator.hardwareConcurrency, navigator.deviceMemory, navigator.languages, navigator.userAgentData) y anota qué devuelve cada uno.

  1. Compara ese registro con la misma lectura dentro de new Worker('worker.js'); una diferencia señala un valor puesto por el script de la página.
  2. Compara userAgentData.brands y la plataforma con las cabeceras Sec-CH-UA y Sec-CH-UA-Platform que recibe tu servidor después de enviar Accept-CH.
  3. Repite la lectura en una sesión nueva con el mismo perfil; los valores de plataforma y hardware no deben moverse entre sesiones.
  4. Si dos vistas discrepan, sustituye el perfil en lugar del valor, porque un segundo cambio añade un segundo lugar que puede discrepar.

Un conjunto que supera estos cuatro pasos es coherente, y la coherencia es todo lo que afirma esta superficie: el navegador responde igual en todas partes a una misma pregunta, lo que todavía no dice nada sobre cómo tratará un sitio esa sesión.

Fuentes

Referencias públicas utilizadas para las afirmaciones sobre navigator, Client Hints y BotBrowser en este artículo:

#Navigator#fingerprinting#identidad del navegador#privacidad

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.