Control del recuento de núcleos de CPU con BotBrowser
Cómo navigator.hardwareConcurrency expone la identidad de la CPU para el fingerprinting y cómo BotBrowser controla el recuento de núcleos informado en todos los contextos.
Introducción
La propiedad navigator.hardwareConcurrency devuelve el número de núcleos lógicos de CPU disponibles para el navegador. Fue diseñada para ayudar a las aplicaciones web a optimizar cargas de trabajo paralelas, permitiendo que el código JavaScript decida cuántos Web Workers crear o cómo particionar tareas de procesamiento. Pero esa misma propiedad revela información de hardware que contribuye al fingerprinting del navegador. Un dispositivo con 6 núcleos lógicos es mucho menos común que uno con 8, y un servidor con 64 núcleos destaca inmediatamente. Debido a que el recuento de núcleos es estable, fácil de consultar y varía según la configuración de hardware, se ha convertido en un componente estándar en los sistemas de seguimiento. Este artículo explica cómo el recuento de núcleos contribuye al fingerprinting, por qué las sobrescrituras simples generan problemas y cómo BotBrowser proporciona un informe consistente del recuento de núcleos mediante su sistema de perfiles.
Impacto en la privacidad
El recuento de núcleos puede parecer una señal de bajo valor, pero su contribución es significativa en contexto. El valor de cualquier atributo de fingerprint depende de su distribución en la población. Según datos del proyecto AmIUnique, navigator.hardwareConcurrency tiene alrededor de 4.5 bits de entropía, lo que significa que puede distinguir aproximadamente 23 grupos diferentes. Aunque 23 grupos no parezcan mucho, cada bit adicional de entropía duplica aproximadamente el poder identificador cuando se combina con otras señales.
La distribución está fuertemente sesgada. Los valores 4 y 8 representan la mayoría de los navegadores de escritorio. Los valores 2 (máquinas antiguas, Chromebooks de bajo coste), 6 (ciertas configuraciones Intel), 12 (procesadores Ryzen 5), 16 (equipos de alto rendimiento) y cualquier valor por encima de 16 son progresivamente más raros. Un equipo que informe 24, 32 o 64 núcleos casi con seguridad es un servidor o estación de trabajo, algo extremadamente poco común en la población de navegación normal.
Los dispositivos móviles añaden más diferenciación. La mayoría de los teléfonos informan 4 u 8 núcleos, pero familias de SoC específicas (Snapdragon, Exynos, MediaTek, Apple Silicon) emparejan recuentos concretos con otras propiedades identificables. Un teléfono con hardwareConcurrency de 8 combinado con un patrón de user agent específico reduce el conjunto de dispositivos a unos pocos modelos.
La preocupación por la privacidad se amplifica porque hardwareConcurrency está disponible en todos los contextos de ejecución: hilo principal, dedicated workers, shared workers y service workers. No requiere permisos y no puede ser bloqueado sin romper aplicaciones web legítimas que lo usan para optimización de rendimiento.
Antecedentes técnicos
Cómo funciona hardwareConcurrency
La propiedad navigator.hardwareConcurrency devuelve un entero sin signo que representa el número de procesadores lógicos disponibles. “Procesadores lógicos” significa núcleos físicos multiplicados por hilos por núcleo (por ejemplo, una CPU de 4 núcleos con hyperthreading informa 8).
console.log(navigator.hardwareConcurrency); // p. ej., 8
El valor también está disponible en contextos worker:
// Dentro de un Web Worker
console.log(self.navigator.hardwareConcurrency); // mismo valor
Por qué varía el valor
Varios factores determinan qué devuelve hardwareConcurrency:
- Hardware físico. El número de núcleos y hilos depende del modelo del procesador. Los Intel i5 suelen tener 4-6 núcleos con hyperthreading. Los AMD Ryzen 7 tienen 8 núcleos con SMT. Los chips Apple M-series tienen diferentes recuentos de núcleos entre clústeres de eficiencia y rendimiento.
- Virtualización. Las máquinas virtuales informan el número de vCPU asignadas, que puede diferir del host. Una VM con 2 vCPU informará
hardwareConcurrencycomo 2. - Planificación del SO. Algunos sistemas operativos permiten limitar el recuento de procesadores visibles. Los entornos de contenedores (Docker, LXC) pueden restringir la visibilidad de CPU.
- Implementación del navegador. La mayoría de los navegadores informan el valor bruto del SO. Algunos han experimentado con limitar o agrupar el valor, pero Chromium informa normalmente el recuento real.
Correlación con otras señales
El recuento de núcleos no existe en aislamiento. Los sistemas de seguimiento lo cruzan con:
navigator.deviceMemory— Una máquina de 2 núcleos con 8 GB de RAM es plausible; una de 2 núcleos con 0.25 GB sugiere otra clase de dispositivo.navigator.platform— “Linux x86_64” con 4 núcleos limita a hardware específico. “Linux armv81” con 8 núcleos sugiere un servidor ARM o un teléfono.- User agent. La versión del navegador y del SO constriñe qué recuentos de núcleos son realistas.
- Tiempos de rendimiento. El rendimiento paralelo real (medido mediante canales laterales de temporización) puede compararse con el recuento informado.
Una inconsistencia entre recuento informado y rendimiento paralelo observable es una señal fuerte de manipulación.
Enfoques comunes de protección y sus limitaciones
Sobrescribir hardwareConcurrency manualmente mediante extensión o inyección JavaScript es lo más común. Esto cambia el valor retornado pero genera problemas:
- Inconsistencia de rendimiento. Si informas 4 núcleos pero la máquina real tiene 16, las cargas paralelas se ejecutarán más rápido de lo esperado en una máquina de 4 núcleos.
- Detección de prototipo. Las sobrescrituras JS pueden detectarse inspeccionando el descriptor de propiedad, la cadena de prototipos o midiendo el tiempo de ejecución del getter.
- Grietas en contextos worker. Algunas soluciones solo modifican el
navigatordel hilo principal y no parchean los workers.
Aleatorizar el valor crea configuraciones poco plausibles. Un valor aleatorio como 7 o 13 no corresponde a arquitecturas reales.
Usar un valor fijo común (como siempre reportar 8) es mejor que aleatorizar, pero puede entrar en conflicto con otras señales (por ejemplo, user agent que indica un teléfono de 4 núcleos).
La exigencia fundamental es que el recuento informado debe ser internamente coherente con otras propiedades del dispositivo y con características de rendimiento observables.
Enfoque a nivel de motor de BotBrowser
BotBrowser controla navigator.hardwareConcurrency a nivel del motor Chromium mediante su sistema de perfiles de fingerprint. Este enfoque aporta varias ventajas frente a modificaciones a nivel JS.
Valores guiados por perfil
Cada perfil de fingerprint de BotBrowser especifica un valor hardwareConcurrency que coincide con la configuración real del dispositivo perfilado. Un perfil de escritorio Windows 10 con Intel i7 informa 8 o 16 núcleos. Un perfil Android con Snapdragon 888 informa 8 núcleos. Los valores provienen de configuraciones de dispositivos reales, no de números arbitrarios.
Consistencia en todos los contextos
Dado que el control ocurre a nivel del motor, todos los contextos informan el mismo valor:
- Hilo principal
navigator.hardwareConcurrency - Dedicated Worker
self.navigator.hardwareConcurrency - Shared Worker
self.navigator.hardwareConcurrency - Service Worker
self.navigator.hardwareConcurrency
No existe una brecha donde un contexto muestre el valor real y otro el valor de perfil.
Coherencia entre señales
El valor hardwareConcurrency dentro del perfil forma parte de una identidad de dispositivo completa. Se alinea con:
- La cadena de user agent y la plataforma
- El valor de deviceMemory
- La resolución de pantalla y otras señales hardware
- La marca y versión del navegador
Esto evita que las comprobaciones cruzadas revelen inconsistencias.
Sin artefactos JavaScript
Puesto que el valor se establece a nivel del motor, no hay descriptores de propiedad modificados, ni getters no nativos, ni diferencias temporales que medir. La propiedad se comporta exactamente como en el hardware perfilado.
Configuración y uso
Carga básica de perfil
chrome --bot-profile="/path/to/profile.enc" \
--user-data-dir="$(mktemp -d)"
El perfil determina automáticamente el recuento de núcleos informado.
Verificación del valor
// Consola del navegador o script de automatización
console.log(navigator.hardwareConcurrency);
// Devuelve el recuento del perfil, no del hardware real
Integración Playwright
const { chromium } = require('playwright');
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);
// Verificar que el worker coincide
const workerCores = await page.evaluate(() => {
return new Promise(resolve => {
const blob = new Blob([
'postMessage(self.navigator.hardwareConcurrency)'
], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = e => resolve(e.data);
});
});
console.log(`Worker cores: ${workerCores}`);
Integración Puppeteer
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
defaultViewport: null,
args: [
'--bot-profile=/path/to/profile.enc'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);
Verificación
Chequeo del valor. Consulte navigator.hardwareConcurrency y confirme que coincide con el valor esperado del perfil cargado.
Consistencia en workers. Cree un Web Worker y consulte self.navigator.hardwareConcurrency dentro de él; el valor debe coincidir con el hilo principal.
Coherencia entre propiedades. Verifique que el recuento de núcleos sea plausible para la plataforma, user agent y deviceMemory del perfil.
Estabilidad entre sesiones. El valor debe ser idéntico en múltiples sesiones con el mismo perfil.
Buenas prácticas
- Use un perfil completo. No intente sobrescribir solo
hardwareConcurrencyde forma aislada. - Elija perfiles con configuraciones realistas. Valores comunes (4, 8) pasan desapercibidos más fácilmente que valores inusuales (6, 12, 24).
- Pruebe en contextos worker. Asegúrese de que las consultas en workers devuelvan el mismo valor que el hilo principal.
- Evite sobrescribir manualmente el recuento. Los perfiles BotBrowser están diseñados para coherencia interna; cambiar manualmente el recuento sin ajustar otras propiedades crea inconsistencias detectables.
FAQ
P: Cuáles son los valores más comunes de hardwareConcurrency? R: En escritorio, 4 y 8 son los más frecuentes, representando más del 70% de los navegadores. En móvil, 4 y 8 también dominan. Valores de 2, 6, 10, 12, 16 y superiores son progresivamente más raros.
P: Puede un sitio medir mi recuento real de núcleos independientemente de lo que informe hardwareConcurrency? R: Teóricamente, un sitio podría intentar medir el rendimiento paralelo con SharedArrayBuffer y temporizadores de alta resolución, pero las mitigaciones de seguridad del navegador (reducción de la precisión de temporizadores, requisitos COOP/COEP) dificultan esto. El control a nivel de motor de BotBrowser además ayuda a mantener coherencia.
P: Cambia hardwareConcurrency con las actualizaciones del navegador? R: No. El valor refleja hardware y configuración del SO, no la versión del navegador.
P: Está disponible navigator.hardwareConcurrency en todos los navegadores? R: Sí. Los principales navegadores (Chrome, Firefox, Safari, Edge) lo soportan y está estandarizado en la especificación HTML.
P: Por qué algunas VMs informan recuentos diferentes al host? R: Las VMs muestran los vCPU asignados por el hipervisor; el host puede tener más núcleos, pero la VM solo ve los asignados.
P: Afecta el recuento de núcleos al rendimiento de Web Workers en BotBrowser? R: BotBrowser controla solo el valor reportado, no la planificación real del CPU. La ejecución sigue usando el hardware real; el valor solo afecta lo que JavaScript ve.
Resumen
navigator.hardwareConcurrency es un dato sencillo pero significativo para el fingerprinting cuando se combina con otras señales. BotBrowser controla este valor a nivel del motor mediante perfiles, garantizando consistencia en todos los contextos de ejecución JavaScript y coherencia con el resto de señales de identidad.
Para temas relacionados, vea What is Browser Fingerprinting, Navigator Property Protection y Deterministic Browser Behavior.
title: "Control de nucleos de CPU con BotBrowser" description: "Como BotBrowser controla navigator.hardwareConcurrency a traves de perfiles de huella digital para reportar nucleos de CPU consistentes en todos los contextos." date: "2025-05-14" locale: es category: fingerprint tags: ["cpu", "cores", "hardwareConcurrency", "fingerprinting", "privacy"] published: true
El riesgo de privacidad
navigator.hardwareConcurrency devuelve el numero de nucleos logicos del procesador disponibles para el navegador. Este valor es una senal de rastreo porque revela la clase de dispositivo: servidor, escritorio, portatil o movil. No requiere permisos y es accesible desde el hilo principal, Web Workers e iframes.
La solucion de BotBrowser
BotBrowser establece el conteo de nucleos desde el perfil de huella digital a nivel del motor del navegador, antes de que cualquier JavaScript se ejecute. El valor es consistente en todos los contextos de ejecucion.
Cargar un perfil
chrome --bot-profile="/profiles/windows-chrome-122.enc" \
--user-data-dir="$(mktemp -d)"
Si el perfil fue capturado de un escritorio de 8 nucleos, navigator.hardwareConcurrency devuelve 8 independientemente de si la maquina host tiene 2 nucleos o 96 nucleos.
Todos los contextos coinciden
El conteo de nucleos del perfil se aplica a:
navigator.hardwareConcurrencyde la pagina principal- Contextos de Web Worker y SharedWorker
- Contextos de Service Worker
- Objetos navigator de iframe
Automatizacion basada en servidor
Al ejecutar en un servidor en la nube, el conteo de nucleos del host revelaria un entorno de servidor. BotBrowser presenta el conteo de nucleos de dispositivo de consumo del perfil:
const { chromium } = require('playwright-core');
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/profiles/windows-chrome-122.enc',
],
headless: true,
});
const page = await (await browser.newContext()).newPage();
const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log('Nucleos reportados:', cores); // 8, no 96
Verificacion
Verifica la consistencia del conteo de nucleos entre contextos:
const page = await (await browser.newContext()).newPage();
const mainCores = await page.evaluate(() => navigator.hardwareConcurrency);
const workerCores = await page.evaluate(() => {
return new Promise(resolve => {
const blob = new Blob([
'self.postMessage(navigator.hardwareConcurrency)'
], { type: 'application/javascript' });
const w = new Worker(URL.createObjectURL(blob));
w.onmessage = e => resolve(e.data);
});
});
console.log('Hilo principal:', mainCores);
console.log('Web Worker:', workerCores);
console.log('Coinciden:', mainCores === workerCores);
Ambos valores deben coincidir con el conteo de nucleos registrado en el perfil, no con el conteo real de la maquina host.
Primeros pasos
- Descarga BotBrowser desde GitHub
- Elige un perfil del repositorio de perfiles
- Inicia con
--bot-profilepara aplicar la identidad de hardware completa - Verifica con
navigator.hardwareConcurrencyen la consola del navegador