getClientRects() and getBoundingClientRect() expose sub-pixel layout differences that fingerprint your device — without ever touching a canvas.
Every element on a web page has a position and size that JavaScript can read down to a fraction of a pixel. Ask a browser for the exact rectangle a heading occupies and it hands back floating-point numbers like 312.234375 — precision no human eye could ever use, produced by font hinting, sub-pixel anti-aliasing, and platform-specific text layout. Those numbers differ slightly from device to device, and a script that measures enough of them can turn ordinary page layout into a tracking signal, with no canvas element and no pixel readback in sight.
Key Takeaways
getClientRects()andgetBoundingClientRect()returnDOMRectvalues with sub-pixel (floating-point) precision — precision that varies with font rendering, DPI scaling, and the OS text-layout engine.- Measuring the rectangles of rendered text is a layout-based fingerprint: it needs no
<canvas>element, no pixel readback, and no permission prompt, so it slips past defenses aimed specifically at canvas. - It correlates with — but isn't identical to — canvas fingerprinting, since both stem from font and rendering-pipeline differences; combining the two raises confidence beyond either alone.
- Anti-detect browsers such as GoLogin and Dolphin{anty} ship dedicated "Rects" spoofing toggles, a tacit admission from the anti-detect industry that this signal is checked in the wild.
- BrowserInsight's fingerprint check surfaces the layout and canvas signals your browser currently exposes side by side.
What getClientRects() actually returns
getClientRects() and its simpler cousin getBoundingClientRect() are ordinary layout APIs, standardized in the CSSOM View Module. They exist so that JavaScript can answer everyday questions like "is this element currently visible in the viewport?" or "where exactly does this line of wrapped text end?" Nothing about them looks like a tracking tool.
Call getBoundingClientRect() on any element and you get a single DOMRect — top, left, width, height, and the derived edges — describing its bounding box relative to the viewport. Call getClientRects() instead and you get a full list of rectangles, one per line box, which matters for inline content: a sentence that wraps across three lines returns three separate rects, each with its own coordinates. Range.getClientRects() does the same for an arbitrary text selection, letting a script measure a specific run of characters rather than a whole element.
The values that come back are not integers. They're double-precision floats, because the browser's layout engine positions text using sub-pixel arithmetic even though your screen ultimately rounds everything to physical pixels. That extra precision — the fractional remainder that never gets rendered exactly the same way twice across devices — is the entire basis of this fingerprint.
Why the numbers vary by device
If two browsers render the same HTML with the same CSS, why would the rectangles differ at all? Several layers between "here is some text" and "here are its final pixels" each introduce small, reproducible variation:
- Font hinting and shaping. The OS text-shaping engine — DirectWrite on Windows, Core Text on macOS, FreeType/HarfBuzz on Linux — decides exactly how glyph outlines snap to the pixel grid. Different hinting rules produce different advance widths for the same string in the same font.
- Device pixel ratio. A HiDPI display (
window.devicePixelRatioof 2 or 3) rounds sub-pixel layout to a finer physical grid than a 1x display, shifting the fractional part of every coordinate. See MDN'sdevicePixelRatioreference for how the browser exposes this. - Font availability and fallback. If the requested font isn't installed, the browser substitutes a fallback with different metrics — the same mechanism font fingerprinting relies on, but here the signal is the raw rectangle geometry rather than a simple presence/absence bit.
- Browser engine and version. Chromium (Blink), Firefox (Gecko), and Safari (WebKit) each implement their own text-layout and line-breaking logic, so identical markup can legitimately measure a few hundredths of a pixel apart between engines, and sometimes between versions of the same engine.
- Zoom level and OS text-scaling. Page zoom and OS-level accessibility scaling (Windows "make text bigger", macOS display scaling) both feed into the same layout pipeline and shift the sub-pixel remainder.
None of these are configuration options anyone deliberately sets for privacy. They're side effects of normal rendering, which is exactly why the resulting rectangles are stable for a given device and session, yet vary from one device to the next.
Client rects vs canvas fingerprinting
The two techniques are close cousins — both exploit rendering-pipeline differences rooted in fonts, GPUs, and OS text engines — but they differ in what they touch and how easy they are to catch.
| Property | ClientRects fingerprinting | Canvas fingerprinting |
|---|---|---|
| API surface | Plain DOM layout (getClientRects, getBoundingClientRect) | <canvas> + 2D context (toDataURL, getImageData) |
| Requires pixel readback | No | Yes |
| Visible to canvas-specific blockers | No | Yes — extensions hook these exact calls |
| Signal source | Sub-pixel text/element layout geometry | Rasterized pixel colors |
| Typical entropy | Moderate on its own; strong combined with fonts | High on its own |
| Detectable as "an off-screen canvas was read" | N/A — no canvas involved | Yes, via API-call monitoring |
The practical consequence is what makes rect fingerprinting attractive to trackers and anti-detect vendors alike: any defense that specifically watches for canvas API calls — a canvas blocker extension, a farbling layer, a monitoring script like the one in our canvas guide — has nothing to intercept here, because no canvas is ever created. A script can quietly measure the layout of ordinary text and headings already on the page and derive a comparable signal.
How the measurement is actually done
A typical implementation renders a handful of styled text elements — often mixing several fonts, font sizes, and CSS properties like letter-spacing known to trigger diverging sub-pixel rounding — then reads back their rectangles:
// Illustrative sketch of a rects-based measurement
function measureRects() {
const probe = document.createElement('div');
probe.style.cssText = 'position:absolute; visibility:hidden; font-size:14px; letter-spacing:0.3px;';
probe.style.fontFamily = 'Arial, sans-serif';
probe.textContent = 'BrowserInsight fingerprint probe 0123456789';
document.body.appendChild(probe);
const rects = probe.getClientRects();
const values = Array.from(rects).flatMap(r => [r.width, r.height, r.left, r.top]);
document.body.removeChild(probe);
return values; // fed into a hash alongside other signals
}
The element never needs to be visible — visibility: hidden still participates in layout, so the rectangles it produces are real. Multiple probe strings, fonts, and CSS combinations are typically measured and hashed together, the same "measure many small signals, combine them" approach used across fingerprinting techniques generally — see our browser fingerprinting guide for how signals like this stack into an overall identifier.
Where this shows up in practice
This technique doesn't get much mainstream press compared to canvas or WebGL, but it's a known quantity in two specific corners of the ecosystem:
- Fingerprinting/anti-fraud vendors include rect-based measurements as one input among many, precisely because it's cheap to compute and orthogonal to the defenses most privacy tools focus on.
- Anti-detect browsers — tools built to present a different, consistent fingerprint profile per browser instance — treat it seriously enough to expose dedicated controls. GoLogin and Dolphin{anty} both ship settings specifically for spoofing or normalizing "Rects" output, alongside their canvas and WebGL toggles. The existence of a purpose-built toggle is a reasonable proxy for "this is actually checked" — vendors don't build spoofing controls for signals nobody reads.
How to reduce your exposure
There's no dedicated "disable getClientRects" switch in mainstream browsers, because the API is load-bearing for ordinary layout — text selection, scroll-into-view, tooltips, and virtually every JavaScript UI framework depend on it. The available mitigations mirror the ones that work against canvas fingerprinting, because the two share a root cause:
- Favor uniformity over customization. Tor Browser standardizes font rendering and disables several of the finer-grained layout APIs' precision, shrinking the population you can be distinguished within — the same philosophy it applies to canvas.
- Limit installed fonts and extensions. Every extra font you install adds another way for fallback substitution to shift a rectangle's dimensions. A stock font set on a stock OS install is harder to single out than a heavily customized one.
- Use resistFingerprinting-style protections. Firefox's
privacy.resistFingerprintingrounds and standardizes several rendering-related values, reducing the sub-pixel variance this technique depends on, in the same way it constrains canvas and WebGL output. - Check what you expose. Run BrowserInsight's fingerprint check to see your canvas, WebGL, and other rendering signals in one place, then compare the result across a normal browser and a privacy-hardened one to see which settings actually move the needle.
As with canvas, the anti-fingerprinting paradox applies: a rare, hand-rolled rects spoof that overshoots — returning suspiciously round numbers, or values with zero sub-pixel variance across every probe — can be more distinctive than the raw signal it was meant to hide.
Frequently Asked Questions
Is ClientRects fingerprinting the same as canvas fingerprinting?
No, though they're closely related. Canvas fingerprinting reads back rasterized pixels from an off-screen <canvas>; ClientRects fingerprinting reads the sub-pixel layout geometry of ordinary DOM elements or text, with no canvas involved at all. Both trace back to font rendering and platform text-layout differences, so they tend to correlate, but a defense built only for canvas does nothing to stop this technique.
Does a canvas blocker extension stop this?
Not by itself. Canvas blockers hook canvas-specific APIs like toDataURL() and getImageData(). getClientRects() and getBoundingClientRect() are unrelated DOM layout methods, so a blocker scoped to canvas has no reason to intercept them.
Can this technique identify me on its own?
Rarely with high confidence by itself — many devices share similar rendering pipelines and produce comparable rectangles. It's most useful to trackers as one signal combined with fonts, canvas, WebGL, and other passive attributes, the same way each individual signal in a full fingerprint contributes partial entropy rather than a complete identity.
Why do anti-detect browsers specifically mention "Rects" settings?
Because the technique is real and checked by some fingerprinting and anti-fraud vendors, tools built to present a consistent spoofed identity need to normalize or randomize it just like they do for canvas and WebGL — otherwise the rects signal would leak the real underlying device through an otherwise well-spoofed profile.
Conclusion
ClientRects fingerprinting is a reminder that "fingerprinting defense" can't mean "block canvas and call it done." Any API precise enough to reflect font rendering, DPI scaling, or platform text layout is precise enough to fingerprint — and ordinary DOM layout methods that every web app already relies on qualify. Understanding the mechanism is what lets you evaluate whether a given privacy tool actually covers it, rather than assuming canvas protection is the whole story.
Recommended Reading:


