Del valor a la relación
El fingerprinting temprano era una lista. Recoger canvas, WebGL, fuentes, tamaño de pantalla, zona horaria; hashearlo todo junto; comparar el hash. Si coincidía con un valor conocido como malo, bloquear.
Ese enfoque murió hace mucho, por una razón sencilla: se vencía cambiando valores. Lo sustituyó la correlación entre atributos: en vez de preguntar cuánto vale cada dato, el sistema pregunta si esos valores podrían pertenecer al mismo ordenador.
Eso cambia enormemente la dificultad. Falsear un valor es trivial. Falsear cuarenta valores que impliquen todos la misma máquina es un problema de modelado, y es el problema donde fallan casi todas las configuraciones antidetect, porque su interfaz te invita a elegir cada campo por separado de un desplegable.
No intentas producir un fingerprint raro. Intentas producir uno que no llame la atención: la descripción verosímil de un ordenador corriente que resulta no ser el tuyo.
Las contradicciones que se comprueban
Estas son las correlaciones que más aparecen en la lógica de detección real. Ninguna es exótica; todas son baratas.
GPU frente a plataforma
Tu cadena de renderizador WebGL sin enmascarar nombra un chip real y una ruta de controlador real. ANGLE (Apple, Apple M2, OpenGL 4.1) es un Mac. ANGLE (NVIDIA, NVIDIA GeForce RTX 4070 Direct3D11 vs_5_0 ps_5_0, D3D11) es Windows — Direct3D no existe en otro sitio. Un user agent que dice macOS junto a un renderizador D3D11 no es un dispositivo raro; es uno imposible.
GPU frente a pantalla
Una máquina con GPU de la serie M y una pantalla de 1366×768 a devicePixelRatio 1 no existe: Apple no ha vendido ese panel en la época relevante. Gráficos integrados de hace una década junto a una pantalla de 3840×2160 es igual de improbable. Los proveedores de detección mantienen tablas de distribución precisamente para estos pares.
Fuentes frente a sistema operativo
Los conjuntos de fuentes son firmas del sistema operativo. Segoe UI viene con Windows. SF Pro y Helvetica Neue con macOS. Ubuntu y la familia Liberation con las distribuciones Linux habituales. Un perfil «Windows» que no puede dibujar Segoe UI ha fallado una comprobación que le cuesta al rastreador una sola llamada a measureText. La superficie de las fuentes merece tratamiento aparte, y lo tiene.
Zona horaria frente a IP
El fallo más común de todos, y el menos técnico. Intl.DateTimeFormat().resolvedOptions().timeZone devuelve lo que el navegador cree ser; la IP dice de dónde sale la conexión. Una IP residencial brasileña con Europe/Rome es un desajuste que marcaría cualquier ingeniero novato. Peor aún: el navegador también expone el getTimezoneOffset() en crudo, así que un perfil que falsea el nombre IANA pero no el desfase se contradice solo, sin ningún dato externo.
Idioma frente a todo lo demás
Hay tres superficies de idioma y a menudo solo se fijan dos: la cabecera HTTP Accept-Language, navigator.languages en JavaScript y la configuración regional que resuelve la API Intl. Hemos visto perfiles en activo anunciando it-IT desde JavaScript y en-US,en;q=0.9 en la cabecera al mismo tiempo. Es un error de configuración visible en un log de peticiones.
Números del hardware frente a clase de dispositivo
hardwareConcurrency y deviceMemory deberían describir una máquina que alguien compró de verdad. deviceMemory está cuantizado por la especificación a 0.25, 0.5, 1, 2, 4, 8 — un valor de 6 no solo es raro: está fuera de especificación. Sesenta y cuatro núcleos lógicos junto a 4 GB de memoria declarada no describen nada que exista en el mercado.
Táctil frente a formato del aparato
maxTouchPoints > 0 en un user agent de escritorio, sin un perfil de dispositivo táctil que lo acompañe, es un resto habitual de copiar un fingerprint móvil. También lo es un user agent móvil con una pantalla de 1920×1080 y un puntero de ratón.
La comprobación en dos contextos
Más allá de la verosimilitud por parejas hay una prueba más estricta, y es la que termina sesiones: haz la misma pregunta en dos sitios y compara.
El navegador expone varios contextos de ejecución que deberían describir la misma máquina: la ventana principal, un Web Worker, un iframe y un Service Worker. Un override a nivel de página suele llegar solo al primero. Los scripts de detección leen hardwareConcurrency, deviceMemory, platform, userAgent y las cadenas de WebGL desde un worker y las contrastan con las de la ventana.
No hay explicación inocente para un desacuerdo. No es una heurística con tasa de falsos positivos; es una prueba. Es el argumento más fuerte para manejar los fingerprints en el motor y no en un script inyectado, y se trata con más detalle en el artículo sobre CDP.
Dónde fallan los generadores de perfiles aleatorios
Las herramientas que generan un «fingerprint aleatorio» suelen muestrear cada campo de forma independiente de una lista de valores verosímiles. Cada campo por separado parece correcto. La combinación suele ser absurda.
El muestreo independiente produce una GPU de Mac con un conjunto de fuentes de Windows, una pantalla 4K sobre gráficos integrados de 2014, o un user agent de Chrome 147 con una lista de marcas userAgentData de Chrome 131. Cada valor pasó su propia validación; la máquina descrita no existe.
El arreglo es muestrear la máquina, no los campos. Parte de un arquetipo de dispositivo real — digamos, un ThinkPad de 2023 con gráficos Iris Xe, 16 GB de RAM, un panel de 1920×1080 y el conjunto de fuentes de Windows 11 — y deriva de él todos los valores. Varía dentro del rango realista del arquetipo, nunca entre arquetipos.
Una prueba útil para cualquier herramienta: crea diez perfiles y lee su renderizador WebGL y su plataforma. Si consigues una GPU de Apple junto a Win32, el generador está muestreando campos.
Corriente gana a único
Un último punto que va contra el instinto. La unicidad no es el objetivo. Un fingerprint que no coincide con nada registrado es en sí mismo una señal: significa que el rastreador nunca ha visto esta configuración, y eso no es lo que parece un usuario corriente.
El sitio cómodo es el centro de la distribución. Una pantalla de 1920×1080, 8 o 16 GB de RAM, 8 núcleos lógicos, una GPU de gama media, el conjunto de fuentes por defecto del sistema operativo y una zona horaria que cuadre con la IP de salida. Aburrido en todas las dimensiones, y compartido con millones de máquinas más.
Resiste la tentación de elegir hardware impresionante. Una estación de trabajo de 32 núcleos con 128 GB de RAM es memorable, y memorable es lo contrario de lo que quieres.
Una lista de comprobación que puedes pasar
Antes de poner un perfil a trabajar, verifica esto en orden. Cualquier fallo merece arreglarse antes de continuar:
- La geolocalización de la IP,
timeZoneygetTimezoneOffset()apuntan todos al mismo sitio. Accept-Language,navigator.languagesy la configuración regional que resuelve Intl concuerdan.- El renderizador WebGL nombra un chip que se vende con la plataforma del user agent.
- La lista de fuentes es el conjunto por defecto de esa versión del sistema operativo, y nada exótico añadido.
- La resolución de pantalla y el devicePixelRatio describen un panel que se vendió con esa clase de GPU.
deviceMemoryes un valor legal yhardwareConcurrencyresulta verosímil a su lado.- Un Web Worker devuelve los mismos valores que la ventana.
- El hash del canvas es estable entre renderizados y entre sesiones — mira por qué importa.
- WebRTC no informa una IP distinta de la del proxy. Esta fuga es silenciosa.
- Las marcas de
navigator.userAgentDatacoinciden con la versión mayor de Chrome en la cadena del user agent.
CreepJS hará casi todo esto por ti y te dirá claramente qué pares considera incoherentes. Pásalo una vez por plantilla de perfil, no una vez por perfil: si la plantilla es sólida, los perfiles derivados también lo serán.