All articles Advanced signals

ClientRects and DOMRect Fingerprinting: Sub-Pixel Layout Signals

Two browsers can render the same paragraph and disagree about where every letter sits by fractions of a pixel. Those disagreements are measurable through the DOMRect APIs, and they form one of the quietest but most reliable browser signals available.

How the signal is collected

The technique relies on Element.getClientRects() and Element.getBoundingClientRect(). A script injects text, often a string mixing Latin, emoji, and complex scripts, into a hidden element and reads back the bounding rectangles. The returned coordinates carry sub-pixel precision, so the exact width, height, x, and y values reflect how the browser shaped and rasterized the glyphs.

Because layout depends on the font stack, the text-shaping engine, the OS, and the device pixel ratio, the resulting geometry varies across environments. Measure enough characters and the vector of rectangles becomes a fingerprint.

What actually drives the variation

  • Font availability and fallback: if a requested font is missing, the browser substitutes another, shifting every rectangle. The substitution order is platform-specific.
  • Text-shaping engine: HarfBuzz on Linux, DirectWrite on Windows, and Core Text on macOS handle kerning and ligatures differently.
  • Sub-pixel rounding: browsers round fractional layout coordinates according to their own rules, and the rounding differs by engine version.
  • Zoom and device pixel ratio: a visitor at 110% zoom produces a distinct set of rectangles from one at 100%.

The signal overlaps with font fingerprinting but is not identical. Font detection asks which fonts exist; ClientRects asks exactly how this engine laid out these glyphs, which captures rasterization nuances that a font list never does.

Strengths and limits

ClientRects is attractive because it runs fast, needs no special permissions, and is hard to spoof consistently. An anti-detect browser can jitter a single measurement, but Prynt reads many rectangles and checks that they agree with each other and with the separately measured fonts, device pixel ratio, and platform. Random per-rect noise breaks that internal consistency and becomes its own detection signal.

The main limitation is that the raw values are noisy, so a naive approach that hashes them directly produces unstable IDs. The fix is to quantize: round measurements into buckets tuned so that the same device lands in the same bucket across reloads while different devices separate. Prynt handles this quantization server-side, which keeps the client script lightweight and lets us tune thresholds without shipping new code to every visitor.

Where it fits in a fingerprint

On its own, ClientRects contributes moderate entropy. Its real value is as a corroborating signal. When the layout geometry agrees with the canvas output, the font list, and the reported platform, confidence in the overall visitorId rises. When a headless browser reports a desktop user agent but produces layout metrics typical of a Linux server with no display fonts, the contradiction surfaces.

Prynt folds ClientRects into the same multi-signal model that powers its server-side bot detection, where layout anomalies join network and behavioral signals to separate real browsers from automation. Because correlation happens in our cloud, a client that tampers with one rectangle cannot quietly rewrite the verdict.

Zoom, DPI, and stability tuning

The biggest practical risk with ClientRects is over-sensitivity. Because the API returns sub-pixel coordinates, small legitimate changes such as a browser update that tweaks its rounding, or a user nudging zoom from 100% to 110%, can shift every measurement. A system that hashes raw values too tightly will churn out a new identifier for the same person on every visit. The remedy is careful bucketing calibrated against real traffic, so the quantization tolerance absorbs benign drift while still separating genuinely different devices. Prynt tunes these thresholds continuously from aggregate data rather than baking them into the client script, which means the same visitor stays stable through minor zoom and version changes while an anti-detect browser injecting per-load noise still stands out as unstable.

Implementation notes for teams

  • Measure a diverse character set, including emoji and non-Latin scripts, to maximize cross-platform variation.
  • Quantize before hashing, and validate that the same device stays stable across reloads and minor zoom changes.
  • Cross-check rectangles against fonts, device pixel ratio, and platform. Internal disagreement is a tamper signal.
  • Keep the hidden element out of the accessibility tree and remove it after measurement to avoid layout side effects.

ClientRects fingerprinting is a reminder that entropy hides in places most engineers never look. The exact pixels where a browser draws text are a small, durable, hard-to-fake tell about the device behind the screen.

Try Prynt free and see layout signals resolve into a stable identity in the live playground.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading