Accessibility Media Query Fingerprinting: 5 CSS Signals Your Browser Reveals (2026)
Accessibility media queries are among the quieter fingerprinting signals. While most attention goes to canvas and WebGL (see the WebGL fingerprinting deep-dive), these CSS features expose OS-level settings to any page you visit. There is no permission prompt: a few lines of CSS or JavaScript tell a site whether you have enabled reduced motion, high contrast, inverted colours, or reduced transparency.
There is a practical lesson for anyone who manages many browser profiles. A profile inherits settings from the machine it runs on unless the browser isolates them. If you set up client or test profiles on your own laptop, where "Reduce motion" may be switched on, the personal preference shows up in every one of them. For a team, that is a good reason to check what each profile actually reports.
What We're Covering
- Which accessibility media queries exist and what they expose
- Why fingerprinting libraries read them
- How to query a profile's current values
- Which combinations are valid on which platform
- How to audit profiles in JustBrowser
You will need a browser profile to test. The JustBrowser seven-day trial works, or any multi-account browser you already use. We will compare results with CreepJS and BrowserLeaks.
Prerequisites
- Basic understanding of CSS media queries
- A multi-account browser with profile configuration access
- Familiarity with browser fingerprinting concepts (the multi-account browser myths debunked post covers fundamentals)
- 20 minutes
Step 1: The Five Accessibility Media Queries
CSS Media Queries Level 5 introduced several features that let websites adapt to user preferences. That is helpful for users who need it, and every adaptation point is also a data point.
prefers-reduced-motion
Tells the site whether the user wants less animation. Values: no-preference (default) or reduce.
const motion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
console.log(motion ? 'reduce' : 'no-preference');
On macOS: System Settings → Accessibility → Display → Reduce motion. On Windows: Settings → Accessibility → Visual effects → Animation effects (off = reduce).
prefers-contrast
Whether the user wants higher or lower contrast. Values: no-preference, more, less, or custom.
const contrast = window.matchMedia('(prefers-contrast: more)').matches;
Less common than reduced-motion, but meaningful when present. Windows High Contrast mode triggers more, and so does macOS's "Increase contrast".
forced-colors
Indicates the browser is enforcing a limited colour palette (like Windows High Contrast). Values: none or active.
const forcedColors = window.matchMedia('(forced-colors: active)').matches;
This one is binary and platform-specific. It is almost exclusively a Windows signal, so forced-colors: active on a macOS machine would be an impossible combination.
prefers-reduced-transparency
Whether the user prefers opaque backgrounds over transparency effects. Values: no-preference or reduce.
const transparency = window.matchMedia('(prefers-reduced-transparency: reduce)').matches;
On macOS: System Settings → Accessibility → Display → Reduce transparency. On Windows: Settings → Accessibility → Visual effects → Transparency effects.
inverted-colors
Whether display colours are inverted. Values: none or inverted.
const inverted = window.matchMedia('(inverted-colors: inverted)').matches;
This query is supported in Safari/WebKit. Chrome doesn't implement it, so in real Chrome neither (inverted-colors: inverted) nor (inverted-colors: none) matches, and a Chrome profile reporting inverted-colors: inverted does not behave like real Chrome.
Step 2: Why These Matter for Fingerprinting
Each query adds a little entropy: at most one bit for a two-state query, and less in practice because most people keep the defaults. Fingerprinting is cumulative, so every bit helps narrow the population.
They also create consistency requirements. The issue is not only that prefers-reduced-motion: reduce makes a browser more distinctive. A browser that reports a fresh default Windows 11 install but also three accessibility features switched on is an unusual combination, because most users never touch these settings.
The open-source FingerprintJS library collects several of these values, and CreepJS displays them alongside its other signals. That is what a site owner would expect from a fingerprinting library: it reads many small signals and checks that they tell one story.
The arithmetic is simple. A minority of users have prefers-reduced-motion: reduce enabled, and fewer have prefers-contrast: more. The overlap is smaller still. Add a few more signals and a browser can become uniquely identifiable.
Accessibility features exist to help people, and using them for fingerprinting is an uncomfortable side effect. It is also a reason privacy-minded users and browser vendors keep debating how much of this should be exposed to pages at all.
Step 3: Checking Your Profile's Current Values
Open dev tools in a profile and run:
const queries = [
'prefers-reduced-motion: reduce',
'prefers-reduced-motion: no-preference',
'prefers-contrast: more',
'prefers-contrast: less',
'prefers-contrast: no-preference',
'forced-colors: active',
'forced-colors: none',
'prefers-reduced-transparency: reduce',
'prefers-reduced-transparency: no-preference',
'inverted-colors: inverted',
'inverted-colors: none'
];
queries.forEach(q => {
const match = window.matchMedia(`(${q})`).matches;
if (match) console.log(`✓ ${q}`);
});
You should see one match per preference category, except inverted-colors in Chrome, which doesn't support the feature and matches neither value. If you see both reduce and no-preference for the same query, something is inconsistent.
For a typical default-settings user, expect:
prefers-reduced-motion: no-preferenceprefers-contrast: no-preferenceforced-colors: noneprefers-reduced-transparency: no-preferenceinverted-colors: none(Safari only; Chrome shows no match)
That is the majority case, and the right baseline for any profile that does not need anything special.
Step 4: Platform-Specific Constraints
Not every preference state is valid on every OS.
Windows constraints:
forced-colors: activeis Windows-specific and valid there.inverted-colorsis not supported in Chrome or Edge, so neither value matches there.
macOS constraints:
inverted-colors: invertedonly works in Safari. Chrome on macOS doesn't support the query, whatever the system setting.forced-colors: activeis not something Chrome on macOS reports.
A Chrome profile on Windows should show the preference behaviour of Chrome on Windows, not Chrome on macOS and not Safari. Browsers built on a real Chromium engine with native platform behaviour handle this naturally, because the values come from the rendering engine rather than from a script. Extension-based tools can only change what JavaScript sees, and CSS media queries are evaluated outside JavaScript.
For what multi-account browsers do and don't change, see our multi-account browser myths post.
Step 5: Auditing JustBrowser Profiles
JustBrowser is a multi-account browser with a custom Chromium engine and native C++ integration. Each profile is its own browser with its own cookies, storage, proxy and identity parameters. Accessibility preferences are not among the identity parameters JustBrowser documents, so check what each profile reports rather than assuming.
To verify a profile:
- Open the profile and run the audit script from Step 3
- Confirm the values make sense for the profile's platform, and note any non-default value that came from the host machine's own settings
- Re-run it after you change a profile's OS, or the host machine's accessibility settings
For specialised work such as accessibility QA, you don't need to change the machine at all: Chrome DevTools' Rendering panel can emulate prefers-reduced-motion, prefers-contrast, forced-colors and prefers-reduced-transparency for the current tab, and Playwright's page.emulateMedia() can set reduced motion and forced colours from a script. Then confirm your site's layout responds correctly.
If you are automating those tests, the REST API for Playwright and Puppeteer lets you start a profile on the local API and attach a standard automation library.
Step 6: Comparing Against Public Tools
Run a profile through these pages and read the output:
CreepJS (abrahamjuliot.github.io/creepjs)
Look at the CSS section. It reports the detected media query values next to the other signals.
BrowserLeaks CSS (browserleaks.com/css)
Shows all media query matches including accessibility features. Useful for seeing raw values without interpretation. Compare against what you expect.
Treat these as readouts, not scoreboards. They show what a page can see, which is the useful part for an audit.
Common Issues
A profile shows a motion preference you did not choose
Cause: The setting came from the machine the profile was created on rather than from a deliberate choice.
What to do: Check the profile's accessibility values with the audit script. A CSS media query can't be overridden from page JavaScript, so if your browser doesn't control the value, the options are to change the host OS setting or, for testing, to use DevTools or Playwright emulation as described in Step 5.
A macOS profile shows forced-colors: active
Cause: Usually a leftover from emulation or from a Windows template that wasn't adjusted for the platform.
What to do: Turn off any forced-colors emulation in DevTools and check the profile's platform settings. forced-colors should be none in Chrome on macOS.
inverted-colors returns a value in a Chrome profile
Cause: Real Chrome doesn't implement inverted-colors, so neither value should match, whatever the system settings.
What to do: This points to an engine-level problem rather than a configuration one, since Chromium does not expose it. Report it to the tool's vendor.
Everything is default but something still looks off
Cause: The accessibility preferences are probably not the issue. Defaults are what you want for most profiles.
What to do: Review other signals: TLS fingerprinting, canvas consistency, WebGL parameters. Accessibility queries matter mostly in combination with other mismatches.
Next Steps
Accessibility media queries are one piece of the system-preferences surface. Related areas worth understanding:
- Colour-gamut and HDR media queries — covered in color-gamut HDR media query fingerprinting, distinct from accessibility but similar in mechanism
- Navigator.deviceMemory and hardwareConcurrency — hardware signals that describe the same machine
- Screen resolution and DPR — another place where values should agree
For ad-verification and click-quality work, ClickzProtect can help you analyse the traffic arriving at your own campaigns.
Canvas and WebGL get the attention, but small details like these are where a profile can quietly carry your own machine's preferences. Check them once, and again whenever the host's settings change.
Frequently Asked Questions
How much entropy do accessibility media queries add to a browser fingerprint?
Less than you might think per query: a two-state query can carry at most one bit, prefers-contrast's four states at most two, and in practice far less, because most people keep the defaults. Combined, the five major accessibility queries (prefers-reduced-motion, prefers-contrast, forced-colors, prefers-reduced-transparency, inverted-colors) still add to the total, and fingerprinting is cumulative: every bit narrows the population. Users with non-default accessibility settings are already in smaller groups, which makes these queries especially identifying for them.
Why do fingerprinting libraries read accessibility media queries?
Because they are cheap to read and they have to agree with the rest of the picture. Some states exist only on certain platforms: forced-colors is effectively a Windows feature, and inverted-colors is supported by Safari but not by Chrome. The open-source FingerprintJS library collects several of these values and CreepJS displays them, so an impossible combination is visible to anyone who looks.
Should a profile use non-default accessibility values?
Only if you need them. Non-default accessibility settings make a browser stand out. Most users keep every accessibility preference at its default, so a profile with default values is the common case. The exception is when you are testing accessibility features or building for users who rely on them.
Can a website read accessibility settings without asking?
Yes. Media queries need no permission: any page can evaluate them in CSS or with matchMedia, and the answer reflects the OS setting the browser passes through. That is what makes them useful for accessibility, and also readable for fingerprinting.
Try JustBrowser
A multi-account browser for teams, built on a custom Chromium engine with native C++ integration, not an extension. Each profile is its own browser with its own cookies, storage, proxy and 40+ identity parameters, and teammates can share profiles. Local REST API and CDP for Playwright, Puppeteer, Selenium. Windows x64 and macOS (Apple Silicon). 7-day free trial, card required — then $9.99/month or $99.99/year, unlimited profiles, free team seats.
Get started → · How it differs from Multilogin / GoLogin / AdsPower
Ready to manage multiple accounts?
Seven days free, then $9.99/month — one plan, everything included.