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 aChrome/<number>token). - Excluded components: none.
- Chromium-only components that are
okhere: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 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_memoryfromnavigator.deviceMemory(coarse buckets such as8; from Chromium 146 with the tag;c146, for example16;c146);heap_limitfromperformance.memory.jsHeapSizeLimit;ua_client_hints: brands without versions (GREASE removed), mobile, platform, and from onegetHighEntropyValues()call the architecture, bitness, wow64, model and form factors;ua_versions: full brand versions and the platform version, kept out of both ids because they change with every update;keyboard_layoutfromnavigator.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_latencyisunavailablewith ruleIdskipped. Desktop Chrome prints an autoplay warning when a page creates anAudioContextwithout a user gesture, and WhiskerJS writes nothing to the console.apple_payandprivate_clickreport the plain valuenone: these are Safari features.ua_client_hintsandua_versionsend withhe=blockedinstead 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_layoutisblockedin cross-origin iframes, where Chrome refuses the call.webgpuisunavailablewithno_apiwherenavigator.gpuis missing, orno_contextwhen 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 catches it and the component becomes noisy with ruleId render_mismatch, and canvas_readback reports altered. The known-answer probes 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 and their documented false positives:
automation_webdriver: Selenium, Playwright and Puppeteer setnavigator.webdriverby default, and so do your own end-to-end tests.headless_user_agent: the user agent containsHeadlessChrome.headless_markers: an outer window of 0x0, or a desktop Chrome user agent withoutwindow.chrome. Some embedded Chromium views raise it too.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,prototype_lieandnavigator_own_property: expect them from privacy and anti-fingerprinting extensions.permissions_inconsistent: notificationsdeniedwhile the permissions query saysprompt, a known headless Chrome trait.ua_ch_mismatch: the user agent disagrees with Client Hints (Chromium version, platform, mobile), or a brand containsHeadless. User-agent switchers raise it too.exposed_binding: Playwright exposed a function to the page.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 in Chrome, run it a few times, and come back after a browser update to see which structuredId group moves. The lab mode 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 (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 | none | code | No ApplePaySession: reports the plain value none. |
audio | ok | code | noisy / seeded_noise if the audio known-answer probe sees noise. |
audio_latency | unavailable | code | Skipped (unavailable / skipped): creating an AudioContext here would print a console warning. |
browser_class | ok | code | Class chromium. |
canvas | ok | code | noisy / render_mismatch or seeded_noise if an extension or setting adds noise to readback. |
canvas_readback | ok | code | exact, or altered when an extension adds noise. |
color_depth | ok | code | |
color_gamut | ok | code | |
content_blockers | ok | code | none, or the bait names a content blocker hid. |
cpu_architecture | ok | code | |
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 | ok | code | |
font_preferences | ok | code | |
fonts | ok | code | |
fonts_canvas | ok | code | |
forced_colors | ok | code | |
hardware_concurrency | ok | code | Read 16 times; noisy / read_varies if the reads disagree. Some browsers cap or round the value. |
heap_limit | ok | code | |
intl_locale | ok | code | |
keyboard_layout | ok | code | navigator.keyboard.getLayoutMap() is a Chromium desktop API; blocked in cross-origin iframes. |
languages | ok | code | |
math | ok | code | |
media_codecs | ok | code | |
noise_profile | ok | code | canvas=exact,webgl=exact,audio=exact on a stock browser; webgl=na without WebGL. |
pdf_viewer | ok | code | |
permissions | ok | code | |
pixel_ratio | ok | code | |
platform | ok | code | |
plugins | ok | code | |
prefers_contrast | ok | code | |
private_click | none | code | No attributionSourceId on anchors: reports the plain value none. |
reduced_motion | ok | code | |
screen_frame | ok | code | |
screen_resolution | ok | code | |
speech_voices | ok | code | Digest of the voice list, or none; some browsers fill the list late. |
storage | ok | code | |
time_zone | ok | code | |
touch_support | ok | code | |
ua_client_hints | ok | code | he=blocked when a Permissions Policy refuses the detailed hints. |
ua_versions | ok | code | |
vendor | ok | code | |
vendor_flavors | ok | code | |
webgl_image | ok | code | noisy / render_mismatch or seeded_noise if an extension or setting adds noise to readback. |
webgl_params | ok | code | Where WebGL 1 is available; unavailable / no_context without it. |
webgl_renderer | ok | code | |
webgl_vendor | ok | code | |
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.