# Chrome (desktop)

> Desktop Chrome offers every API WhiskerJS reads, and the library excludes nothing there.

Source: https://whiskerjs.com/browsers/chrome-desktop/ (last updated 2026-10-26)

> **In plain words:**
>
> Desktop Chrome is the browser where WhiskerJS can read the most: it offers every API the library uses, including a few that only Chromium-based browsers have, such as the device memory and Client Hints. WhiskerJS removes nothing on purpose here. The main things to know are that one small audio signal is skipped to keep the console clean, and that automated or headless Chrome tends to raise integrity flags.

## At a glance

- Browser class: `chromium` (the user agent has a `Chrome/<number>` token).
- Excluded components: none.
- Chromium-only components that are `ok` here: `device_memory`, `heap_limit`, `ua_client_hints`, `ua_versions`, `keyboard_layout`.
- Skipped on purpose: `audio_latency`.
- Lab sample: Mac Chrome kept one id across 4 runs at signalsVersion 1.

## What works

Nearly everything. The graphics group reads a 2D canvas scene twice, a WebGL triangle twice, 21 WebGL parameters with shader precisions and extensions, and the unmasked renderer and vendor through `WEBGL_debug_renderer_info`. Where Chrome has WebGPU enabled, [`webgpu`](https://whiskerjs.com/signals/webgpu/) hashes the adapter’s info, features and seven limits; whether `navigator.gpu` exists depends on the Chrome version, the operating system and the GPU, so treat it as variable.

The Chromium-only components work here:

- [`device_memory`](https://whiskerjs.com/signals/device-memory/) from `navigator.deviceMemory` (coarse buckets such as `8`; from Chromium 146 with the tag `;c146`, for example `16;c146`);
- [`heap_limit`](https://whiskerjs.com/signals/heap-limit/) from `performance.memory.jsHeapSizeLimit`;
- [`ua_client_hints`](https://whiskerjs.com/signals/ua-client-hints/): brands without versions (GREASE removed), mobile, platform, and from one `getHighEntropyValues()` call the architecture, bitness, wow64, model and form factors;
- [`ua_versions`](https://whiskerjs.com/signals/ua-versions/): full brand versions and the platform version, kept out of both ids because they change with every update;
- [`keyboard_layout`](https://whiskerjs.com/signals/keyboard-layout/) from `navigator.keyboard.getLayoutMap()`, outside the ids.

Fonts, font preferences, audio, Math, codecs, locale, the five display preference queries, storage presence and permission states are all read as on any current browser.

## What is unavailable or blocked

- [`audio_latency`](https://whiskerjs.com/signals/audio-latency/) is `unavailable` with ruleId `skipped`. Desktop Chrome prints an autoplay warning when a page creates an `AudioContext` without a user gesture, and WhiskerJS writes nothing to the console.
- [`apple_pay`](https://whiskerjs.com/signals/apple-pay/) and [`private_click`](https://whiskerjs.com/signals/private-click/) report the plain value `none`: these are Safari features.
- `ua_client_hints` and `ua_versions` end with `he=blocked` instead of the detailed hints when a Permissions Policy refuses them, for example in an embedded frame. That marker is stable, so it does not make the id jump.
- `keyboard_layout` is `blocked` in cross-origin iframes, where Chrome refuses the call.
- [`webgpu`](https://whiskerjs.com/signals/webgpu/) is `unavailable` with `no_api` where `navigator.gpu` is missing, or `no_context` when no adapter is returned (seen in a headless container run).

## What WhiskerJS excludes and why

Nothing. The exclusion table has an empty row for the `chromium` class, because stock Chrome does not randomise the signals WhiskerJS reads. If an extension adds noise to canvas or WebGL readback, the [double render](https://whiskerjs.com/glossary/#double-render) catches it and the component becomes `noisy` with ruleId `render_mismatch`, and [`canvas_readback`](https://whiskerjs.com/signals/canvas-readback/) reports `altered`. The [known-answer probes](https://whiskerjs.com/signals/noise-profile/) also catch noise that is the same on both reads (`noisy` / `seeded_noise`, for `canvas`, `webgl_image` and `audio`).

## Integrity flags to expect

From the [integrity checks](https://whiskerjs.com/docs/integrity/) and their documented false positives:

- [`automation_webdriver`](https://whiskerjs.com/docs/integrity/#automation_webdriver): Selenium, Playwright and Puppeteer set `navigator.webdriver` by default, and so do your own end-to-end tests.
- [`headless_user_agent`](https://whiskerjs.com/docs/integrity/#headless_user_agent): the user agent contains `HeadlessChrome`.
- [`headless_markers`](https://whiskerjs.com/docs/integrity/#headless_markers): an outer window of 0x0, or a desktop Chrome user agent without `window.chrome`. Some embedded Chromium views raise it too.
- [`software_renderer`](https://whiskerjs.com/docs/integrity/#software_renderer): the WebGL renderer names SwiftShader or similar. Real users with hardware acceleration switched off, or on remote desktops, raise it as well.
- [`native_tampering`](https://whiskerjs.com/docs/integrity/#native_tampering), [`prototype_lie`](https://whiskerjs.com/docs/integrity/#prototype_lie) and [`navigator_own_property`](https://whiskerjs.com/docs/integrity/#navigator_own_property): expect them from privacy and anti-fingerprinting extensions.
- [`permissions_inconsistent`](https://whiskerjs.com/docs/integrity/#permissions_inconsistent): notifications `denied` while the permissions query says `prompt`, a known headless Chrome trait.
- [`ua_ch_mismatch`](https://whiskerjs.com/docs/integrity/#ua_ch_mismatch): the user agent disagrees with Client Hints (Chromium version, platform, mobile), or a brand contains `Headless`. User-agent switchers raise it too.
- [`exposed_binding`](https://whiskerjs.com/docs/integrity/#exposed_binding): Playwright exposed a function to the page.
- [`vm_renderer`](https://whiskerjs.com/docs/integrity/#vm_renderer): the WebGL renderer names a virtual machine adapter (VMware, VirtualBox, Parallels, QEMU and KVM, Hyper-V). Real users on virtual desktops raise it too.

For illustration only: a headless Chromium run in a test container (not the lab sample) was classed `other` at signalsVersion 5 (it is `chromium` since signalsVersion 9), had a SwiftShader WebGL renderer and raised `automation_webdriver`, `headless_user_agent`, `permissions_inconsistent` and `software_renderer`. Any single flag is weak evidence; your server weighs them.

## Early lab observations

An early, small sample at signalsVersion 1, not a benchmark: on a Mac, Chrome kept **one id across 4 runs**, and that id differed from the ids of the other three device and browser pairs in the sample. `device_memory` was `ok`. The sample used the first collector (30 components), not the current 47, and involved no other library.

## Testing it yourself

Open the [live demo](https://whiskerjs.com/demo/) in Chrome, run it a few times, and come back after a browser update to see which structuredId group moves. The [lab mode](https://whiskerjs.com/demo/#lab) copies one tab-separated line per run, so you can collect runs from several machines and compare them. Nothing is sent anywhere.

## Support table for Chrome (desktop)

Expected status of every component in this browser at signalsVersion 9, from [the support matrix](https://whiskerjs.com/browsers/support-matrix/) (updated 2026-10-26). Basis "code" means expected from the library code and documentation, not yet measured; "lab" means seen in the early lab sample.

| Component | Status | Basis | Note |
| --- | --- | --- | --- |
| [`apple_pay`](https://whiskerjs.com/signals/apple-pay/) | none | code | No ApplePaySession: reports the plain value none. |
| [`audio`](https://whiskerjs.com/signals/audio/) | ok | code | noisy / seeded_noise if the audio known-answer probe sees noise. |
| [`audio_latency`](https://whiskerjs.com/signals/audio-latency/) | unavailable | code | Skipped (unavailable / skipped): creating an AudioContext here would print a console warning. |
| [`browser_class`](https://whiskerjs.com/signals/browser-class/) | ok | code | Class chromium. |
| [`canvas`](https://whiskerjs.com/signals/canvas/) | ok | code | noisy / render_mismatch or seeded_noise if an extension or setting adds noise to readback. |
| [`canvas_readback`](https://whiskerjs.com/signals/canvas-readback/) | ok | code | exact, or altered when an extension adds noise. |
| [`color_depth`](https://whiskerjs.com/signals/color-depth/) | ok | code |   |
| [`color_gamut`](https://whiskerjs.com/signals/color-gamut/) | ok | code |   |
| [`content_blockers`](https://whiskerjs.com/signals/content-blockers/) | ok | code | none, or the bait names a content blocker hid. |
| [`cpu_architecture`](https://whiskerjs.com/signals/cpu-architecture/) | ok | code |   |
| [`device_memory`](https://whiskerjs.com/signals/device-memory/) | ok | lab | Seen ok on Mac Chrome in the lab sample. From Chromium 146 the value carries the tag ;c146 (new buckets). |
| [`dynamic_range`](https://whiskerjs.com/signals/dynamic-range/) | ok | code |   |
| [`font_preferences`](https://whiskerjs.com/signals/font-preferences/) | ok | code |   |
| [`fonts`](https://whiskerjs.com/signals/fonts/) | ok | code |   |
| [`fonts_canvas`](https://whiskerjs.com/signals/fonts-canvas/) | ok | code |   |
| [`forced_colors`](https://whiskerjs.com/signals/forced-colors/) | ok | code |   |
| [`hardware_concurrency`](https://whiskerjs.com/signals/hardware-concurrency/) | ok | code | Read 16 times; noisy / read_varies if the reads disagree. Some browsers cap or round the value. |
| [`heap_limit`](https://whiskerjs.com/signals/heap-limit/) | ok | code |   |
| [`intl_locale`](https://whiskerjs.com/signals/intl-locale/) | ok | code |   |
| [`keyboard_layout`](https://whiskerjs.com/signals/keyboard-layout/) | ok | code | navigator.keyboard.getLayoutMap() is a Chromium desktop API; blocked in cross-origin iframes. |
| [`languages`](https://whiskerjs.com/signals/languages/) | ok | code |   |
| [`math`](https://whiskerjs.com/signals/math/) | ok | code |   |
| [`media_codecs`](https://whiskerjs.com/signals/media-codecs/) | ok | code |   |
| [`noise_profile`](https://whiskerjs.com/signals/noise-profile/) | ok | code | canvas=exact,webgl=exact,audio=exact on a stock browser; webgl=na without WebGL. |
| [`pdf_viewer`](https://whiskerjs.com/signals/pdf-viewer/) | ok | code |   |
| [`permissions`](https://whiskerjs.com/signals/permissions/) | ok | code |   |
| [`pixel_ratio`](https://whiskerjs.com/signals/pixel-ratio/) | ok | code |   |
| [`platform`](https://whiskerjs.com/signals/platform/) | ok | code |   |
| [`plugins`](https://whiskerjs.com/signals/plugins/) | ok | code |   |
| [`prefers_contrast`](https://whiskerjs.com/signals/prefers-contrast/) | ok | code |   |
| [`private_click`](https://whiskerjs.com/signals/private-click/) | none | code | No attributionSourceId on anchors: reports the plain value none. |
| [`reduced_motion`](https://whiskerjs.com/signals/reduced-motion/) | ok | code |   |
| [`screen_frame`](https://whiskerjs.com/signals/screen-frame/) | ok | code |   |
| [`screen_resolution`](https://whiskerjs.com/signals/screen-resolution/) | ok | code |   |
| [`speech_voices`](https://whiskerjs.com/signals/speech-voices/) | ok | code | Digest of the voice list, or none; some browsers fill the list late. |
| [`storage`](https://whiskerjs.com/signals/storage/) | ok | code |   |
| [`time_zone`](https://whiskerjs.com/signals/time-zone/) | ok | code |   |
| [`touch_support`](https://whiskerjs.com/signals/touch-support/) | ok | code |   |
| [`ua_client_hints`](https://whiskerjs.com/signals/ua-client-hints/) | ok | code | he=blocked when a Permissions Policy refuses the detailed hints. |
| [`ua_versions`](https://whiskerjs.com/signals/ua-versions/) | ok | code |   |
| [`vendor`](https://whiskerjs.com/signals/vendor/) | ok | code |   |
| [`vendor_flavors`](https://whiskerjs.com/signals/vendor-flavors/) | ok | code |   |
| [`webgl_image`](https://whiskerjs.com/signals/webgl-image/) | ok | code | noisy / render_mismatch or seeded_noise if an extension or setting adds noise to readback. |
| [`webgl_params`](https://whiskerjs.com/signals/webgl-params/) | ok | code | Where WebGL 1 is available; unavailable / no_context without it. |
| [`webgl_renderer`](https://whiskerjs.com/signals/webgl-renderer/) | ok | code |   |
| [`webgl_vendor`](https://whiskerjs.com/signals/webgl-vendor/) | ok | code |   |
| [`webgpu`](https://whiskerjs.com/signals/webgpu/) | varies | code | Depends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter. |

## Questions and answers

### Is anything excluded in Chrome?

No. The exclusion table has no row for the chromium class, so all 47 components are collected. Some can still be noisy if an extension adds noise to canvas, WebGL or audio readback.

### Why is audio_latency unavailable in Chrome?

Creating an AudioContext outside a user gesture makes desktop Chrome print an autoplay warning in the console, and WhiskerJS never writes to the console. So it reports unavailable with ruleId skipped. Nothing is wrong with the browser.

### What browser_class does headless Chrome show?

chromium, since signalsVersion 9. A headless Chromium whose user agent names only HeadlessChrome/ was classed other until signalsVersion 8, because the class test looked for a Chrome/ token and the old headless mode lacks window.chrome. The headless flags, such as headless_user_agent, report the rest.

### Why does device_memory end in ;c146?

Chromium 146 changed the memory buckets (up to 32 GB on desktop, where the old cap was 8). From that version WhiskerJS tags the value, for example 16;c146, so a server can tell which scheme it comes from. Expect one id change per user at the update to 146.

## Related pages

- [Microsoft Edge](https://whiskerjs.com/browsers/edge/): Another Chromium browser, with the same behaviour.
- [Chrome on Android](https://whiskerjs.com/browsers/chrome-android/): The same engine on phones.
- [ua_client_hints](https://whiskerjs.com/signals/ua-client-hints/): Client Hints, a Chromium API.
- [Bot and headless detection](https://whiskerjs.com/use-cases/bot-detection/): How the flags can feed your server's rules.
- [Browser support matrix](https://whiskerjs.com/browsers/support-matrix/): All browsers side by side.
