Browsers · WhiskerJS 0.1.0

Browser support matrix

The expected status of every component in nine browser families at signalsVersion 5, rendered from one data file.

In plain words

Not every browser offers every measurement. Some lack the API, some randomise it on purpose, and some only offer it in certain modes. This table shows, for each of the 46 WhiskerJS signals, what to expect in nine browser families. It is filled from the library’s code and documentation plus one small early lab sample, so treat it as expectations, not measurements.

How to read it

  • ok: the value is read. none: read, but here the plain value is none (for example no Apple Pay outside Safari). unavailable: the browser does not offer the API, or WhiskerJS skips it here on purpose. excluded: the exclusion table removes it for this browser class. varies: depends on version, settings, a private window, an extension or the device.
  • Cells marked lab were seen in the early lab sample (signalsVersion 1, four device and browser pairs, not a benchmark). Every other cell is expected behaviour from the code and documentation, not yet measured.
  • In any browser a component can also be noisy, blocked or timed_out on a given run; see Statuses and reason codes.

Where the data comes from

The page is rendered from one file in the site repository, data/support-matrix.json. It holds the browser list, one row per component and one cell per browser (status, basis and a short note). It will be refreshed from aggregated diagnostics once those exist; updating that file updates this page and the table at the end of every browser page, with no code change.

The matrix

46 components by 9 browser families, signalsVersion 5, updated 2026-10-26. Scroll sideways on a small screen. Notes for individual cells follow the table.

ComponentGroupChrome (desktop)Chrome on AndroidSafari on macOSSafari and every iOS browserFirefoxFirefox resistFingerprinting and Tor BrowserBraveMicrosoft EdgeSamsung Internet
apple_paybrowsernone *none *ok *varies *none *none *none *none *none *
audioaudiookokok *ok *okokexcluded *okok
audio_latencyoutside the idsunavailable *ok *ok *ok *varies *varies *varies *unavailable *ok *
browser_classbrowserok *ok *ok *ok *ok *ok *ok *ok *ok *
canvasgpuok *ok *varies *varies *ok *excluded *excluded *ok *ok *
canvas_readbackoutside the idsok *okvaries *varies *okvaries *varies *okok
color_depthdeviceokokokokokokokokok
color_gamutprefsokokokokokokokokok
content_blockersoutside the idsok *ok *ok *ok *ok *ok *ok *ok *ok *
cpu_architecturedeviceokokokokokokokokok
device_memorydeviceok (lab) *okunavailable (lab) *unavailable (lab) *unavailable *unavailable *varies *okok
dynamic_rangeprefsokokokokokokokokok
font_preferencesfontsokokokokokokokokok
fontsfontsokokokokokok *excluded *okok
fonts_canvasfontsokokokokokok *excluded *okok
forced_colorsprefsokokokokokokokokok
hardware_concurrencydeviceok *ok *ok *ok *ok *excluded *excluded *ok *ok *
heap_limitdeviceokokunavailable *unavailable *unavailable *unavailable *okokok
intl_localelocaleokokokokokokokokok
keyboard_layoutoutside the idsok *varies *unavailable *unavailable *unavailable *unavailable *varies *ok *varies *
languageslocaleokokokokokok *okokok
mathbrowserokokokokokokokokok
media_codecsbrowserokokokokokokokokok
pdf_viewerbrowserokokokvaries *okokokokok
permissionsoutside the idsokokokokokokokokok
pixel_ratiooutside the idsokokokokokexcluded *okokok
platformbrowserokokokokokokokokok
pluginsbrowserokvaries *okvaries *okokexcluded *okvaries *
prefers_contrastprefsokokokokokokokokok
private_clickbrowsernone *none *ok *varies *none *none *none *none *none *
reduced_motionprefsokokokokokokokokok
screen_frameoutside the idsokokokokokexcluded *okokok
screen_resolutiondeviceokokokokokexcluded *okokok
speech_voicesoutside the idsok *ok *ok *ok *ok *varies *ok *ok *ok *
storagebrowserokokokokokokokokok
time_zonelocaleokokokokokexcluded *okokok
touch_supportdeviceokokokokokokokokok
ua_client_hintsbrowserok *ok *unavailable *unavailable *unavailable *unavailable *ok *ok *ok *
ua_versionsoutside the idsokokunavailable *unavailable *unavailable *unavailable *ok *okok
vendorbrowserokokokokokokokokok
vendor_flavorsbrowserokokokokokokokokok
webgl_imagegpuok *ok *varies *varies *ok *excluded *excluded *ok *ok *
webgl_paramsgpuok *ok *ok *ok *ok *ok *ok *ok *ok *
webgl_renderergpuokokok *ok *ok *excluded *okokok
webgl_vendorgpuokokokokok *excluded *okokok
webgpugpuvaries *varies *varies *varies *varies *varies *varies *varies *varies *

Filled on 2026-10-26 from the WhiskerJS code and documentation at signalsVersion 5 (expected behaviour) and from the early lab sample at signalsVersion 1 (four device-browser pairs). It is not a measurement. It will be refreshed from aggregated diagnostics once those exist; this file is the only place to change.

Notes on individual cells

Every cell marked with * above, by component.

ComponentBrowserStatusNote
apple_payChrome (desktop)noneNo ApplePaySession: reports the plain value none.
apple_payChrome on AndroidnoneNo ApplePaySession: reports the plain value none.
apple_paySafari on macOSokversion=<n>;can_pay=<1, 0 or blocked>; can_pay is blocked in insecure or cross-origin contexts.
apple_paySafari and every iOS browservariesSafari has ApplePaySession; in other iOS browsers it depends on the app. none where it is missing.
apple_payFirefoxnoneNo ApplePaySession: reports the plain value none.
apple_payFirefox resistFingerprinting and Tor BrowsernoneNo ApplePaySession: reports the plain value none.
apple_payBravenoneNo ApplePaySession: reports the plain value none.
apple_payMicrosoft EdgenoneNo ApplePaySession: reports the plain value none.
apple_paySamsung InternetnoneNo ApplePaySession: reports the plain value none.
audioSafari on macOSokNo double render for audio: noise added to audio reads would change the digest each run.
audioSafari and every iOS browserokNo double render for audio: noise added to audio reads would change the digest each run.
audioBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
audio_latencyChrome (desktop)unavailableSkipped (unavailable / skipped): creating an AudioContext here would print a console warning.
audio_latencyChrome on AndroidokRead when the user agent says Android.
audio_latencySafari on macOSokRead for browser class safari; the context is closed at once.
audio_latencySafari and every iOS browserokRead for browser class safari; the context is closed at once.
audio_latencyFirefoxvariesSkipped on desktop; Firefox for Android has an Android user agent, so it is read there.
audio_latencyFirefox resistFingerprinting and Tor BrowservariesSkipped on desktop; read only with an Android user agent.
audio_latencyBravevariesRead on Android (Android user agent), skipped on desktop.
audio_latencyMicrosoft EdgeunavailableSkipped (unavailable / skipped): creating an AudioContext here would print a console warning.
audio_latencySamsung InternetokRead when the user agent says Android.
browser_classChrome (desktop)okClass chromium.
browser_classChrome on AndroidokClass chromium.
browser_classSafari on macOSokClass safari.
browser_classSafari and every iOS browserokClass safari, for every iOS browser (Apple vendor, no Chrome/ token).
browser_classFirefoxokClass firefox.
browser_classFirefox resistFingerprinting and Tor BrowserokClass firefox_rfp only when every resistFingerprinting trait holds; otherwise firefox.
browser_classBraveokClass brave (navigator.brave.isBrave is a function).
browser_classMicrosoft EdgeokClass chromium.
browser_classSamsung InternetokClass chromium.
canvasChrome (desktop)oknoisy / render_mismatch if an extension or setting adds noise to readback.
canvasChrome on Androidoknoisy / render_mismatch if an extension or setting adds noise to readback.
canvasSafari on macOSvariesApple describes fingerprinting protections that can add noise to readback in some modes (for example private browsing); WhiskerJS reports noisy / render_mismatch when the double render differs.
canvasSafari and every iOS browservariesApple describes fingerprinting protections that can add noise to readback in some modes (for example private browsing); WhiskerJS reports noisy / render_mismatch when the double render differs.
canvasFirefoxoknoisy / render_mismatch if an extension or setting adds noise to readback.
canvasFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
canvasBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
canvasMicrosoft Edgeoknoisy / render_mismatch if an extension or setting adds noise to readback.
canvasSamsung Internetoknoisy / render_mismatch if an extension or setting adds noise to readback.
canvas_readbackChrome (desktop)okexact, or altered when an extension adds noise.
canvas_readbackSafari on macOSvariesexact, or altered where readback noise is applied.
canvas_readbackSafari and every iOS browservariesexact, or altered where readback noise is applied.
canvas_readbackFirefox resistFingerprinting and Tor BrowservariesresistFingerprinting changes canvas readback, so altered is likely.
canvas_readbackBravevariesNot excluded; Brave's canvas farbling can make it report altered.
content_blockersChrome (desktop)oknone, or the bait names a content blocker hid.
content_blockersChrome on Androidoknone, or the bait names a content blocker hid.
content_blockersSafari on macOSoknone, or the bait names a content blocker hid.
content_blockersSafari and every iOS browseroknone, or the bait names a content blocker hid.
content_blockersFirefoxoknone, or the bait names a content blocker hid.
content_blockersFirefox resistFingerprinting and Tor Browseroknone, or the bait names a content blocker hid.
content_blockersBraveokBrave's built-in blocking may hide some baits; reports the hidden bait names or none.
content_blockersMicrosoft Edgeoknone, or the bait names a content blocker hid.
content_blockersSamsung Internetoknone, or the bait names a content blocker hid.
device_memoryChrome (desktop)ok (lab)Seen ok on Mac Chrome in the lab sample.
device_memorySafari on macOSunavailable (lab)Seen unavailable on Mac Safari in the lab sample; Safari does not offer navigator.deviceMemory.
device_memorySafari and every iOS browserunavailable (lab)Seen unavailable on iPhone Safari and iPhone Chrome in the lab sample; no iOS browser offers it.
device_memoryFirefoxunavailablenavigator.deviceMemory is a Chromium API. Reports unavailable / no_api.
device_memoryFirefox resistFingerprinting and Tor Browserunavailablenavigator.deviceMemory is a Chromium API. Reports unavailable / no_api.
device_memoryBravevariesChromium API; Brave's fingerprinting protections may change the value.
fontsFirefox resistFingerprinting and Tor BrowserokTor Browser limits fonts to a bundled set, so values are alike across its users.
fontsBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
fonts_canvasFirefox resistFingerprinting and Tor BrowserokTor Browser limits fonts to a bundled set, so values are alike across its users.
fonts_canvasBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
hardware_concurrencyChrome (desktop)okSome browsers cap or round the value.
hardware_concurrencyChrome on AndroidokSome browsers cap or round the value.
hardware_concurrencySafari on macOSokSome browsers cap or round the value.
hardware_concurrencySafari and every iOS browserokSome browsers cap or round the value.
hardware_concurrencyFirefoxokSome browsers cap or round the value.
hardware_concurrencyFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
hardware_concurrencyBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
hardware_concurrencyMicrosoft EdgeokSome browsers cap or round the value.
hardware_concurrencySamsung InternetokSome browsers cap or round the value.
heap_limitSafari on macOSunavailableperformance.memory is a Chromium API. Reports unavailable / no_api.
heap_limitSafari and every iOS browserunavailableperformance.memory is a Chromium API. Reports unavailable / no_api.
heap_limitFirefoxunavailableperformance.memory is a Chromium API. Reports unavailable / no_api.
heap_limitFirefox resistFingerprinting and Tor Browserunavailableperformance.memory is a Chromium API. Reports unavailable / no_api.
keyboard_layoutChrome (desktop)oknavigator.keyboard.getLayoutMap() is a Chromium desktop API; blocked in cross-origin iframes.
keyboard_layoutChrome on AndroidvariesChromium API meant for physical keyboards; on Android expect unavailable.
keyboard_layoutSafari on macOSunavailableNo navigator.keyboard here: unavailable / no_api.
keyboard_layoutSafari and every iOS browserunavailableNo navigator.keyboard here: unavailable / no_api.
keyboard_layoutFirefoxunavailableNo navigator.keyboard here: unavailable / no_api.
keyboard_layoutFirefox resistFingerprinting and Tor BrowserunavailableNo navigator.keyboard here: unavailable / no_api.
keyboard_layoutBravevariesChromium API; Brave may turn it off.
keyboard_layoutMicrosoft Edgeoknavigator.keyboard.getLayoutMap() is a Chromium desktop API; blocked in cross-origin iframes.
keyboard_layoutSamsung InternetvariesChromium API meant for physical keyboards; on Android expect unavailable.
languagesFirefox resistFingerprinting and Tor BrowserokresistFingerprinting can normalise the reported language.
pdf_viewerSafari and every iOS browservariesunavailable where navigator.pdfViewerEnabled does not exist.
pixel_ratioFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
pluginsChrome on AndroidvariesMobile builds often list no plugins and then report the plain value none.
pluginsSafari and every iOS browservariesMobile builds often list no plugins and then report the plain value none.
pluginsBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
pluginsSamsung InternetvariesMobile builds often list no plugins and then report the plain value none.
private_clickChrome (desktop)noneNo attributionSourceId on anchors: reports the plain value none.
private_clickChrome on AndroidnoneNo attributionSourceId on anchors: reports the plain value none.
private_clickSafari on macOSokSafari Private Click Measurement exposes attributionSourceId.
private_clickSafari and every iOS browservariesDepends on whether the app's WebKit exposes Private Click Measurement; none otherwise.
private_clickFirefoxnoneNo attributionSourceId on anchors: reports the plain value none.
private_clickFirefox resistFingerprinting and Tor BrowsernoneNo attributionSourceId on anchors: reports the plain value none.
private_clickBravenoneNo attributionSourceId on anchors: reports the plain value none.
private_clickMicrosoft EdgenoneNo attributionSourceId on anchors: reports the plain value none.
private_clickSamsung InternetnoneNo attributionSourceId on anchors: reports the plain value none.
screen_frameFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
screen_resolutionFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
speech_voicesChrome (desktop)okDigest of the voice list, or none; some browsers fill the list late.
speech_voicesChrome on AndroidokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesSafari on macOSokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesSafari and every iOS browserokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesFirefoxokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesFirefox resistFingerprinting and Tor BrowservariesDigest of the voice list, or none when the list is empty.
speech_voicesBraveokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesMicrosoft EdgeokDigest of the voice list, or none; some browsers fill the list late.
speech_voicesSamsung InternetokDigest of the voice list, or none; some browsers fill the list late.
time_zoneFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
ua_client_hintsChrome (desktop)okhe=blocked when a Permissions Policy refuses the detailed hints.
ua_client_hintsChrome on Androidokhe=blocked when a Permissions Policy refuses the detailed hints.
ua_client_hintsSafari on macOSunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_client_hintsSafari and every iOS browserunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_client_hintsFirefoxunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_client_hintsFirefox resistFingerprinting and Tor Browserunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_client_hintsBraveokChromium API; the brand list is whatever Brave reports.
ua_client_hintsMicrosoft Edgeokhe=blocked when a Permissions Policy refuses the detailed hints.
ua_client_hintsSamsung Internetokhe=blocked when a Permissions Policy refuses the detailed hints.
ua_versionsSafari on macOSunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_versionsSafari and every iOS browserunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_versionsFirefoxunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_versionsFirefox resistFingerprinting and Tor Browserunavailablenavigator.userAgentData (Client Hints) is a Chromium API. Reports unavailable / no_api.
ua_versionsBraveokChromium API; not in either id.
webgl_imageChrome (desktop)oknoisy / render_mismatch if an extension or setting adds noise to readback.
webgl_imageChrome on Androidoknoisy / render_mismatch if an extension or setting adds noise to readback.
webgl_imageSafari on macOSvariesApple describes fingerprinting protections that can add noise to readback in some modes (for example private browsing); WhiskerJS reports noisy / render_mismatch when the double render differs.
webgl_imageSafari and every iOS browservariesApple describes fingerprinting protections that can add noise to readback in some modes (for example private browsing); WhiskerJS reports noisy / render_mismatch when the double render differs.
webgl_imageFirefoxoknoisy / render_mismatch if an extension or setting adds noise to readback.
webgl_imageFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
webgl_imageBraveexcludedExclusion table: brave_farbling (Brave adds per-site, per-session noise).
webgl_imageMicrosoft Edgeoknoisy / render_mismatch if an extension or setting adds noise to readback.
webgl_imageSamsung Internetoknoisy / render_mismatch if an extension or setting adds noise to readback.
webgl_paramsChrome (desktop)okWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsChrome on AndroidokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsSafari on macOSokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsSafari and every iOS browserokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsFirefoxokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsFirefox resistFingerprinting and Tor BrowserokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsBraveokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsMicrosoft EdgeokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_paramsSamsung InternetokWhere WebGL 1 is available; unavailable / no_context without it.
webgl_rendererSafari on macOSokOften a generic string such as Apple GPU.
webgl_rendererSafari and every iOS browserokOften a generic string such as Apple GPU.
webgl_rendererFirefoxokRead from gl.RENDERER; WEBGL_debug_renderer_info is not requested in Firefox.
webgl_rendererFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
webgl_vendorFirefoxokRead from gl.VENDOR; WEBGL_debug_renderer_info is not requested in Firefox.
webgl_vendorFirefox resistFingerprinting and Tor BrowserexcludedExclusion table: firefox_rfp (fixed or normalised values).
webgpuChrome (desktop)variesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuChrome on AndroidvariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuSafari on macOSvariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuSafari and every iOS browservariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuFirefoxvariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuFirefox resistFingerprinting and Tor BrowservariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuBravevariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuMicrosoft EdgevariesDepends on browser version, operating system and GPU; needs a secure context. unavailable / no_api without navigator.gpu, no_context without an adapter.
webgpuSamsung InternetvariesDepends 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 this matrix measured?

Not yet. Almost every cell is expected behaviour read from the library code and documentation. Only the cells marked lab come from the early lab sample at signalsVersion 1, which covered four device and browser pairs. The matrix will be refreshed from aggregated diagnostics.

Why do all iOS browsers share one column?

On iOS every browser uses Apple's WebKit engine and reports the Apple vendor, so WhiskerJS classes Chrome, Firefox and Edge on iOS as safari, the same as Safari itself.

What does varies mean?

The status depends on the browser version, a setting, a private window, an extension or the device. The note on that row says what it depends on.