12k
All articles

¿Todavía puedes confiar en la cadena de user agent?

Consulta qué datos del user-agent siguen siendo fiables, cuáles congelan los navegadores y cómo Client Hints de Chromium y la detección de funciones evitan errores.

OpenReplay Team
OpenReplay Team
¿Todavía puedes confiar en la cadena de user agent?

En parte. La cadena de user agent sigue indicando de forma fiable la familia del navegador, su versión principal, si el dispositivo es móvil o de escritorio y la familia del sistema operativo. No indica de forma fiable la versión del sistema operativo, el modelo del dispositivo, la arquitectura de la CPU ni, en los navegadores basados en Chromium, la versión menor del navegador.

Si has encontrado Android 10; K en tus logs procedente de un teléfono que claramente no ejecuta Android 10, o Mac OS X 10_15_7 procedente de un MacBook con chip de la serie M, no hay nada roto. Esos valores son marcadores de posición, y los navegadores los envían a propósito.

Este artículo desglosa una cadena actual de Chrome y muestra qué campos están congelados en cada motor. Después explica qué sustituye a la cadena en Chromium y cuándo sigue siendo razonable analizarla.

Puntos clave

  • Todos los navegadores principales siguen empezando su cadena User-Agent con Mozilla/5.0, un token de compatibilidad que no dice nada sobre el navegador que la envía.
  • Chrome informa Windows NT 10.0; Win64; x64, Macintosh; Intel Mac OS X 10_15_7, X11; Linux x86_64 o Linux; Android 10; K independientemente de la versión real del sistema operativo, y sus números de versión menor, compilación y parche son siempre 0.0.0.
  • A partir de Safari 26, Safari en iOS, iPadOS y visionOS informa una versión del sistema operativo congelada. Safari en Mac mantiene congelada la versión de macOS desde 2017.
  • Los User-Agent Client Hints solo existen en los navegadores basados en Chromium. Firefox y Safari no envían encabezados Sec-CH-UA-*.
  • Cualquier cliente puede enviar cualquier User-Agent, por lo que el encabezado solo sirve para filtrar los bots que se identifican como tales.

¿Qué dice realmente una cadena de user agent de Chrome?

Solo un segmento de la cadena UA actual de Chrome para escritorio cambia entre versiones: la versión principal. Todo lo demás es un token de compatibilidad fijo o un valor de plataforma congelado. Este es Chrome 154 en Windows:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36
SegmentoQué afirma¿Es cierto?
Mozilla/5.0Un navegador compatible con MozillaNo significa nada. Todos los navegadores lo envían
(Windows NT 10.0; Win64; x64)Windows 10, x86 de 64 bitsCongelado. Windows 11 y los equipos ARM envían el mismo valor
AppleWebKit/537.36 (KHTML, like Gecko)Un motor WebKit derivado de KHTML y similar a GeckoResiduo de compatibilidad. El motor de Chrome es Blink
Chrome/154.0.0.0Chrome 154.0.0.0La versión principal es real. 0.0.0 es un marcador de posición
Safari/537.36SafariNo es Safari. Se mantiene para que el código que busca “Safari” siga coincidiendo

La referencia de Firefox en MDN describe Mozilla/5.0 como un token genérico que declara compatibilidad con Mozilla, y casi todos los navegadores lo envían sea cual sea su motor. La referencia de User-Agent en MDN confirma que los navegadores basados en Blink incluyen KHTML, like Gecko y Safari únicamente como tokens de compatibilidad. En una cadena de Chrome, AppleWebKit/537.36 (KHTML, like Gecko) y Safari/537.36 no describen ni el motor de Chrome ni Safari. Son tokens fijos que se conservan para que el código antiguo de detección siga funcionando. Para ver este mismo desglose con tu propia cadena, pégala en el analizador de user agent de OpenReplay.

¿Qué campos del user agent están congelados y cuáles siguen siendo fiables?

Los tres motores han congelado las partes de alta entropía de la cadena: la versión del sistema operativo, el modelo del dispositivo y la arquitectura de la CPU. Chromium, además, pone a cero la versión menor del navegador. Las partes de baja entropía siguen reflejando el navegador real. El plan de User-Agent Reduction de Chrome empezó a fijar la versión menor, la compilación y el parche en 0.0.0 en Chrome 101 (2022). Desde que terminó, el 23 de septiembre de 2023, la prueba de retirada que permitía a los sitios seguir recibiendo la cadena completa, todas las cargas de página reciben la cadena reducida. La guía de reducción del UA de MDN enumera los valores de plataforma fijos, incluido Android 10; K en Android.

Chrome / EdgeFirefoxSafari
Familia del navegador, versión principalRealRealReal (Version/)
Móvil o escritorio, familia del SORealRealReal
Versión del SOCongeladaLimitada (macOS 10.15, Android 10)Congelada (macOS; iOS desde la 26)
Modelo del dispositivoK en AndroidNunca se envíaNunca se envía
Arquitectura de la CPUCongeladaCongeladaEn Mac, siempre “Intel”
Versión menor0.0.0No se exponeReal (Version/)
UA Client HintsSíNoNo

Edge usa los mismos tokens congelados que Chrome y añade Edg/. Desde Firefox 87, Firefox informa todas las versiones de macOS a partir de Big Sur como 10.15 e identifica los Mac con Apple Silicon como Intel. Desde Firefox para Android 122, informa Android 10 sea cual sea la versión real. Según la publicación de WebKit sobre Safari 26.0, Safari en Mac envía el mismo valor Intel Mac OS X 10_15_7 desde 2017. A partir de Safari 26 (septiembre de 2025), Safari en iOS, iPadOS y visionOS también informa una versión congelada de iOS 18 en lugar de la real. Safari 26.0 enviaba 18_6. Desde Safari 26.2, WebKit fija el valor en la última versión de iOS 18, por lo que las cadenas actuales envían 18_7. El token Version/ se sigue actualizando con cada versión.

La reducción de Chromium abarca Chrome en Windows, macOS, Linux, ChromeOS y Android. No abarca Android WebView ni Chrome para iOS. En la práctica:

  • Windows 10 y Windows 11 son indistinguibles.
  • Los Mac con Apple Silicon se identifican como “Intel” en los tres motores.
  • Una cadena de Chrome para Android con Android 10; K no describe un dispositivo con Android 10. Todas las instancias de Chrome en Android envían esa versión y el modelo de marcador de posición K.

¿Por qué es mejor la detección de características que la detección del navegador?

El nombre de un navegador no dice nada fiable sobre lo que es capaz de hacer. La detección de características comprueba directamente la capacidad, y eso ya era así antes de que se congelara ninguna cadena. Una comprobación basada en el UA falla cuando la cadena miente, cuando un navegador nuevo incorpora la API o cuando una versión antigua carece de ella. Baseline ofrece una visión multinavegador de cuándo se puede confiar en una característica. Cuando no se puede, una comprobación en tiempo de ejecución cubre el hueco:

// Brittle: guesses capability from a name
if (/Chrome\/\d+/.test(navigator.userAgent)) enableShareButton();

// Direct: asks the browser
if ('share' in navigator) enableShareButton();

¿Cómo funcionan los User-Agent Client Hints?

Los User-Agent Client Hints son un conjunto de encabezados de solicitud Sec-CH-UA-* que los navegadores basados en Chromium envían en sustitución de los detalles que la cadena UA ya no incluye. Chrome y Edge envían Sec-CH-UA, Sec-CH-UA-Mobile y Sec-CH-UA-Platform de forma predeterminada. Firefox y Safari no envían ninguno. MDN clasifica Sec-CH-UA-Platform como un hint de baja entropía, por lo que el navegador lo incluye sin que el servidor lo solicite, salvo que una política de permisos lo bloquee. Todos los demás hints deben solicitarse.

Para solicitar hints, el servidor los enumera en Accept-CH, y el navegador los incluye en las solicitudes seguras posteriores a ese origen.

Accept-CH no tiene efecto en la primera solicitud. Para obtener un hint de alta entropía en la primera solicitud, el servidor debe indicarlo en Critical-CH además de en Accept-CH. En lugar de renderizar esa primera respuesta, el navegador vuelve a enviar la solicitud, esta vez con el hint. El servidor también debe añadir el hint a Vary para que las cachés almacenen cada versión por separado.

import https from 'node:https';
import { readFileSync } from 'node:fs';

https.createServer(
  { key: readFileSync('key.pem'), cert: readFileSync('cert.pem') },
  (req, res) => {
    const platform = req.headers['sec-ch-ua-platform'];           // default hint
    const version = req.headers['sec-ch-ua-platform-version'];    // opt-in only

    res.setHeader('Accept-CH', 'Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch');
    res.setHeader('Critical-CH', 'Sec-CH-UA-Platform-Version');
    res.setHeader('Vary', 'Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch');
    res.setHeader('Content-Type', 'text/plain');
    res.end(`platform=${platform ?? 'n/a'} version=${version ?? 'n/a'}\n`);
  }
).listen(8443);

Node convierte los nombres de los encabezados a minúsculas. Los valores llegan como cadenas entrecomilladas con formato de campo estructurado (structured field), como "Windows". En el navegador, navigator.userAgentData.getHighEntropyValues() devuelve los mismos datos sin necesidad de configurar encabezados. MDN marca uaFullVersion como obsoleto en favor de fullVersionList.

async function describeClient() {
  const uaData = navigator.userAgentData;
  if (!uaData) return { source: 'ua', ua: navigator.userAgent }; // Firefox, Safari
  const high = await uaData.getHighEntropyValues([
    'platformVersion', 'architecture', 'model', 'fullVersionList',
  ]);
  return { source: 'ua-ch', brands: uaData.brands, mobile: uaData.mobile, ...high };
}

¿Cuándo sigue siendo razonable analizar la cadena de user agent?

Analizarla sigue siendo razonable cuando solo necesitas los campos que siguen siendo fiables y cuando equivocarse tiene un coste bajo.

Segmentos de analítica. El análisis del user agent es preciso para segmentos de analítica como “Chrome 154, escritorio, Windows”. Un segmento “Windows 10” o “Android 10” no lo es: absorbe sin avisar las versiones más recientes, así que trátalo solo como familia del sistema operativo. Comprueba Edg/ antes que Chrome/, y Chrome/ antes que Safari/, porque cada cadena contiene los tokens que aparecen después en esa lista.

Filtrado de bots. El RFC 9110 define User-Agent como un encabezado que proporciona el cliente, y nada lo verifica. Cualquier cliente puede enviar cualquier valor. El encabezado detecta los rastreadores que se identifican y no sirve de nada contra los bots que no lo hacen.

Tickets de soporte. Cuando un usuario informa de un error, normalmente necesitas saber aproximadamente qué estaba usando, no su compilación exacta. Las herramientas de reproducción de sesiones registran el UA con cada sesión, lo que basta para ver que un error se reproduce en Firefox en macOS pero no en Chrome. Registrar además el resultado de tus comprobaciones de características acota aún más el problema.

Conclusión

Puedes confiar en la cadena de user agent para conocer la familia del navegador, la versión principal, si es móvil o escritorio y la familia del sistema operativo. Trata todo lo demás como un marcador de posición. Para aplicar estas conclusiones, audita tu código en busca de cualquier rama que lea de la cadena una versión del sistema operativo, un modelo de dispositivo o una versión menor. Sustituye las comprobaciones de capacidades basadas en el UA por detección de características y traslada las necesidades reales de detalle de plataforma a los Client Hints, con una alternativa para Firefox y Safari, que no los envían.

Preguntas frecuentes

¿Cómo distingo Windows 11 de Windows 10 si el user agent dice Windows NT 10.0?

Solicita el client hint platformVersion, ya sea con navigator.userAgentData.getHighEntropyValues(['platformVersion']) o enviando Accept-CH: Sec-CH-UA-Platform-Version. Microsoft documenta que los valores de 1.0.0 a 10.0.0 corresponden a Windows 10 y los de 13.0.0 o superiores a Windows 11, y su código de ejemplo trata una versión principal de 13 o superior como Windows 11. Firefox no envía Client Hints, por lo que no permite distinguir entre ambos.

¿Durante cuánto tiempo sigue enviando un navegador los hints solicitados con Accept-CH?

Chrome guarda en disco las preferencias de Accept-CH de cada origen y, desde Chrome 103, no tienen una caducidad fija. Duran hasta que el usuario borra las cookies o los datos del sitio de ese origen, y también se eliminan junto con las cookies de sesión. Un servidor puede volver a enviar Accept-CH para sustituir la lista, enviar un Accept-CH vacío para detener todos los hints o enviar Clear-Site-Data: 'clientHints'.

¿Por qué el encabezado Sec-CH-UA contiene una marca como Not A;Brand?

Es una entrada deliberadamente falsa conocida como GREASE. Chromium añade una marca intencionadamente incorrecta con un número de versión bajo, y varía su puntuación y su posición en la lista. Esto obliga a los servidores a analizar el encabezado correctamente en lugar de buscar una cadena fija o una lista fija de marcas. Analiza Sec-CH-UA como una lista de campos estructurados, busca la marca que necesitas, como Chromium, Google Chrome o Microsoft Edge, e ignora cualquier entrada que no reconozcas.

¿Por qué mi analizador de user agent identifica Chrome en iPhone como Safari?

Chrome para iOS envía la cadena de user agent de Mobile Safari con un token CriOS/ en lugar de Version/, por lo que la cadena no contiene el token Chrome/. Firefox para iOS hace lo mismo con FxiOS/. Un analizador que solo busca Chrome/ y Firefox/ acaba clasificándolos como Safari, así que comprueba primero CriOS/ y FxiOS/. La reducción del UA de Chromium no abarca Chrome para iOS.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.