Scrapeless Wiki

What Is CSS Fingerprinting? – Definition and How It Works

Informational P3 what is css fingerprinting

Learn how media queries, feature support, and font metrics fingerprint a browser without any JavaScript at all.

CSS fingerprinting extracts identifying information using stylesheets alone. Its defining property is that it works with JavaScript disabled.

1. How It Works Without JavaScript

The trick is conditional resource loading. A CSS rule that only applies under some condition can request a background image, and the server observes which images were requested:

@media (min-width: 1920px) {
  body { background-image: url("/probe?w=1920"); }
}
@media (prefers-color-scheme: dark) {
  body { border-image: url("/probe?dark=1"); }
}
@supports (backdrop-filter: blur(1px)) {
  body { list-style-image: url("/probe?backdrop=1"); }
}

Each request that arrives tells the server that the corresponding condition was true. Enough probes reconstruct a detailed profile with no script execution at all.

2. What Can Be Probed

Technique Reveals
@media width/height Viewport and screen dimensions
prefers-color-scheme Dark or light preference
prefers-reduced-motion Accessibility preference
resolution / device-pixel-ratio Display scaling
pointer / hover Input capability β€” touch versus mouse
@supports Feature support, implying engine and version
font-family fallback Which fonts are installed
-webkit-/-moz- prefixes Engine family
@media (scripting: none) Whether JavaScript is enabled

3. Font Detection Without JavaScript

A classic technique: render text in a candidate font with a distinctive fallback, and use the difference in rendered width to reveal whether the font exists.

Done in pure CSS via conditional rules keyed on layout differences, it enumerates installed fonts β€” historically one of the highest-entropy signals available, because font inventories vary by OS, locale, and installed software.

4. Why It Matters for Automation

Two implications, in opposite directions.

Disabling JavaScript does not make you anonymous. A common assumption is that a script-free client is unfingerprintable. CSS probing defeats that, and @media (scripting: none) even detects the absence of scripting directly β€” which is itself unusual and therefore a signal.

A headless browser's CSS environment is often default. No unusual fonts, a default colour scheme preference, no accessibility preferences set, and a pointer capability that may contradict the claimed device. Real users' browsers carry the accumulated idiosyncrasy of a real installation.

5. The Reduced-Motion and Colour-Scheme Signals

prefers-reduced-motion and prefers-color-scheme are set by the operating system. A container's defaults are predictable β€” usually light scheme and no reduced-motion preference.

Real populations are mixed: a substantial share of users run dark mode, and a meaningful minority have reduced motion enabled. Uniform defaults across a fleet of sessions is a weak but real pattern.

6. Fonts Are the Highest-Value Part

A minimal container image ships almost no fonts. That produces two observable effects:

  • Font enumeration returns a tiny set, unlike any consumer machine.
  • Text renders in fallback fonts, which changes layout and, in screenshots, appearance.

Installing a realistic font set in the container addresses both, and it also fixes the more mundane problem of text rendering as boxes in screenshots.

7. Practical Guidance

  1. Install fonts in any container running a browser β€” for rendering correctness as much as fingerprinting.
  2. Do not assume no-JavaScript equals unfingerprintable.
  3. Vary colour-scheme and motion preferences across a fleet if uniformity is a concern.
  4. Keep pointer and hover capability consistent with the claimed device class.
  5. Prefer a full browser profile over a stripped one; stripped environments are distinctive.

8. Summary

CSS fingerprinting uses conditional rules that load resources only when a condition holds, letting a server profile viewport, colour scheme, accessibility preferences, feature support, input capability, and installed fonts without executing any JavaScript.

It defeats the assumption that a script-free client is anonymous β€” @media (scripting: none) even detects that state directly β€” and a container's sparse font set and default preferences are its most visible tells, so install real fonts and vary the preferences.