What the hardware APIs report
A handful of properties summarise the device:
navigator.hardwareConcurrency- the number of logical cores, used by sites to size worker pools. Real consumer devices cluster at 4, 8, 10, 12, 16. A value of 1 or 2 is unusual on modern hardware; 32, 64, or 96 indicates a server.navigator.deviceMemory- approximate RAM, deliberately bucketed for privacy to one of 0.25, 0.5, 1, 2, 4, or 8 (capped at 8). A phone reporting 8 with a desktop screen, or a desktop reporting 0.5, is suspicious.- The
screenobject -width/height,availWidth/availHeight(minus OS taskbars),colorDepth(almost always 24), anddevicePixelRatio(1 on standard displays, 2 on Retina, 1.5/1.25 on scaled Windows).
None is unique, but together with the GPU and platform they describe a class of device, and that class has to be internally consistent.
The cloud-server signature
The most actionable hardware tell is the under- or over-provisioned cloud instance. Scrapers run on VPS and container hosts whose hardwareConcurrency reflects the VM size - often 1, 2, or alternatively 32/64 on big boxes - and whose headless browser reports a default or zero-size screen. Combinations that no real user produces:
hardwareConcurrency: 1with a desktop Chrome UA (real desktops are multi-core).hardwareConcurrency: 64with an Android UA (no phone has 64 cores).screen.width: 800, height: 600or0x0with a flagship-phone UA.deviceMemory: 8(the cap) on every request from a fleet, while real traffic spreads across buckets.
These are cheap server-side checks that catch entire scraping fleets sharing one VM profile.
Coherence and stability
Spoofing the values is easy; spoofing them coherently is the hard part. The core count, RAM bucket, GPU tier (from WebGL/WebGPU), screen resolution, and device pixel ratio must all describe one believable machine that also matches the User-Agent and Client Hints. A request claiming an iPhone should report the core count and screen metrics of that specific iPhone, not generic desktop values.
Two further traps: the values must be stable within a session (real hardware does not change cores mid-visit), and they must match what timing-based probes infer - a timing attack can estimate the true core count by saturating workers, catching a browser that claims 8 cores but schedules like 2. This is why hardware spoofing works best as part of a complete device profile rather than field-by-field edits.
