# pixel_ratio

> The ratio of physical to CSS pixels (devicePixelRatio), rounded to three decimals. Reported, but kept out of both ids because page zoom changes it.

Source: https://whiskerjs.com/signals/pixel-ratio/ (last updated 2026-10-26)

**pixel_ratio at a glance (from the library code, signalsVersion 9)**

| Field | Value |
| --- | --- |
| Component name | `pixel_ratio` |
| In the visitorId | no (reported, kept out of both ids) |
| structuredId group | none |
| Hashing | plain value; a digest only when longer than 128 characters or not printable ASCII |
| Excluded under | Firefox resistFingerprinting (firefox_rfp); Tor Browser and Mullvad Browser (rfp_hardened) |
| Inner timeout | 1000 ms |
| Added in | [signalsVersion 1](https://whiskerjs.com/whats-new/) |

> **In plain words:**
>
> Sharp screens pack more physical pixels into each unit a web page uses for layout; the browser reports this as the pixel ratio (for example 2 on many phones and Retina laptops). The same number also changes when you zoom a page. So WhiskerJS reports it for your server to look at, but never lets it change the identifiers.

## What it reads

`window.devicePixelRatio`.

## How the technique works

The number is read once and rounded to three decimals with WhiskerJS’s own rounding (so `1.2500000001` becomes `1.25`). A value that is not a finite positive number gives `unavailable`.

## Why it helps

It reflects the screen density and the operating system’s display scaling (for example 1.25 or 1.5 on Windows laptops), which separates many devices. That is useful context for your server, for example to check that a phone user agent comes with a phone-like ratio. It is not used for matching because it is not stable.

## Stability

Low on desktop: page zoom changes it, and so can moving the window to a monitor with different scaling. On phones it is usually fixed. This is exactly why it is kept out of both ids: neither the visitorId nor the structuredId moves when a user zooms.

On your server, if you compare two results from the same device and only `pixel_ratio` differs, the user most likely zoomed or moved the window. Nothing in the ids changes in that case, which is the intended behaviour.

## Browser support and what blocks it

- Available everywhere: [Chrome](https://whiskerjs.com/browsers/chrome-desktop/), [Firefox](https://whiskerjs.com/browsers/firefox/), [Safari](https://whiskerjs.com/browsers/safari-macos/), [iOS browsers](https://whiskerjs.com/browsers/safari-ios/), [Android browsers](https://whiskerjs.com/browsers/chrome-android/).
- [Firefox resistFingerprinting, Tor Browser and Mullvad Browser](https://whiskerjs.com/browsers/firefox-rfp-and-tor/): `excluded` with ruleId `firefox_rfp` (`rfp_hardened` for Tor and Mullvad), because the value is normalised to 1 there. A pixel ratio of 1 is also one of the traits WhiskerJS needs before it classes a Firefox as `firefox_rfp`.

## Privacy

It describes screen density and the zoom level at that moment. It is not stored and does not join an id.

## How WhiskerJS handles noise and failures

| Status | ruleId | When |
| --- | --- | --- |
| `ok` |   | the ratio, up to three decimals |
| `unavailable` | `no_api` | not a finite positive number |
| `excluded` | `firefox_rfp`, `rfp_hardened` | browser classes `firefox_rfp`, `rfp_hardened` |
| `excluded` | `caller_excluded` | you excluded it |
| `timed_out` | `timeout`, `aborted` | budget or abort |

## Example value

All three headless test browsers in the container reported `1`. Typical values elsewhere: `2`, `3`, `1.25`, `1.5`.

## Questions and answers

### Why is pixel_ratio not in the visitorId?

In desktop browsers, zooming the page in or out changes devicePixelRatio. If it were in the id, a user pressing Ctrl and plus would get a new id.

### Why is it excluded under Firefox resistFingerprinting?

resistFingerprinting (also in Tor Browser and Mullvad Browser) reports a pixel ratio of 1 regardless of the screen, so reading it adds nothing. The exclusion table reports it as excluded with ruleId firefox_rfp, or rfp_hardened for Tor and Mullvad.

### What can my server use it for?

As a consistency hint: a phone user agent with a ratio of 1, or a value that does not fit the reported screen, is worth a look. Do not use it to match devices.

## Related pages

- [screen_resolution](https://whiskerjs.com/signals/screen-resolution/): The screen size, which is in the id.
- [screen_frame](https://whiskerjs.com/signals/screen-frame/): Another screen value kept out of the ids.
- [What changes the id](https://whiskerjs.com/docs/identifiers/#what-changes-the-id): And what does not.
- [Firefox resistFingerprinting, Tor and Mullvad](https://whiskerjs.com/browsers/firefox-rfp-and-tor/): Where this component is excluded.
