Back to Blog
Fingerprint

Navigator Properties Fingerprinting: What Your Browser Reveals

How navigator.platform, hardwareConcurrency, and deviceMemory expose your identity, and how to ensure consistent navigator properties.

Introduction

The navigator object in JavaScript is one of the most accessible sources of device information available to any website. Properties like navigator.platform, navigator.hardwareConcurrency, navigator.deviceMemory, navigator.userAgent, and navigator.languages reveal details about your operating system, CPU, RAM, and browser configuration. Individually, each property provides limited identifying power. Combined, they form a composite fingerprint that narrows the user population significantly. Unlike experimental APIs that may require permissions, navigator properties are universally available, widely supported, and queried by virtually every tracking script on the web. This article explains how navigator properties contribute to fingerprinting and how BotBrowser provides consistent, profile-driven values for every property.

Privacy Impact

Navigator properties are the foundation layer of browser fingerprinting. Every tracking script begins with navigator, because the data is free, requires no permissions, and is available immediately.

A 2020 study from the University of Iowa analyzed over 100,000 browser fingerprints and found that the combination of navigator.userAgent, navigator.platform, navigator.hardwareConcurrency, navigator.deviceMemory, and navigator.languages provided an average of 12.8 bits of identifying information. For context, 12.8 bits can distinguish roughly 7,000 unique configurations. Add screen resolution and timezone, and the combination typically identifies more than 90% of users uniquely.

The W3C's Privacy Interest Group has documented the privacy implications of navigator properties extensively. Their fingerprinting guidance document lists hardwareConcurrency, deviceMemory, and languages as "high-entropy" surfaces that contribute meaningfully to cross-site tracking. Despite this, these properties remain available without restrictions in all major browsers because too many legitimate web applications depend on them.

Enterprise and development environments face additional risk. Non-standard values like 64-core hardwareConcurrency (server testing), 0.25 GB deviceMemory (embedded devices), or unusual language combinations immediately stand out in any population.

Technical Background

The navigator object contains dozens of properties. Here are the most significant for fingerprinting:

Core Identity Properties

  • navigator.userAgent - The user agent string. Contains browser name, version, OS name, and OS version. Despite deprecation efforts, it remains the most queried property.
  • navigator.platform - Returns a string identifying the platform: "Win32", "MacIntel", "Linux x86_64", "Linux armv81", etc.
  • navigator.vendor - Returns the browser vendor. "Google Inc." for Chrome/Chromium-based browsers, "" for Firefox, "Apple Computer, Inc." for Safari.

Hardware Properties

  • navigator.hardwareConcurrency - Returns the number of logical CPU cores. Common values range from 2 to 16 for consumer devices. Values above 16 or below 4 significantly narrow the population.
  • navigator.deviceMemory - Returns the approximate RAM in GB. Possible values are 0.25, 0.5, 1, 2, 4, and 8 (capped at 8). This API is only available in Chromium-based browsers.

Locale and Language Properties

  • navigator.language - Returns the preferred language (e.g., "en-US").
  • navigator.languages - Returns an array of preferred languages in order (e.g., ["en-US", "en", "fr"]).

Connection and Media Properties

  • navigator.connection - The NetworkInformation API, exposing effectiveType, downlink, rtt, and saveData. These values reflect network conditions but are stable enough to contribute to fingerprinting.
  • navigator.mediaDevices - Enumerating media devices reveals the number and types of cameras, microphones, and audio outputs.

User Agent Client Hints

Modern Chromium browsers also expose navigator.userAgentData, which provides structured access to browser brand, platform, and mobile status. The high-entropy getHighEntropyValues() method returns detailed platform version, architecture, bitness, and device model information.

Why These Values Vary

Navigator property values depend on:

  • Operating system. Platform strings, default languages, and available memory APIs differ by OS.
  • Hardware. CPU core count and memory size are hardware-dependent.
  • Browser version. User agent strings change with each release. Client hint brands and versions evolve.
  • User configuration. Language preferences and locale settings are user-controlled.

The distribution of these values is uneven. A few configurations (8-core Windows 10 with 8 GB RAM, en-US language) are very common. Everything else is progressively rarer and more identifying.

Common Protection Approaches and Their Limitations

User agent spoofing is the oldest and most common approach. Extensions or browser settings change navigator.userAgent to a different string. The problem: most spoofing tools only change the UA string without adjusting other correlated properties. Claiming to be macOS via user agent while navigator.platform says "Win32" is an obvious inconsistency.

VPNs have no effect on navigator properties. These values are determined by the browser and operating system, not the network.

Incognito/private mode does not change navigator properties. Your fingerprint is identical in normal and private browsing.

Browser extensions that modify navigator properties operate in JavaScript and can be fingerprinted themselves. The presence of modified getters on navigator properties is detectable through prototype chain inspection and timing analysis.

Randomization of navigator properties creates unrealistic combinations. A device with 3 CPU cores, 3 GB memory, and a platform string of "Win64" does not correspond to any real hardware. These combinations are more unique and identifiable than honest values.

The fundamental challenge is consistency. Navigator properties must form a coherent set that matches a real device configuration. Platform must match user agent. Core count must be realistic for the reported hardware. Memory must align with the platform. Languages must be plausible for the reported locale.

BotBrowser's Engine-Level Approach

BotBrowser configures all navigator properties through its profile system at the engine level. When a profile is loaded, every property on the navigator object returns values derived from the profiled device.

Complete Property Coverage

BotBrowser's profiles define values for all fingerprint-relevant navigator properties:

  • userAgent, appVersion, platform, vendor, and appCodeName are all consistent with the profiled browser and OS.
  • hardwareConcurrency matches the profiled device's CPU configuration.
  • deviceMemory matches the profiled device's RAM tier.
  • language and languages match the profiled locale.
  • userAgentData (brands, platform, mobile flag, fullVersionList) is generated to match the profiled browser brand and version.

Internal Consistency

The critical advantage of BotBrowser's approach is that all properties are derived from a single coherent profile. There is no scenario where platform says "MacIntel" while userAgent contains "Windows NT 10.0". The profile defines the device identity, and all navigator properties reflect it.

This extends to User Agent Client Hints. When a site calls navigator.userAgentData.getHighEntropyValues(), the returned platform, platformVersion, architecture, bitness, model, and fullVersionList all match the profile. The Sec-CH-UA-* HTTP headers sent with requests match the JavaScript values.

Network Information Control

With the --bot-network-info-override flag, BotBrowser also controls navigator.connection values (rtt, downlink, effectiveType, saveData) and the corresponding Client Hints headers. This ensures that network-related navigator properties align with the profile.

Worker Consistency

Navigator properties are also available in Web Workers and Service Workers. BotBrowser ensures the same values are returned in all execution contexts, including dedicated workers, shared workers, and service workers. There is no gap where a worker returns your real hardware values while the main thread returns profile values.

Configuration and Usage

Basic Profile Loading

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

All navigator properties are configured automatically from the profile.

Language and Locale Override

# Auto-detect from IP (default)
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-languages=auto \
       --bot-config-locale=auto

# Manual override
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-languages="fr-FR,fr,en" \
       --bot-config-locale="fr-FR"

Network Information Override

chrome --bot-profile="/path/to/profile.enc" \
       --bot-network-info-override

Playwright Integration

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-config-languages=auto',
    '--bot-config-locale=auto',
    '--bot-config-timezone=auto'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

// Verify navigator properties
const platform = await page.evaluate(() => navigator.platform);
const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Platform: ${platform}, Cores: ${cores}`);

Puppeteer Integration

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-network-info-override'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

Verification

Property consistency check. Query all navigator properties and verify they form a coherent set. Platform should match the user agent OS. Core count should be realistic for the platform. Memory should be plausible.

Client Hints verification. Use navigator.userAgentData.getHighEntropyValues(['platform', 'platformVersion', 'architecture', 'bitness', 'model', 'fullVersionList']) and confirm the values match the profile. Check that Sec-CH-UA-* HTTP request headers match the JavaScript values.

Worker consistency. Run the same navigator property queries in a Web Worker and compare results with the main thread. They should be identical.

Cross-session stability. Query navigator properties across multiple sessions with the same profile. All values should be identical.

Best Practices

  • Always load a profile. Without --bot-profile, navigator properties reflect your actual system. The profile is what provides controlled values.
  • Use auto-detection for locale signals. --bot-config-timezone=auto, --bot-config-locale=auto, and --bot-config-languages=auto derive locale from your proxy IP, keeping navigator language properties consistent with your apparent location.
  • Do not manually override individual properties. The profile ensures internal consistency. Overriding one property (like hardwareConcurrency) without adjusting correlated values creates inconsistencies.
  • Monitor user agent format changes. Browser user agent strings change with each version. Use current profiles from the BotBrowser profiles repository to stay up to date.
  • Test in both main thread and workers. Verify navigator consistency across all execution contexts.

FAQ

Q: Does navigator.hardwareConcurrency really help identify users? A: Yes. While common values (4, 8) are shared by many users, uncommon values (1, 2, 6, 24, 64) are highly identifying. Combined with other navigator properties, even common values contribute to the overall fingerprint.

Q: What happens to navigator.deviceMemory on Firefox or Safari? A: deviceMemory is a Chromium-only API. Firefox and Safari do not expose it. BotBrowser profiles for Chrome/Edge/Brave include deviceMemory values. If a profile targets a browser that does not support this API, it is not exposed.

Q: Can websites tell if navigator properties have been modified? A: Poorly implemented modifications (JavaScript overrides) can be detected through prototype inspection and timing analysis. BotBrowser's engine-level control modifies the properties at the source, so there are no JavaScript-visible artifacts.

Q: Does BotBrowser handle the User-Agent reduction (UA-CH) changes? A: Yes. BotBrowser generates proper User Agent Client Hints (Sec-CH-UA-*) headers and navigator.userAgentData values that match the profile. The reduced user agent string and high-entropy hints are both consistent.

Q: How does BotBrowser handle navigator.webdriver? A: BotBrowser controls the navigator.webdriver property through its profile system, ensuring it returns the expected value for the browsing context.

Q: Are navigator properties affected by the --bot-noise-seed flag? A: Navigator properties are deterministic values (core count, memory, platform) that do not involve noise. They come directly from the profile. The noise seed affects rendering outputs (canvas, WebGL, audio), not hardware identity properties.

Summary

Navigator properties form the foundation layer of browser fingerprinting. They are universally accessible, require no permissions, and provide significant identifying information when combined. BotBrowser controls all navigator properties at the engine level through its profile system, ensuring internal consistency across the user agent, platform, hardware, locale, and client hint APIs. Combined with auto-detection for timezone, locale, and language settings, BotBrowser produces a coherent browser identity that matches a real device configuration.

For related topics, see What is Browser Fingerprinting, CPU Core Count Control, Screen and Window Protection, and Timezone, Locale, and Language.

#navigator#fingerprinting#browser-identity#privacy