Skip to content
Fingerprinting

The heap limit as a RAM tell: what jsHeapSizeLimit says that deviceMemory does not

navigator.deviceMemory stops at 8. The JavaScript heap limit keeps going a little further, and it has to agree with whatever memory a session claims.

Pim
Pim· Clearcote Research
6 min read

Key takeaways

  • performance.memory.jsHeapSizeLimit is a non-standard Chromium value that V8 derives from the machine's physical memory; it grows with RAM and stops at 4,395,630,592 bytes on machines with about 8 GiB or more.
  • Measured on Chrome 153 and 156: 4,127,195,136 with 7.5 GB of usable RAM, and 4,395,630,592 on 16 GB and 32 GB machines; about 7.8 GiB usable, typical for a machine sold as 8 GB, gives 4,303,880,192.
  • navigator.deviceMemory rounds and caps at 8, so the heap limit carries extra detail in exactly the range where most desktops sit, and a deployed challenge widget reads it.

Two memory values, two resolutions

A page has two ways to learn about the machine's memory in Chromium. navigator.deviceMemory is the standard one. It is deliberately coarse: the value is rounded to a power of two and capped at 8, so a 12 GB laptop, a 16 GB desktop and a 64 GB workstation all report 8.

performance.memory is the older, non-standard one, still present in Chromium-based browsers. Its usedJSHeapSize and totalJSHeapSize describe the page's own usage and change all the time. Its jsHeapSizeLimit does not: it is the maximum size of the JavaScript heap, a constant for a given browser on a given machine.

That constant is not chosen by the page or the browser's settings. V8 computes it at startup from the physical memory the operating system reports.

How V8 sizes the heap

V8 gives the old generation a share of physical memory, so a machine with less RAM gets a smaller heap, and caps the result so that large machines do not reserve absurd amounts. On 64-bit desktop Chrome the measurements land on a small set of values:

  • 7.5 GB of usable RAM: 4,127,195,136 bytes.
  • About 7.8 GiB usable: 4,303,880,192 bytes. This is typical of a machine sold as 8 GB: firmware and integrated graphics reserve part of the memory, so the operating system reports a little under 8 GiB, and the limit lands just below the cap.
  • 16 GB and 32 GB: 4,395,630,592 bytes, the cap. Anything above about 8 GiB reports the same value.

The cap and the step below it are where most desktop and laptop users are. That makes the value worth reading even though it carries only a few bits.

What it adds to deviceMemory

Read together, the two values constrain each other. A session that reports deviceMemory 4 should have a heap limit from the lower range, not the cap. A session that reports 8 should have one of the two top values. A heap limit at the cap with deviceMemory 2 describes a machine that does not exist.

The heap limit also separates machines that deviceMemory lumps together: an 8 GB laptop and a 16 GB desktop both say 8, but only one of them reports the cap. And because the value is fixed per machine, it adds to a fingerprint's stability across sessions.

A deployed challenge widget reads performance.memory inside a probe that also builds isolated iframes and checks security policies, and sends the limit to its server encoded in base 23. The encoding is cosmetic; the value is the one above.

Changing one without the other

Spoofing tools commonly override navigator.deviceMemory and leave performance.memory alone. On a 32 GB server presenting a 4 GB laptop, that leaves the heap limit at the cap: one value says small machine, the other says large one. Overriding jsHeapSizeLimit in JavaScript has the usual problems of any page-level patch, covered in timing native functions, and it has to happen in every realm, workers included.

Choosing the right value is its own problem. The cap is right for 8 GB and above only if the persona is a machine whose usable memory reaches it; an "8 GB" persona that reports the cap claims more usable memory than most 8 GB machines have. Clearcote's engine derives the limit from the persona's memory the way V8 does on real hardware, including the reserved slice, which is why its 8 GB personas report 4,303,880,192.

The through-line

The heap limit is a small example of the rule in anatomy of a browser fingerprint: every value that depends on the hardware has to come from the same imagined machine. Memory shows up in deviceMemory, in the heap limit, in the storage quota and in how many workers a page can run in parallel. A session that changes the first and forgets the rest has not changed its memory, only one report of it. Coherence over camouflage makes the general case.

#fingerprinting#coherence#chromium#reference

Clearcote puts this into practice

An open-source Chromium with fingerprint control compiled into the engine. A drop-in for Playwright & Puppeteer.

  • 222engine patches
  • 34,478lines added
  • 330Chromium files changed
  • 354checks per build

Engine numbers are for the Pro build; the free open build is a smaller, public patch set.

Free for one browser with GitHub. No card.