Browser Fingerprinting Explained: Surfaces, Detection, and Research

Browser fingerprinting is the practice of collecting a set of browser and device attributes — without cookies — to build a statistically unique identifier that can track or classify a visitor across sessions.

Understanding fingerprinting is essential for privacy researchers, security engineers, QA teams building detection-aware test suites, and developers who want to know what signals their applications inadvertently expose.


What Is Browser Fingerprinting?

When you load a webpage, your browser answers dozens of implicit questions: What fonts are installed? How does your GPU render a specific gradient? What is your screen resolution? What language settings does your OS report? Individually, each answer is shared by many users. Combined into a vector, they form a fingerprint that identifies the specific browser-device-OS combination with high statistical accuracy.

Unlike cookies, fingerprints require no storage on the client. They are reconstructed from signals that browsers expose as part of normal operation, making them persistent across incognito windows, cookie clears, and VPN changes. A 2014 EFF study found that 84% of browsers in their dataset produced a unique fingerprint from a 22-attribute combination alone.


Fingerprint Surfaces

Canvas Fingerprinting

The HTML <canvas> element renders text and shapes using the GPU and OS font renderer. Subtle differences in antialiasing, subpixel rendering, color profile, and font hinting produce pixel-level variation between environments. A fingerprinting script draws an off-screen canvas, reads the pixel data with toDataURL(), and hashes the result. The hash is stable for the same device and differs across OS, GPU, and driver combinations.

Canvas fingerprinting is one of the most widely deployed techniques because it requires no browser permissions and produces a highly unique value — typically stable for months unless the GPU driver or OS font configuration changes.

WebGL Fingerprinting

WebGL exposes two highly identifying strings accessible via JavaScript:

Beyond strings, floating-point rendering precision tests — drawing specific geometric shapes and reading back the pixel values — produce device-specific numeric outputs tied to GPU arithmetic implementation. These numeric fingerprints are especially stable across browser updates.

TLS and JA3/JA4 Fingerprinting

Before any HTML loads, the browser and server perform a TLS handshake. The ClientHello message contains:

The JA3 algorithm hashes these fields into a 32-character hexadecimal string. Different browser-OS combinations produce different JA3 hashes, and the hash is visible to any network observer — including CDN-level bot detectors — before a single line of page JavaScript executes.

JA4 is a newer, more structured specification that encodes TLS version, cipher count, extension count, ALPN, and other fields in a human-readable, sortable format. It is designed to be more resilient to minor version shuffles while still reliably distinguishing major browser and OS families from one another.

Font Fingerprinting

JavaScript has no direct API to enumerate installed fonts. However, scripts measure text rendered in a test font versus a fallback font using either <canvas> pixel output or DOM element width. If the measured width matches the test font’s expected metric, the font is present. The resulting detected-font list is highly OS-specific: Windows 11, macOS Sonoma, and Android 14 carry substantially different default font sets.

Additional Fingerprint Surfaces

SurfaceAPI or MechanismWhat It Reveals
Screen and viewportscreen.width, window.innerWidthPhysical display + browser chrome size
TimezoneIntl.DateTimeFormat().resolvedOptions()OS timezone setting
Languagenavigator.language, Accept-Language headerOS and browser locale
Touch supportnavigator.maxTouchPointsMobile vs. desktop hardware
Battery statusnavigator.getBattery()Charge level and charging state
CPU coresnavigator.hardwareConcurrencyProcessor core count
Memorynavigator.deviceMemoryRAM bucket (0.25 to 8 GB)
Audio contextOfflineAudioContext rendering hashDSP and audio driver variation
Sensor APIsDeviceMotion, DeviceOrientationPhysical sensor presence or absence
Connection typenavigator.connection.effectiveTypeNetwork class (4G, wifi, etc.)
Media devicesnavigator.mediaDevices.enumerateDevices()Camera and microphone hardware IDs

How Bot Detection Uses Fingerprinting

Commercial detection platforms combine passive and active fingerprinting into a multi-layer classification pipeline:

  1. Passive collection — TLS/JA3 at the edge, HTTP header order and casing, IP reputation and ASN classification.
  2. Active JavaScript probes — Canvas hash, WebGL renderer and precision tests, font detection, audio context hash, timing measurements.
  3. Consistency cross-checks — A request claiming to be mobile Safari on iOS that produces a Windows WebGL renderer string, a desktop JA3 hash, and zero touch points is inconsistent. Inconsistency scores are the primary classification signal, not any individual attribute.
  4. Behavioral analysis — Mouse movement entropy, scroll velocity distributions, event timing cadence, inter-keystroke intervals.
  5. Environmental tells — Presence of navigator.webdriver, CDP artifact properties (window.cdc_*), headless browser indicators (navigator.plugins.length === 0, missing window.chrome object).

The important insight for researchers is that no single signal classifies a session as automated. Detection systems score the coherence of the entire attribute vector. An inconsistency between any two correlated signals — UA vs. GPU, JA3 vs. declared OS, touch points vs. mobile viewport — raises the suspicion score.


How Researchers Study Browser Fingerprinting

Security and privacy researchers use controlled, instrumented environments to map which signals sites collect and how detection logic responds to deliberate variation. A typical research workflow:

  1. Baseline capture — Record a complete fingerprint from a known clean device with no automation tooling.
  2. Controlled variation — Modify one signal at a time (e.g., change only the canvas hash by adjusting GPU driver settings) and observe how the classification outcome changes.
  3. Network-layer capture — Record TLS ClientHello packets alongside JavaScript-layer signals using a proxy (mitmproxy, Wireshark) to map the full collection surface across both layers.
  4. Cross-environment comparison — Compare desktop, emulated mobile, and Android-native fingerprints side by side to identify which signals differ and by how much.

Open-source tools used in this work include FingerprintJS (browser-side attribute collection), mitmproxy (TLS inspection), and automation frameworks that run inside genuine OS environments to produce unpatched baseline fingerprints.


How Damru Fits

Damru provides a containerized Android environment (Redroid) driven by Playwright over CDP. Because the browser runs on a real Android OS, every fingerprint signal is authentic by default — the TLS stack, GPU renderer, touch APIs, and sensor feeds all originate from the Android layer rather than from JavaScript overrides applied to a desktop binary.

For fingerprinting researchers, this means Damru can establish a clean, unpatched Android baseline and then allow controlled modification of individual signals to study how detection systems respond. Each Redroid container session is isolated, reproducible, and scriptable through Python.

pip install damru
import asyncio
from damru import AsyncDamru

async def collect_fingerprint_baseline():
    async with AsyncDamru(device_profile="pixel_7a") as browser:
        page = await browser.new_page()
        await page.goto("https://your-research-endpoint.example.com")

        # Collect the canvas hash from a genuine Android environment
        canvas_output = await page.evaluate("""() => {
            const c = document.createElement('canvas');
            const ctx = c.getContext('2d');
            ctx.fillStyle = '#f60';
            ctx.fillRect(125, 1, 62, 20);
            ctx.fillStyle = '#069';
            ctx.font = '11pt Arial';
            ctx.fillText('Damru baseline', 2, 15);
            return c.toDataURL();
        }""")

        webgl_renderer = await page.evaluate("""() => {
            const gl = document.createElement('canvas').getContext('webgl');
            const ext = gl.getExtension('WEBGL_debug_renderer_info');
            return gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
        }""")

        print("Canvas (first 80 chars):", canvas_output[:80])
        print("WebGL renderer:", webgl_renderer)  # Adreno renderer, not desktop GPU

asyncio.run(collect_fingerprint_baseline())

Running this inside Damru captures genuine Android canvas and WebGL output, giving researchers a real-device baseline to compare against emulated or patched environments — a comparison that would be impossible on a desktop Chromium binary regardless of how many JavaScript patches are applied.

To capture baselines across many device profiles at once, spin up a fleet of Android workers and watch any one of them live from the Damru instance manager.


FAQ

What is the most identifying browser fingerprint signal? Canvas and WebGL fingerprints are among the most unique individual signals because they reflect the specific combination of GPU hardware, driver version, and OS font renderer. Combined with the TLS JA3 hash — which is collected before JavaScript runs — they form a highly stable cross-session identifier that persists through cookie clears and incognito mode.

Can browser fingerprinting work in incognito or private browsing mode? Yes. Fingerprinting does not use cookies or local storage, so private mode does not prevent it. The browser still exposes the same GPU renderer, font set, screen dimensions, and TLS stack in incognito mode as it does in a regular session.

What is the difference between JA3 and JA4 fingerprinting? JA3 hashes specific TLS ClientHello fields into a single MD5 string. JA4 is a more structured successor that encodes TLS version, cipher count, extension count, ALPN protocol, and other fields in a human-readable, sortable format designed to remain stable across minor version shuffles while still reliably distinguishing major browser and OS families.

How is browser fingerprinting different from cookie-based tracking? Cookies require client-side storage that users can delete or block. Browser fingerprints are reconstructed from browser behavior on every page load and require no storage, making them persistent across cookie clears, incognito sessions, and even browser reinstalls — as long as the underlying hardware, OS, and driver configuration remain unchanged.