What it measures
performance.memory.jsHeapSizeLimit is the V8 heap ceiling Chromium chose for the current tab at startup. Typical observed values: low-RAM Android (1 to 2 GiB device RAM) reports 256 to 512 MiB; mid-range desktop / Chromebook (4 to 8 GiB RAM) reports ~2 GiB; high-RAM desktop (16+ GiB RAM) reports ~4 GiB. Chromium caps the limit at 4 GiB on 64-bit regardless of physical RAM.
Chromium incognito mode reduces the cap below the normal-mode value, the same observation the existing incognito-detection layer uses via the flag_js_heap_limit_low flag (which fires when limit < 3 GiB).
Why engine-bound
Only Chromium exposes performance.memory. Safari and Firefox return undefined. Brave inherits Chromium and exposes the same value without farbling.
Including this in the hardware signal set would shatter cross-browser stability. Chrome on a Mac would give a value while Safari on the same Mac would give absent. Classifying it engine-bound keeps hardwareFingerprint clean.
Confidence rules
| Confidence | Trigger |
|---|---|
| normal | performance.memory.jsHeapSizeLimit is a positive finite number |
| absent | performance.memory missing (Safari / Firefox) |
| absent | jsHeapSizeLimit is undefined, null, non-number, or ≤ 0 |
Things worth knowing
- The existing flag_js_heap_limit_low incognito-detection flag reads the same API independently. Adding this signal does not change that flag's logic. Both coexist without interference.
- Brave Standard Shields does NOT farble performance.memory. Values match upstream Chromium.
- performance.memory is non-standard and has been on Chromium's 'consider removing' list for years. If removed, this signal becomes permanent absent across all browsers, a graceful failure mode.
- FingerprintJS does not collect jsHeapSizeLimit as a hash-contributing signal (only for confidence scoring). Thumbmark collects it inside its hardware component. We sit in between, collecting it as an engine-bound standalone signal in 1.7.0.
Last reviewed 2026-06-04

