# ua_versions

> Full brand versions and the operating system version from Chromium's Client Hints. Reported for your server, kept out of both ids because every update changes them.

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

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

| Field | Value |
| --- | --- |
| Component name | `ua_versions` |
| 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 | no browser class |
| Inner timeout | 1000 ms |
| Added in | [signalsVersion 2](https://whiskerjs.com/whats-new/) |

> **In plain words:**
>
> Chromium-based browsers can tell a page their exact version numbers and the operating system version. That is useful for your server, for example to spot an outdated browser or a mismatch with the request headers, but it changes with every update. WhiskerJS reports it separately and never lets it touch the identifiers.

## What it reads

From `navigator.userAgentData`: `fullVersionList` and `platformVersion` from the shared `getHighEntropyValues()` call, or the low-entropy `brands` list when the detailed call gives nothing.

## How the technique works

1. Without `navigator.userAgentData` the component is `unavailable` / `no_api`.
2. It uses the same single high-entropy request as [`ua_client_hints`](https://whiskerjs.com/signals/ua-client-hints/).
3. Brands are filtered for [GREASE](https://whiskerjs.com/glossary/#grease) and sorted. When `fullVersionList` is present and not empty it is used; otherwise the low-entropy `brands`, whose versions are major versions only.
4. The value is `brands=Name/version,...;platform_version=<v>` when the detailed hints came back, or `brands=...;he=<state>` when they were blocked (`he=blocked`), failed (`he=failed`) or do not exist (`he=none`).
5. Longer than 128 characters means it is hashed.

## Why it helps

Exact versions are a strong consistency check against the user agent header and the [`ua_client_hints`](https://whiskerjs.com/signals/ua-client-hints/) brands, and they show outdated or unusual builds. They also explain id changes: if the `browser` group moved and `ua_versions` moved too, a browser update is the likely cause.

Keep it with the stored result so you can explain id changes later: when you see a new visitorId for a known account, an older and a newer `ua_versions` side by side often answer the question in seconds.

## Stability

Low by design: it changes with every browser or operating system update. That is the reason it is outside both ids.

## Browser support and what blocks it

- Chromium-based browsers: [Chrome desktop](https://whiskerjs.com/browsers/chrome-desktop/), [Chrome Android](https://whiskerjs.com/browsers/chrome-android/), [Edge](https://whiskerjs.com/browsers/edge/), [Brave](https://whiskerjs.com/browsers/brave/), [Samsung Internet](https://whiskerjs.com/browsers/samsung-internet/).
- [Safari](https://whiskerjs.com/browsers/safari-macos/), [iOS browsers](https://whiskerjs.com/browsers/safari-ios/) and [Firefox](https://whiskerjs.com/browsers/firefox/): `unavailable` / `no_api`.
- A [Permissions Policy](https://whiskerjs.com/glossary/#permissions-policy) that refuses the detailed hints gives `he=blocked`.

## Privacy

Version numbers are shared by everyone on the same release, so they identify a release rather than a person. Your server already receives similar information in the user agent header. The value is not in an id.

## How WhiskerJS handles noise and failures

| Status | ruleId | When |
| --- | --- | --- |
| `ok` |   | versions, or a `he=` marker |
| `unavailable` | `no_api` | no `navigator.userAgentData` |
| `unavailable` | `no_digest` | a long value needs hashing without `crypto.subtle` |
| `excluded` | `caller_excluded` | you excluded it |
| `timed_out` | `timeout`, `aborted` | the hints did not answer in 1000 ms, or budget or abort |

## Example value

From headless Chromium in a Linux container: `brands=Chromium/140.0.7339.16,HeadlessChrome/140.0.7339.16;platform_version=7.0.14`. Firefox and WebKit in the same run: `unavailable` / `no_api`.

## Questions and answers

### Why are versions kept out of the visitorId?

Browsers update every few weeks and operating systems often. With versions in the id, every update would give the same device a new id.

### What do I get when the detailed hints are refused?

The brand list falls back to the low-entropy brands with their major versions only, and the second part becomes he=blocked (or he=failed, he=none) instead of platform_version.

### Why is ua_versions sometimes a digest?

Any value longer than 128 characters is hashed. A long brand list with full versions can pass that limit.

## Related pages

- [ua_client_hints](https://whiskerjs.com/signals/ua-client-hints/): The stable part of Client Hints, in the id.
- [High-entropy hints](https://whiskerjs.com/glossary/#high-entropy-hints): The detailed Client Hints.
- [Recommended server checks](https://whiskerjs.com/docs/integration/#recommended-server-checks): Compare versions with the request headers.
