What it measures
Each call records the integer offsetWidth of a fixed test string rendered in a hidden off-screen container across a small set of CSS generic family keywords, plus a minimum-font-size policy probe.
The generic-family measurements capture which actual font the browser substitutes for each CSS keyword. On the same machine, Safari resolves sans-serif to Helvetica, Chrome on macOS resolves it to Arial, Firefox on Linux to DejaVu Sans. The minimum-font-size probe catches users with accessibility minimum font size settings configured; when enforced, a small span is clamped to the floor and its rendered width balloons.
Complementary to the fonts signal
The fonts signal probes a curated detect list to answer 'which named fonts are installed?'. Font preferences captures what the OS and browser have chosen as defaults for each CSS generic family. Distinct entropy axis: fonts answers 'which named fonts exist?' while font preferences answers 'what does your sans-serif render as?'
Width only. Height is dropped per the design constraint. Sub-pixel glyph-positioning jitter makes offsetHeight unstable across calls on the same engine; offsetWidth is rock solid because it's an integer sum of glyph advance widths.
Confidence rules
| Confidence | Trigger |
|---|---|
| normal | document and document.body available; all measurements collected |
| absent | document is undefined (non-browser runtime) or document.body is null |
Things worth knowing
- Apple-only system family keywords return the baseline width on non-Apple browsers (the family doesn't resolve to anything). The differential between Apple and non-Apple values is the entropy point.
- Brave Standard Shields farbles widths per-eTLD+1, but the farbling is deterministic per origin, so the hash stays stable across calls on the same site.
- Firefox resistFingerprinting returns a fixed set of widths consistent across all Firefox-resist installs. Entropy collapses but the signal stays normal.
- Dynamic Type on iOS Safari: the system body width shifts when the user changes their iOS Dynamic Type accessibility setting. Real entropy, but it means the hash changes after a user adjusts accessibility — an unavoidable trade-off.
- Hidden off-screen container is removed in a finally block. No DOM leak even on exceptions.
- The exact families probed, the test string, the font sizes used, and the per-call measurement count are deliberately not published. Treat the result shape and confidence as the stable interface.
Last reviewed 2026-06-04

