JustBrowser
Tutorials13 min read

Accessibility Media Query Fingerprinting: 5 CSS Vectors That Expose You (2026)

JustBrowser Platform Team·
prefers-reduced-motionmedia-query-fingerprintingaccessibility-fingerprintantidetect-browserbrowser-detectionbuildinpublicsaasstudioaiworkforcebuildwithclaude

I found out about this fingerprinting vector the embarrassing way.

Running an A/B test across 20 profiles last month, checking conversion funnel behavior across different geo-proxies. Everything looked clean — canvas hashes varied, WebGL matched the claimed GPUs, TLS fingerprints were native. CreepJS gave me 95%+ trust scores on all of them. I felt pretty clever, honestly.

Then one profile got soft-banned from a testing platform. Same proxy tier as the others. Same warm-up routine. But this one I'd configured on my personal Mac, where I have "Reduce motion" enabled because animated interfaces give me headaches. (Yes, I know. Operational security fail.)

The profile inherited that setting. Twenty browser profiles pretending to be different people across three continents — and one of them shared my actual accessibility preference. That's a linking signal. That's me being an idiot.

Accessibility media queries are the fingerprinting vectors nobody talks about. While everyone's focused on canvas and WebGL (rightfully so — check the WebGL fingerprinting deep-dive if you haven't), these CSS features quietly expose your OS-level settings to any page you visit. No permission prompt. No user consent. Just a few lines of CSS or JavaScript, and a site knows whether you've enabled reduced motion, high contrast, inverted colors, or reduced transparency.

What We're Building

By the end of this tutorial, you'll understand:

  1. Which accessibility media queries exist and what they expose
  2. How detection services use them for fingerprinting and consistency checks
  3. How to query your current profile's values
  4. How to configure antidetect profiles with coherent, realistic preference sets
  5. Which mismatches trigger detection flags

You'll need a browser profile to test — JustBrowser the seven-day trial works, or whatever antidetect tool you're using. We'll verify results against CreepJS and BrowserLeaks.

Prerequisites

  • Basic understanding of CSS media queries
  • An antidetect browser with profile configuration access
  • Familiarity with browser fingerprinting concepts (the antidetect browser myths debunked post covers fundamentals)
  • 20 minutes

Step 1: The Five Accessibility Media Queries

CSS Level 5 Media Queries introduced several features that let websites adapt to user preferences. Sounds helpful. It is helpful — for users who need it. But every adaptation point is also a detection 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. macOS's "Increase contrast" does too.

forced-colors

Indicates the browser is enforcing a limited color palette (like Windows High Contrast). Values: none or active.

const forcedColors = window.matchMedia('(forced-colors: active)').matches;

This one's binary and platform-specific. Almost exclusively a Windows signal — when you see forced-colors: active, you're looking at a Windows machine with High Contrast enabled. A macOS profile reporting this? Impossible. Red flag.

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 colors are inverted. Values: none or inverted.

const inverted = window.matchMedia('(inverted-colors: inverted)').matches;

Here's the thing — this query only returns meaningful results on Safari/WebKit. Chrome on macOS doesn't report system-level color inversion through this query. So if you're spoofing a Chrome profile and it reports inverted-colors: inverted, something's wrong. I spent an hour confused by this before reading the spec closely. An hour I'll never get back, which is why I'm writing it down here so you don't have to.

Step 2: Why These Matter for Fingerprinting

Each of these queries adds entropy to your fingerprint. Not massive entropy — we're talking 1-3 bits per query — but fingerprinting is cumulative. Every bit helps narrow the population.

More importantly: these queries create consistency requirements.

The issue isn't that prefers-reduced-motion: reduce makes you trackable. It's that prefers-reduced-motion: reduce on a profile claiming to be a fresh Windows 11 install with default settings makes you detectable. Default Windows doesn't have reduced motion enabled. Most users don't touch these settings. When your "ordinary user" profile has three accessibility features enabled, it looks suspicious.

Detection services check for these contradictions. CreepJS examines whether your accessibility preferences match your claimed platform. FingerprintJS uses preference combinations as part of their confidence scoring. I've seen profiles fail consistency checks purely on accessibility mismatches — green across canvas and WebGL, but red on preference coherence.

The math isn't hard. About 3-5% of users have prefers-reduced-motion: reduce enabled. Maybe 1-2% have prefers-contrast: more. The intersection — users with both enabled — is under 0.5%. Put someone in that 0.5% bucket, and you've narrowed them from "any of 8 billion humans" to "any of 40 million humans." Add a few more signals and you're uniquely identified.

This annoys me, if I'm honest. Accessibility features exist to help people. Using them for fingerprinting feels grimy. But here we are.

Step 3: Checking Your Profile's Current Values

Before configuring anything, audit what your profile currently reports. Open dev tools 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. If you see multiple (like both reduce and no-preference for the same query), something's broken in your spoofing layer.

For a "default user" profile, you want:

  • prefers-reduced-motion: no-preference
  • prefers-contrast: no-preference
  • forced-colors: none
  • prefers-reduced-transparency: no-preference
  • inverted-colors: none

That's the 95% case. Match the majority.

Step 4: Platform-Specific Constraints

Not every preference state is valid on every OS. This is where naive spoofing gets caught.

Windows constraints:

  • forced-colors: active is Windows-specific. Valid.
  • inverted-colors: inverted doesn't work in Chrome/Edge on Windows (the API exists but always returns none). If you're spoofing Chrome on Windows and this returns inverted, you've created an impossible browser.

macOS constraints:

  • inverted-colors: inverted only works in Safari. Chrome on macOS returns none regardless of system settings.
  • forced-colors: active isn't a thing on macOS. If your Mac profile reports it, instant flag.

Linux constraints:

  • Most desktop environments don't expose these preferences consistently. Default values across the board is the safest assumption.

The pattern: match the real behavior of the real OS and real browser. A Chrome Windows profile should have the exact preference behavior of Chrome on Windows — not Chrome on macOS, not Safari anywhere. Native antidetect engines handle this automatically because they're running actual Chromium builds with correct platform behavior. Extension-based tools often miss it.

I've tested maybe a dozen antidetect browsers at this point. Half of them get this wrong. It's frustrating. (Our JustBrowser vs Multilogin comparison covers engine-level differences in detail.)

Step 5: Configuring JustBrowser Profiles

JustBrowser's native Chromium engine handles accessibility preferences at the C++ level, which means they're coherent with the rest of the platform fingerprint by default. But here's how to verify and customize.

In your profile settings, accessibility preferences are grouped under the system preferences section. For a standard "blend-in" profile:

  1. Set all accessibility preferences to their platform defaults
  2. Verify OS setting matches the claimed platform (Windows → Windows defaults, etc.)
  3. Run the query audit script from Step 3 to confirm

For specialized testing (accessibility QA, research personas with specific needs):

  1. Enable the specific preference you need
  2. Make sure other fingerprint signals match a user who would have that preference — for instance, prefers-reduced-motion: reduce correlates with certain browser usage patterns
  3. Verify against CreepJS that no contradictions appear

The key insight: JustBrowser generates these preference values as part of the coherent fingerprint set, not as isolated overrides. When you set a profile to "Windows 11 / Chrome 146 / Default user," the accessibility queries return what that exact configuration would return on a real machine. No manual alignment needed.

For profiles where you've customized the OS or locale, double-check the accessibility values with the audit script. The 40+ identity parameters include these media query responses, but edge-case configurations warrant verification. If you're automating tests programmatically, the REST API for Playwright and Puppeteer exposes these preference values per profile.

Step 6: Testing Against Detection Services

Run your profile through these tests:

CreepJS (abrahamjuliot.github.io/creepjs)

Look for the CSS section. It reports detected media query values and flags inconsistencies. A clean result shows your preferences match the claimed platform. Any "lie detected" here related to system preferences means your profile's accessibility settings contradict other fingerprint signals.

BrowserLeaks CSS (browserleaks.com/css)

Shows all media query matches including accessibility features. Useful for seeing the raw values without interpretation. Cross-reference against your expected configuration.

IPHey and Pixelscan

These check broader consistency but do examine preference coherence. If you're passing CreepJS and BrowserLeaks but failing these, the issue is probably elsewhere — timezone/proxy mismatch is more common. But accessibility preferences do feed into their scoring.

The CreepJS test walkthrough covers interpreting results in detail. For this specific fingerprinting vector, focus on the CSS/media section of the report.

Common Errors and Fixes

Error: CreepJS shows "prefers-reduced-motion mismatch"

Cause: Your profile's motion preference doesn't match your machine's actual setting, and the detection isn't being applied at the right level.

Fix: In extension-based antidetect tools, this happens because JavaScript overrides can't intercept CSS media query evaluation. The CSS level still sees the real value. Native engine antidetect browsers (like JustBrowser) handle this at the rendering engine level. If you're stuck on an extension-based tool, you may need to change your actual OS setting to match the profile — which defeats the purpose. Consider switching tools.

Error: Profile claims macOS but shows forced-colors: active

Cause: Copy-pasted settings from a Windows profile template without adjusting platform-specific values.

Fix: Reset accessibility preferences to macOS defaults. forced-colors should always be none on macOS profiles. If your antidetect tool doesn't let you set this explicitly, it might be inheriting from your host system — another argument for using a tool that isolates completely.

Error: inverted-colors returns a value in Chrome profile

Cause: On real Chrome installations, inverted-colors queries always return none regardless of system settings (Chrome doesn't implement this feature). If your profile returns inverted, you're running something that isn't behaving like real Chrome.

Fix: This usually indicates an underlying engine problem rather than a configuration issue. Real Chromium doesn't expose this. If your tool claims to be Chromium-based but returns inverted, the engine is lying about something fundamental. Report the bug or switch tools. Probably switch tools — I've yet to see a bug report fix this kind of thing quickly.

Error: All values default but still getting flagged

Cause: The accessibility preferences aren't the problem — something else is. Default values are what you want for most profiles.

Fix: Audit other fingerprint vectors. Check TLS fingerprinting, canvas consistency, WebGL parameters. Accessibility queries are usually caught in consistency checks when combined with other mismatches, not flagged in isolation when they're at defaults.

Next Steps

Accessibility media queries are one piece of the system-preferences fingerprinting surface. Related vectors worth understanding:

  • Color-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 should match your claimed device
  • Screen resolution and DPR — screen resolution mismatch issues covers this vector

For click fraud protection and ad verification workflows where you're running multi-geo profiles, these subtle signals matter more than you'd expect. ClickzProtect can help verify that the traffic you're analyzing isn't itself spoofing accessibility signals to evade detection.

The profiles that survive long-term are the ones with internally consistent fingerprints. Canvas and WebGL get the attention, but accessibility preferences are the details that separate careful operators from detectable ones. A profile claiming to be a Windows developer machine with every accessibility feature enabled? Nobody does that. A profile claiming to be default-everything? Believable. Boring. Undetectable.

Blend in. Don't stand out. Be nobody special. (I know, it's not great life advice. But for browser profiles? It works.)

Frequently Asked Questions

How much entropy do accessibility media queries add to a browser fingerprint?

Each media query adds 1-3 bits depending on the number of states. Combined, the five major accessibility queries (prefers-reduced-motion, prefers-contrast, forced-colors, prefers-reduced-transparency, inverted-colors) can contribute 5-10 bits of entropy. That doesn't sound like much, but fingerprinting is cumulative — every bit narrows the population. Users with non-default accessibility settings are already in smaller groups, making these queries especially identifying for them.

Why do detection services check accessibility media queries?

Because mismatches reveal spoofing. If your profile claims to be Windows 11 but reports inverted-colors: inverted (a macOS-only feature), that's an impossible configuration. Detection services like CreepJS and FingerprintJS cross-validate these values against the claimed OS and browser. Inconsistent accessibility preferences are treated as lie signals, often weighted more heavily than simpler fingerprint mismatches.

Should I spoof accessibility media queries to non-default values?

No — unless your profile specifically requires it. Non-default accessibility settings make you stand out, not blend in. About 95% of users have all accessibility preferences at their default values. Spoofing to reduced-motion or high-contrast puts you in a 5% minority. The goal is matching real browser populations, and real browser populations mostly have these features off. The exception: if you're testing accessibility features or simulating a specific user persona.

Can websites detect if accessibility media queries are being spoofed?

Yes, through consistency checks. If your profile reports prefers-reduced-motion: reduce but still runs CSS animations without respecting the preference, that's detectable. If forced-colors: active is set but the page renders with full color instead of the forced palette, the mismatch is visible. Detection services also check whether the reported values are valid for the claimed OS — some states only exist on specific platforms.


Try JustBrowser

Native Chromium antidetect browser — not extension-based. Real C++ engine patches at the canvas / WebGL / font / TLS layer, so 40+ identity parameters are genuine, not faked. REST API for Playwright, Puppeteer, Selenium. 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.

We'd like to use Google Analytics, a Google service, to understand how our website is used. It sets two cookies in your browser and runs only if you click Accept. You can change your choice at any time with Cookie settings. Cookie Policy

Sign-in cookies and the cookie that remembers this choice are always on; the website needs them to work.

Google Analytics, a Google service, helps us understand how our website is used. It sets two cookies, _ga and _ga_TVZHQ99TZW. It is now onoff in this browser. If your browser sends a Global Privacy Control or Do Not Track signal, it stays off. Cookie Policy