Skip to content
Anti-Bot

How Browser Fingerprinting Works

Pim

Pim · Scrappey Research

May 31, 2026 5 min read

What Is Browser Fingerprinting Evasion? — conceptual illustration
On this page

Browser fingerprinting is how a site combines signals — canvas, WebGL, audio, fonts, navigator probes, TLS (the encryption layer behind https, which has its own identifying pattern) — into a single identifier for a browser. A fingerprint is the combined set of these signals, which together can identify one browser. For an automated browser used in authorized workflows on sites you own or are permitted to access, the practical concern is configuration consistency: an empty or contradictory fingerprint is itself unusual, while an internally consistent configuration that matches a real device behaves the way a normal browser would.

Quick facts

Surfaces to handleCanvas, WebGL, audio, fonts, navigator, screen, timezone, TLS, HTTP/2
Hardest constraintCross-surface consistency (Mac UA + Linux fonts = block)
Recommended toolsCamoufox, PatchRight, Brave, undetected-chromedriver
Anti-patternRandomizing each surface independently — produces impossible combinations
Rotation strategyWhole-profile rotation, not per-surface randomization

Why per-surface randomization fails

The obvious-but-wrong approach is to randomize each fingerprint surface on its own — a random canvas hash here, a random WebGL string there, a random font list. The problem is that these signals are not independent in real life, so random combinations produce a device that could not exist: a macOS user-agent paired with a Linux font set, an NVIDIA GPU string on a Mac screen aspect ratio, an Asia/Tokyo timezone with US English. Anti-bot models, trained on millions of real users, know these pairings never occur and flag them instantly. The disguise becomes the giveaway.

Runtime spoofing vs engine-level patching

The same fix can live at two different layers, and where it lives decides how well it holds up:

Runtime spoofingEngine-level patching
How it worksJS injected at page load overrides properties / methodsC++ source of Chromium / Firefox is patched and rebuilt
Examplespuppeteer-extra-stealth, undetected-chromedriver, selenium-stealthCamoufox, CloakBrowser, PatchRight (patches at Playwright source)
Defeats toString check?No — the patch is a JS function, visible via Function.prototype.toString()Yes — the override happens below the JS layer, so toString still returns "[native code]"
Setup costnpm installBinary download (Camoufox/CloakBrowser) or pip install (PatchRight)
MaintenancePlugin updates as detections changeTied to upstream Chromium/Firefox releases; weeks-to-months lag

Runtime spoofing means injecting JavaScript when the page loads to override the values a site reads. It is the cheap starting point and works fine against simpler vendors (Cloudflare Bot Fight Mode, Imperva, AWS WAF Common). Engine-level patching means editing and recompiling the browser's own C++ source so the fix sits below JavaScript, where detection scripts cannot see it. That deeper approach is what you need for Kasada, recent Akamai, Cloudflare Bot Management Enterprise, PerimeterX, and F5 Shape — see the vendor cheatsheet for which deployments fall in which category.

The real-profile-database approach

The hardest part of a consistent configuration isn't any individual signal — it's making them coherent, meaning they all fit together the way they would on one real machine. A browser claiming to be Chrome on Windows 11 with an NVIDIA renderer must also have the matching extension list, the matching AudioContext output for that OS, a timezone that matches the IP's location, and so on across dozens of signals. Spoofing each one by hand almost always produces a combination that doesn't add up.

The state-of-the-art fix is the real-profile database: collect tuples — bundles of values that belong together — of (UA, OS, GPU, audio, canvas, timezone, language, screen size, …) from real users at scale, then hand one whole tuple to each browser session. Camoufox bundles such a database (10k+ profiles); commercial anti-detect browsers like Multilogin and GoLogin maintain larger ones. Because each tuple was captured together from one real machine, every signal in it is automatically consistent.

The catch is novelty. Anti-bot vendors test against the same scraping tools and harvest their profile databases. A profile that's been published in Camoufox's corpus for six months may already be flagged. Refreshing the database is the real work — collecting profiles, rotating them out before they burn, and matching profile geography to proxy geography. This is why commercial anti-detect tools charge $50-200/month for the same idea Camoufox ships free: the operational cost of profile freshness, not the patching itself.

Whole-profile rotation

The right thing to rotate is a complete device profile, not one value at a time: a coherent set of (UA, fonts, GPU, screen, timezone, languages, TLS) that matches a real class of device. Tools like Camoufox ship with ready-made profile pools. If you build your own rotation, the generator has to respect which values go together — for example, a Windows + Chrome profile always carries the same set of installed fonts, the same TLS ciphersuite order (the fixed sequence of encryption options the browser offers), and the same audio context hash range.

What fingerprinting does not cover

A consistent static fingerprint is only one layer of how detection works. Behavioral signals — mouse movement, scroll velocity, how long you linger on a page — are judged separately. And IP reputation runs first: datacenter traffic is often handled differently before the page's JavaScript even loads. The static fingerprint is just one signal among several that systems weigh.

Code example

python
# Camoufox ships with whole-profile fingerprints, not per-surface randomization.
from camoufox.sync_api import Camoufox

with Camoufox(
    headless=False,
    humanize=True,
    fingerprint='windows-chrome-recent',
    proxy={'server': 'http://user:pass@residential:port'}
) as browser:
    page = browser.new_page()
    page.goto('https://target.com')

Related terms

Concept map

Concept map

How How Browser Fingerprinting Works connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Anti-Bot
Building map…

Frequently asked questions

Is consistent fingerprinting the same as stealth mode?

Not quite — stealth tools are one approach. They adjust the known defaults in Puppeteer and Playwright. A consistent browser configuration is broader and also involves whole-profile rotation, behavioral realism, and matching transport-layer (network/TLS) fingerprints.

How often should I rotate fingerprints?

Per session, not per request. A real user keeps the same fingerprint for an entire visit, so changing it mid-session is itself a tell.

Can I use a real Chrome profile instead of patching?

Yes — driving real Chrome with a real user profile over CDP (the Chrome DevTools Protocol, the channel used to control the browser) avoids most patch-detection tells. The tradeoff is operational: managing real profiles at scale is hard, and you still need residential IPs and behavior emulation.

Should I always pick engine-level over runtime patching?

No — runtime patching is cheaper to deploy and is enough against roughly 80% of targets. Decide by testing, not by reputation: start with runtime (undetected-chromedriver or puppeteer-stealth plus a residential IP), measure your block rate, and move up to engine-level only if blocks exceed your budget. Reaching for Camoufox or CloakBrowser on an unprotected site just burns extra compute.

Why don't the engine-level tools just ship every browser version?

Forking Chromium or Firefox for every release is expensive. Camoufox tracks ESR Firefox; CloakBrowser tracks stable Chromium with a few weeks of lag. That lag is itself a fingerprint — a request claiming to be Chrome 134 from a tool actually running Chrome 131 has a mismatch between the User-Agent and the real engine, which sophisticated detection can catch.

Last updated: 2026-05-31