How ClientRects Enables Powerful Browser Fingerprinting

2023-08-17

Browser fingerprinting is a method websites can use to identify and track users, even when they are browsing in private or incognito mode. One technique involves using the JavaScript properties clientWidth and clientHeight to build a fingerprint. In this post, we’ll explore what clientRects are and how they enable browser fingerprinting.

What are Client Rectangles?

The clientRects property returns a collection of ClientRect objects for each CSS box associated with a DOM element. A ClientRect represents a rectangle that provides information about the size and position of an element relative to the viewport.

Specifically, each ClientRect contains read-only properties such as width, height, top, left, bottom and right. These indicate the width, height and position of the element.

For example:

const box = document.querySelector('.box'); 

const rect = box.getBoundingClientRect();

console.log(rect.width); // 300
console.log(rect.height); // 200 
console.log(rect.top); // 100
console.log(rect.left); // 200

This provides precise geometry information about the element relative to the viewport.

Fingerprinting

The clientRect values offer a high level of entropy, meaning they provide a large range of possible values that can uniquely identify a browser and device. Even the slightest differences in browser version, viewport size, font options and other factors will cause clientRect values to vary.

For example, enabling a browser plugin or zooming in will impact the rectangle values. Different browser brands and versions calculate rectangles differently too. This makes clientRects ideal for fingerprinting. Hundreds of rectangle values can be gathered from all page elements to build a unique fingerprint.

Using JavaScript to Collect ClientRect Data

Javascript provides easy access to element rectangles through the getClientRects() and getBoundingClientRect() methods.

For example, this collects an array of rectangles for all child elements:

const container = document.querySelector('.container');

const rects = [];

for (let el of container.children) {
  rects.push(el.getBoundingClientRect()); 
}

// rects array now contains client rects for each child 
element

Alternatively, getClientRects() provides rectangles for every fragment of content:

const paras = document.querySelectorAll('p');

for (let para of paras) {
  const rects = para.getClientRects();

  // rects contains detailed rectangles for each line, 
word and letter
} 

These methods allow efficiently gathering hundreds of unique rectangle values for fingerprinting.

Combining Rectangles with Other Properties

For enhanced fingerprinting, clientRect values can be combined with other browser properties.

Some examples:

  • Screen size and zoom level
  • Browser width and height
  • Installed fonts and styles
  • Timezone and locale
  • Canvas and WebGL fingerprinting

Combining these sources produces an extensive fingerprint with enough entropy to individually identify users.

For example:

const fingerprint = {
  rects: getAllClientRects(),
  screen: {
    width: screen.width,
    height: screen.height,
    zoom: detectZoomLevel()
  },
  fonts: getInstalledFonts(),
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
  // etc
};

This fingerprint object provides a unique identity of the browser, device and user.

Fingerprinting Concerns

While sometimes used for benign purposes, browser fingerprinting raises privacy issues.

Key concerns:

  • Fingerprinting undermines anonymity. Users are tracked without consent across websites.
  • There is no way to opt-out. Users cannot easily modify their fingerprint.
  • Fingerprints may reveal sensitive information about users.

Some ways fingerprints can be abused:

  • Targeting vulnerable demographics
  • Discriminatory advertising
  • Real-world identification
  • Cross-site tracking for surveillance Responsible use of fingerprinting is important for protecting user privacy.

Fingerprinting Defenses

There are ways for users to defend against fingerprinting:

  • Use the Tor browser, which blocks fingerprinting.
  • Enable browser extensions that spoof or block APIs.
  • Disable JavaScript to prevent fingerprinting code.
  • Use a VPN to hide IP address and location.

However, fingerprinting scripts are often sophisticated and difficult to avoid completely.

Ethical Considerations

Web developers should carefully weigh whether fingerprinting is justified. Consider:

  • Transparency: Disclose use of fingerprinting. Seek opt-in consent.
  • Data minimization: Only collect necessary data.
  • Security: Store fingerprints safely, anonymized where possible.
  • Accountability: Provide ways to review and delete data.

Following privacy best practices helps mitigate fingerprinting risks.

Conclusion

ClientRects offer detailed geometry data that enables precise browser fingerprinting when combined with other properties. While sometimes useful, fingerprinting has serious privacy implications that developers must consider. With care, fingerprints can be collected and used in an ethical way that respects user consent and anonymity.