Scalebrowser

hardwareConcurrency and deviceMemory sit on a grid

What navigator.hardwareConcurrency and deviceMemory report, the power of two grid Chromium puts memory on, and which comparisons a changed value fails.

Davide Valli · Founder, Scalebrowser

Published Nov 11, 2026 · 6 min read

Short answer

navigator.hardwareConcurrency reports the number of logical processors, and navigator.deviceMemory the RAM in gigabytes, rounded to a power of two and clamped to 2 to 32 on desktop Chromium 154. Both describe the machine, so they have to agree between the page, its workers and the Device-Memory request header, and stay the same from one start to the next. A value that moves is a tell: an open Camoufox issue reports hardwareConcurrency drifting from 16 to 12 to 14 across restarts of one profile.
2 to 32, RAM in gigabytes, beside a processor chip with pins

Two numbers in every browser fingerprint describe the computer rather than the browser: how many threads it can run at once and roughly how much memory it has. They look harmless, and that is why automation tools often set them to whatever looks common. The trouble is that neither number is free. Each one sits on a grid that Chromium defines, appears in more than one place, and is expected to stay put for as long as the machine does.

What is navigator.hardwareConcurrency?

navigator.hardwareConcurrency is a read-only property that returns the number of logical processors available to run threads on the computer. MDN's reference page defines the range as "between 1 and the number of logical processors potentially available to the user agent", and notes that a browser may report fewer to reflect how many workers can run at once. Its companion is navigator.deviceMemory, which the W3C Device Memory specification, a Working Draft dated 30 March 2026, defines as the device's RAM in GiB, "rounded to a single significant bit" to reduce fingerprinting.

PropertyWhat it reportsWhere a page reads itGrid
hardwareConcurrencylogical processorspage and every workerwhole numbers from 1 upward
deviceMemoryRAM in GiB, approximatedpage, every worker, the Device-Memory request headerpowers of two within browser limits

Reading both takes two lines in the page and the same two lines in a worker:

js
const page = [navigator.hardwareConcurrency, navigator.deviceMemory]
const src = "postMessage([navigator.hardwareConcurrency, navigator.deviceMemory])"
const worker = new Worker(URL.createObjectURL(new Blob([src], { type: "text/javascript" })))
worker.onmessage = (event) => console.log(page, event.data)

A real browser prints the same pair twice. deviceMemory answers only in a secure context, so the test page has to be served over HTTPS.

What grid does navigator.deviceMemory sit on?

navigator.deviceMemory sits on powers of two between 2 and 32 GB on desktop Chromium, and between 1 and 8 GB on Android. The Chromium source, read on 27 September 2026, picks whichever neighbouring power of two is closer to the physical memory and then clamps the result to those limits, with a comment pointing to crbug 454354290 "for updated limits". Before that change the desktop limits were 0.25 and 8 GB. A rule written against the old ceiling would call a real 16 or 32 impossible, and a persona pinned to a value between two grid points, such as 6, exists on no machine at all.

The same number leaves the browser three times: in JavaScript, in the Device-Memory header of the navigation, and in the same header on every subresource. On 14 September 2026 we read all three on one Windows machine with a bench that serves a page over HTTPS and records the request headers it receives.

BrowserNavigation headerSubresource headernavigator.deviceMemory
Chrome for Testing 154.0.8037.9323232
branded Chrome 153.0.8010.37323232
our 154 engine, no persona323232
our 154 engine, persona with 8 GB888
Source: Scalebrowser header bench, one Windows host, 2 captures per browser, 14 September 2026

Both header spellings, Sec-CH-Device-Memory and Device-Memory, carried the same value in all eight captures.

Which hardware values must agree with each other?

Four comparisons decide whether hardwareConcurrency and deviceMemory describe one machine, and each of them needs only values the browser hands out anyway:

  • Page against worker. Both properties exist on the worker's navigator too, and a real browser answers there exactly as in the page.
  • JavaScript against the header. Once a site asks for the hint with Accept-CH, the Device-Memory header and navigator.deviceMemory are one number in a real browser, on the navigation and on every subresource.
  • Cores against memory. The pair is compared with the devices a site has already seen, and a combination few real machines have narrows the crowd the browser hides in.
  • The pair against the rest of the machine. The graphics card, the screen and the platform in the user agent all describe the same computer and are read in the same visit.

These are the hardware a page can query and the comparisons a checker runs on it, and the second one caught our own build. On 12 September 2026 our 151 engine with a persona sent 32 in the memory header and 8 to JavaScript in the same page load, while the same engine without a persona sent 32 in both. We fixed it on 13 September, and the table above is the reading on the 154 engine one day later. Since 28 September 2026 a persona carries neither value, and the engine answers both itself.

Can a page see the Device-Memory header?

No, a page cannot read the headers of its own requests; only the server that receives them can. That makes the header comparison invisible to every fingerprint test page that runs in JavaScript alone, and fully visible to the site's own backend. A test page that shows green says nothing about this pair.

Why does a changing hardwareConcurrency look suspicious?

A changing hardwareConcurrency looks suspicious because a computer does not gain or lose processor threads between two starts of a browser. Camoufox issue 442, opened on 5 January 2026 and still open on 27 September 2026, reports that "the CPU core count reported by navigator.hardwareConcurrency drifts randomly (e.g., 16 -> 12 -> 14)" when a profile is restarted, alongside noise seeds that regenerate and GPU renderer strings that switch. A site that recognises the profile by its cookie then sees one returning visitor on three different computers in a row. Each value alone is ordinary; the sequence is what no real user produces.

Scalebrowser does not assert either value. Since 28 September 2026 a profile takes the processor count and the memory from the machine it runs on, rounded the way Chromium rounds them, at creation and at every start, so the pair is the same at every start and a page that checks it against the machine finds the machine. The graphics card and the screen are taken from the host in the same way. Another set of values that sit on a grid is covered in navigator.connection.

How can you check the values your browser reports?

You can check the values with four comparisons, each of which a detector can run too:

  1. Read both properties in the page and in a worker with the snippet above, and expect the same pair twice.
  2. Log the Device-Memory header on your own server for a page you control, after asking for it with Accept-CH: Device-Memory, and compare it with what JavaScript reported in the same load.
  3. Restart the profile and read again, three or four times; any change is the drift a returning visitor should not show.
  4. Compare with the machine: the logical processors in the operating system's task manager, and the installed memory rounded to the nearest power of two between 2 and 32.

If all four agree, these two values describe one plausible computer. The page on testing your setup lists further ways to see what a site reads, including a check page that works without an account.

Real browser profiles for your AI agent, on your PC.

Each profile keeps its own identity, logins and proxy. Your agent drives it over MCP and signs in without seeing a password.

Download free for Windows

Free plan with 3 profiles · No credit card · Runs on your PC

Written by

Davide Valli

Founder, Scalebrowser

Builds Scalebrowser, browser automation for the agentic era that runs on your own machine. Measures every change a web page could observe against a real browser before it ships, and writes up the ones that turned out wrong.

All articles by Davide Valli

More in Detection

All 19 articles in Detection