Article by Scrapfly Engineering (July 12, 2026) on a fingerprinting channel lodged in the last bits of a number.

The mechanism. IEEE 754 defines how a double is stored but does not require correct rounding of transcendental functions. Since correct rounding is expensive, each platform ships a libm with its own minimax coefficients, tables, and constants. As a result, Math.tanh(0.8) returns three distinct values depending on glibc, libsystem_m, and UCRT. Linux and macOS diverge on roughly a quarter of inputs, typically by 1 ULP. « A detector needs no math, only a table. » And the inconsistency is immediately exploitable: claiming macOS while returning Linux bits contradicts its own User-Agent.

one tanh call on the right input is a per-OS signature. Claim macOS, return Linux math bits, and you have contradicted your own User-Agent.

**Scrapfly Engineering** — équipe d'ingénierie de **Scrapfly** , scrapfly.dev

The tell is recent and dated. Up to Chrome 147, V8 computed tanh with an embedded fdlibm, identical everywhere. Commit c1486295ae5 replaced it with std::tanh, which reads the host libm, shipped with Chrome 148.

Three surfaces leak. Math.tanh is the only Math.* function affected — V8 embeds and statically links everything else. All seven CSS trigonometric functions leak, with Blink calling the host libm after a degree-based angle reduction that does not share code with Math.sin. And Web Audio touches three libraries within a single graph: Accelerate for the FFT and vector stages, scalar libsystem_m for the compressor's transcendentals. WASM, meanwhile, does not leak the OS — only the architecture.

Four traps make the countermeasure difficult: only some functions leak, so spoofing the others creates a detectable asymmetry; JavaScript and CSS are separate code paths; macOS embeds two math libraries that diverge from each other by 10 to 89% depending on the function, so "reproducing Apple's math" makes no sense until one knows which is called at which site; and ARM and x86 differ on fused multiply-add and NaN propagation.

Noise does not work: it produces a value that matches no real OS, and its non-determinism is itself a signal. The only path is bit-for-bit reproduction — coefficients extracted from the target libm and transcribed in hexadecimal, each fusion written as explicit fma(), compiled with -ffp-contract=off.

The publisher states that its posts are drafted with AI assistance, with the mechanisms, figures, and code remaining its own.