| Component name | cpu_architecture |
|---|---|
| In the visitorId | yes |
| structuredId group | device (screen, memory, CPU) |
| Hashing | plain value; a digest only when longer than 128 characters or not printable ASCII |
| Excluded under | no browser class |
| Inner timeout | 1000 ms |
| Added in | signalsVersion 2 |
When a computer works out “infinity minus infinity”, the answer is a special “not a number” value. Intel and AMD processors write that value with one bit set, ARM processors (phones, Apple Silicon Macs) without. WhiskerJS does this one calculation and reads the bit. It tells the two big processor families apart even when the browser hides them in its user agent.
What it reads
A one-element Float32Array shares its buffer with a Uint8Array. WhiskerJS stores Infinity, then Infinity - Infinity in the float, and reports byte 3 of the buffer (the high byte on little-endian machines) as a plain number.
How the technique works
// The idea, in a few lines of browser JavaScript:
const f = new Float32Array(1);
const bytes = new Uint8Array(f.buffer);
f[0] = Infinity;
f[0] = f[0] - f[0]; // NaN, with a bit pattern chosen by the CPU
bytes[3]; // 255 on x86, 127 on ARM
IEEE 754 leaves the sign of a generated NaN to the hardware. x86 produces the “default NaN” with the sign bit set (top byte 0xFF), while ARM produces it without (top byte 0x7F). The calculation is pure: no API, no permission, no timing.
Why it helps
It is a robust CPU family hint that does not depend on what the browser chooses to say about itself. Your server can compare it with the platform, the user agent header and, in Chromium, the arch field of ua_client_hints. It is in the device group.
Stability
Very stable: it changes only when the code runs on a different CPU family, for example a new device, or a browser running under an emulation layer that translates x86 code to ARM or the other way round.
Browser support and what blocks it
ok in all browsers with typed arrays, which is every current browser, and not in the exclusion table. It is unavailable / no_api only where Float32Array or Uint8Array is missing. The container test runs used for these pages, on an ARM host, reported 127 in headless Chromium, Firefox and WebKit.
Privacy
Two possible values in practice, about the processor family only. No permission, no prompt, no request.
How WhiskerJS handles noise and failures
| Status | ruleId | When |
|---|---|---|
ok |
none | 255 or 127 |
unavailable |
no_api |
no typed arrays |
blocked |
security_error, threw |
the calculation threw (not expected) |
excluded |
caller_excluded |
your exclude list |
timed_out |
timeout, aborted |
1000 ms inner timeout, budget, abort |
Example value
"cpu_architecture": { "status": "ok", "value": "127", "hashed": false }
Questions and answers
How can a calculation reveal the processor?
Infinity minus Infinity gives NaN, and the processor decides the NaN's bit pattern. x86 chips set the sign bit and ARM chips do not, so the top byte of the 32-bit float is 255 on x86 and 127 on ARM.
Can it tell an Apple Silicon Mac from an Intel Mac?
It reports the CPU family the JavaScript engine runs on, so an ARM-based Mac and an x86-based Mac give different values, even though both may send similar user agents.