Browser fingerprinting still works in 2026, but the most useful techniques have shifted. Canvas, WebGL, and AudioContext remain partial signals; reduced browser APIs provide less entropy; and network-level fingerprints such as JA4 are generally more durable because page JavaScript cannot directly rewrite the TLS handshake.

It is not a durable cross-browser identity by itself, and no single fingerprint should be treated as proof that a visitor is human or automated. The strongest defensive use combines fingerprint consistency with behavior, request context, and high-confidence evidence such as decoy interactions.

The useful question is which observations remain available, stable, and relevant in the browser modes your visitors actually use. A privacy setting can change a result without the visitor being a bot. A bot can run the same browser engine as a human.

This guide separates documented API behavior from detection assumptions. It is a technical reference, not a benchmark claiming measured accuracy across every browser. For implementation, start with the evaluation checklist below.

The Scoreboard

The table summarizes what each technique can tell you and the main reason it can mislead. It does not assign universal entropy or accuracy scores; those require measurements from a defined population.

TechniqueUseful observationMain limitation
User-Agent and platformClaimed browser family, major version, and platformReduced detail; claims can be changed
navigator.pluginsStandard PDF-viewer compatibility informationNot a list of uniquely installed plugins
CanvasRendering output for a specific scenePrivacy protections can modify readback
WebGLAvailable graphics capabilities and rendering outputExtensions can be hidden; software rendering is not proof of automation
OfflineAudioContextBrowser audio-processing outputDoes not require a physical audio device
Fonts and screen propertiesAvailable layout and display characteristicsShared configurations and restricted APIs reduce distinctiveness
Client HintsBrowser-supplied client information where supportedAvailability and permitted detail vary
TLS fingerprint (JA4)Characteristics of the TLS client seen at the observation pointMany clients share values; handshakes can be imitated
HTTP/2 settingsConnection-level client configurationShared stacks and intermediaries complicate attribution
TCP/IP characteristicsNetwork-stack behavior at the observerNetwork path and proxies affect interpretation

Reduced Browser APIs

User-Agent String

The User-Agent string was the original fingerprinting signal. For two decades, browsers sent increasingly detailed strings identifying the browser name, version, operating system, device type, and rendering engine.

Chromium reduced detailed version and platform information in stages. The browser major version remains useful context; the reduced fields are not a device identifier. The Chromium rollout and format reference documents the retained and replaced fields, including the alternative Client Hints interfaces.

A claimed browser family can still help check consistency against other observations. It should not become a block decision on its own.

Verdict: Low-detail context, with no assurance that a client is telling the truth.

These APIs once exposed information about installed plugins. Modern navigator.plugins is specified to return five standard compatibility entries when inline PDF viewing is supported, or an empty list otherwise. It is not always empty, and an empty list alone is not a headless-browser signature. See the MDN API reference.

Verdict: Keep only if the observed compatibility state contributes to a validated consistency check. Do not treat plugin count as a unique identity.

navigator.platform exposes a broad platform label. Values such as Win32 do not reliably describe the actual processor architecture. Where supported, Client Hints offer a separate interface for requesting additional client information; support and permitted values must be checked.

Verdict: A compatibility hint, not a hardware inventory or an authenticated platform claim.

What’s Degraded but Usable

Canvas Fingerprinting

Canvas fingerprinting works by drawing a complex scene using the HTML5 Canvas API and reading back the pixel data. Differences in GPU hardware, driver versions, font rendering, and anti-aliasing produce slightly different outputs across devices. The technique generates a hash of the rendered image that serves as a partial fingerprint.

Canvas readback needs to be evaluated by browser mode:

  • Firefox: Mozilla documents both known-fingerprinter blocking and protections for suspected fingerprinting. Private Browsing and Strict tracking protection enable the latter, including randomized canvas data. This is distinct from assuming every Firefox user enables privacy.resistFingerprinting. See Firefox’s protection documentation.
  • Safari: Advanced Fingerprinting Protection adds small changes to canvas readback. It is part of the enhanced Private Browsing protections and can also be enabled for regular browsing. Safari should not be described as having no meaningful canvas protection. See WebKit’s explanation.
  • Brave: Its documented randomization strategy varies selected outputs by site and session. This reduces cross-site linkability without necessarily disabling the API. See Brave’s fingerprinting defenses.
  • Chromium-based browsers: Test the specific browser, extensions, and settings you support; sharing an engine does not imply sharing the same privacy behavior.

The following example demonstrates readback, not uniqueness. Handle unavailable contexts and collection failures separately from successful observations.

// Basic canvas fingerprint
function getCanvasFingerprint() {
  const canvas = document.createElement('canvas');
  canvas.width = 256;
  canvas.height = 256;
  const ctx = canvas.getContext('2d');
  if (!ctx) return null;

  // Draw complex scene with text, gradients, curves
  ctx.textBaseline = 'top';
  ctx.font = '14px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(125, 1, 62, 20);
  ctx.fillStyle = '#069';
  ctx.fillText('Browser fingerprint', 2, 15);
  ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
  ctx.fillText('Browser fingerprint', 4, 17);

  // Add geometric shapes for GPU-dependent rendering
  ctx.beginPath();
  ctx.arc(50, 50, 50, 0, Math.PI * 2, true);
  ctx.closePath();
  ctx.fill();

  return canvas.toDataURL();
}

Verdict: A partial rendering signal. This article has no measured basis for an “80% of browsers” coverage claim; measure availability and stability on your traffic.

Font Enumeration

Font fingerprinting measures which fonts are installed by rendering text in specific typefaces and detecting whether the browser fell back to a default. The combination of available fonts was once highly identifying because users install different font sets based on their applications (designers have Adobe fonts, developers have monospace collections, etc.).

Browser restrictions and shared font configurations limit how identifying this can be. Loading a web font does not, by itself, prevent a script from probing system fonts. Access also depends on the collection method and browser protections.

Verdict: A supporting layout observation. Test the permitted font surface on each browser and avoid inferring a person from an apparent font match.

Screen and Display Properties

screen.width, screen.height, screen.colorDepth, window.devicePixelRatio, and related properties still work and still vary across devices. But the entropy is minimal because the market has consolidated around a handful of common resolutions and display configurations.

A 1920x1080 display at 1x pixel ratio describes tens of millions of devices. A 2560x1440 at 1.25x narrows it down, but not by much. These properties are also trivially spoofed by automation frameworks. Playwright and Puppeteer set arbitrary viewport sizes as a one-line configuration.

Verdict: Low entropy. Easy to spoof. Include in a composite fingerprint but don’t rely on it.

What Still Works

WebGL Fingerprinting

WebGL fingerprinting is the quiet workhorse of modern fingerprinting. It operates on two levels:

Level 1: Parameter enumeration. The WebGL API exposes hardware and driver information through getParameter() and getExtension() calls. The renderer string (WEBGL_debug_renderer_info) reveals the GPU model and driver:

function getWebGLFingerprint() {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl');
  if (!gl) return null;

  const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');

  return {
    vendor: gl.getParameter(gl.VENDOR),
    renderer: gl.getParameter(gl.RENDERER),
    unmaskedVendor: debugInfo
      ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)
      : null,
    unmaskedRenderer: debugInfo
      ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
      : null,
    maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
    maxViewportDims: gl.getParameter(gl.MAX_VIEWPORT_DIMS),
    extensions: gl.getSupportedExtensions(),
    shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION),
  };
}

The unmasked renderer string alone provides substantial entropy. ANGLE (NVIDIA GeForce RTX 4070 Ti Direct3D11 vs_5_0 ps_5_0) identifies a specific GPU model. Combined with max texture size, supported extensions, and shader precision formats, WebGL creates a detailed hardware profile.

Level 2: Render output. Drawing a complex 3D scene with WebGL and reading back the pixels produces GPU-dependent output, similar to canvas fingerprinting but with higher variability because 3D rendering pipelines differ more across GPU architectures than 2D rendering.

Availability matters: the WEBGL_debug_renderer_info extension can be unavailable under privacy settings. Firefox disables it when privacy.resistFingerprinting is enabled. Code should handle a missing extension normally. See MDN’s extension reference.

A renderer string such as SwiftShader describes software rendering. It does not establish that a visitor is a bot: graphics configuration and fallback behavior need context. Equally, a bot can run real Chromium with hardware acceleration. Chrome documents that its modern headless and headful modes share an implementation.

Verdict: Useful graphics context and consistency evidence. Neither a renderer name nor missing WebGL is a sufficient automation verdict.

AudioContext Fingerprinting

An OfflineAudioContext renders an audio graph into a buffer without playing it through a physical output device. Differences in implementation and processing can contribute a signal, but the result should not be described as a direct sound-card or speaker fingerprint. See the API reference.

This example computes a summary of a rendered buffer. Repeated values do not establish a unique device.

function getAudioFingerprint() {
  return new Promise((resolve) => {
    const context = new OfflineAudioContext(1, 44100, 44100);
    const oscillator = context.createOscillator();
    oscillator.type = 'triangle';
    oscillator.frequency.setValueAtTime(10000, context.currentTime);

    const compressor = context.createDynamicsCompressor();
    compressor.threshold.setValueAtTime(-50, context.currentTime);
    compressor.knee.setValueAtTime(40, context.currentTime);
    compressor.ratio.setValueAtTime(12, context.currentTime);
    compressor.attack.setValueAtTime(0, context.currentTime);
    compressor.release.setValueAtTime(0.25, context.currentTime);

    oscillator.connect(compressor);
    compressor.connect(context.destination);
    oscillator.start(0);

    context.startRendering().then((buffer) => {
      const data = buffer.getChannelData(0);
      // Sum a slice of samples as the fingerprint
      let sum = 0;
      for (let i = 4500; i < 5000; i++) {
        sum += Math.abs(data[i]);
      }
      resolve(sum);
    });
  });
}

A headless environment can implement offline audio processing without physical audio hardware. An unavailable context or an unexpected value is therefore not proof of automation. Privacy settings can also alter exposed outputs.

Verdict: Another processing observation to evaluate alongside other signals. Measure whether it adds useful information before collecting it in production.

TLS Fingerprinting (JA4)

JA4 summarizes features of a TLS ClientHello. Collection happens at a server, proxy, or edge that can observe the handshake, rather than through page JavaScript. The FoxIO JA4 repository documents the format and implementations.

Page JavaScript cannot directly set the handshake parameters of its browser. The client operator can, however, use a different network stack or an implementation that imitates another client. Automated and human-driven copies of the same browser can share a JA4 value. A TLS-terminating intermediary can also change which client your origin observes.

Use JA4 to group observations and investigate inconsistencies with claimed clients. It does not identify an individual, prove use of Playwright, or establish which model powers an agent.

To inspect a value, use the JA4 lookup and decoder. For collection and detection design, read the JA4 implementation guide.

Verdict: Useful network context with shared values and evasion limits. Evaluate it with request behavior rather than treating it as a universal block key.

HTTP/2 Settings Fingerprinting

When a client establishes an HTTP/2 connection, it sends a SETTINGS frame containing parameters like initial window size, max concurrent streams, header table size, and enabled push. Different HTTP client implementations choose different defaults.

Like TLS fingerprinting, HTTP/2 settings are determined by the client implementation, not configurable from JavaScript. A browser and a bot using the same TLS library but different HTTP/2 stacks will have different SETTINGS fingerprints.

HTTP/2 settings add connection context, but are correlated with the client stack and can be affected by intermediaries. Measure their incremental value alongside TLS observations; two matching fingerprints are not two independent proofs of identity.

Verdict: Additional connection context where available. Validate how proxies and protocol changes affect the observations.

The Anti-Fingerprinting Landscape

Understanding what the other side is doing matters. Here’s the current state of anti-fingerprinting efforts, both from browsers protecting privacy and from automation tools evading detection.

Browser-Level Protections

Browser protections vary by product, version, platform, and browsing mode. Keep these distinctions in your test matrix:

  • User-Agent reduction changes exposed detail; it is not a blanket removal of fingerprinting APIs.
  • Blocking known fingerprinting scripts is different from changing the API values a first-party page can read.
  • Randomization can be stable within a scope such as a site or session. A repeated hash does not prove a protection is disabled.
  • Private browsing does not guarantee that every characteristic is hidden, and it does not imply every fingerprint stays stable.

The browser-vendor references above describe mechanisms. Your own measurements should establish their effect on the detection decisions you actually make.

Automation Tool Countermeasures

Puppeteer Extra Stealth Plugin: Patches navigator.webdriver, spoofs plugins arrays, overrides Chrome runtime properties, and modifies other detectable automation artifacts. Does not affect TLS fingerprints or network-level signals.

Playwright Stealth Patches: Similar to Puppeteer Stealth. Masks automation-specific JavaScript properties. Increasingly includes WebGL spoofing that overrides WEBGL_debug_renderer_info to report a realistic GPU string instead of SwiftShader.

Browser-as-a-Service: Hosted automation can run real browser engines. Do not assume the provider uses an obsolete Chromium release or has a unique TLS signature without a dated, reproducible measurement.

Anti-detect browsers: Modified profiles can alter exposed properties. A detector must evaluate the resulting evidence, rather than treating the product name or a vendor’s spoofing claim as a measured detection result.

Building a Fingerprinting System in 2026

If you’re building fingerprinting into a product today, here’s the architecture that accounts for the current reality.

Layer 1: Network Fingerprints (Server-Side)

Collect at the proxy or load balancer level:

TLS ClientHello → JA4 hash
HTTP/2 SETTINGS → settings fingerprint
TCP/IP characteristics → OS fingerprint

These observations are outside page JavaScript, but remain influenced by the client stack and observation point. Investigate a mismatch with the claimed browser against a current baseline and the known proxy path.

Layer 2: Rendering and Processing Signals (JavaScript)

Collect from the browser:

WebGL renderer + parameters → GPU profile
AudioContext output → audio stack fingerprint
Canvas rendering → 2D render fingerprint

These observations describe the rendering and processing environment, with privacy and availability limits. Keep missing values distinct from observed values. A graphics driver change or browser update can legitimately change a fingerprint.

Layer 3: Behavioral Fingerprints (JavaScript)

Collect over the session:

Mouse movement patterns → human vs. automated motion
Scroll behavior → natural vs. programmatic
Keystroke timing → cadence analysis
Touch events → pressure, area, timing
Interaction timing → human reaction time vs. script delays

Behavioral observations add context about the interaction rather than just its environment. Measure them across legitimate navigation styles, mobile devices, assistive technology, and scripted tests. A quiet mouse or an unusual cadence should not by itself trigger enforcement.

Combining Signals

No single fingerprinting technique is sufficient in 2026. The value is in the combination:

Confidence = f(
  network_fingerprint_consistency,
  hardware_fingerprint_entropy,
  behavioral_signal_humanness,
  cross_signal_coherence
)

Cross-signal coherence means asking whether the observations make sense together. An apparent mismatch may come from automation, a proxy, a browser update, or privacy controls. Record the evidence and test those alternatives before choosing a response.

How to test a fingerprinting system

  1. Define the outcome. Separate recognizing a returning environment from detecting a harmful action. They require different labels.
  2. Build a representative browser matrix. Include normal and private modes, privacy protections, mobile devices, graphics fallbacks, extensions, and your own authorized automation.
  3. Measure availability and stability. Repeat observations across reloads, sessions, browser updates, and cookie clearing. Report missing data separately.
  4. Measure shared fingerprints. Count how often distinct legitimate users share values and how often one user changes them. A unique result in a small sample is not population-wide uniqueness.
  5. Evaluate decisions on held-out traffic. Record false positives and missed abuse by browser group. Keep a recovery path for affected users.
  6. Start in observation mode. Compare fingerprint-only decisions with behavior and stronger evidence such as decoy interactions before enabling blocking.

For a practical deployment path, Bot Scanner covers browser-side collection, the Edge Sensor covers requests outside the browser script, and decoy links add interaction evidence.

The Privacy Tension

This article has been written from a security perspective. That’s intentional. Fingerprinting for bot detection and fingerprinting for cross-site tracking are the same technology applied to different ends.

The privacy concerns are real. Browser fingerprinting has been used to track users across sites without consent, circumventing cookie controls and privacy preferences. The browser vendor restrictions described above are responses to documented abuse.

Security decisions still need evidence when fingerprint data is limited. Use authentication, authorization, abuse controls, request history, and detection signals appropriate to the action being protected. A fingerprint can support that system; it cannot replace it.

Limit collection and retention to the security question you are answering. Account for privacy-preserving browsers when evaluating false positives. The practical goal is to reduce abuse while allowing legitimate visitors to complete their tasks.


Related Reading:

Frequently Asked Questions

Is browser fingerprinting still effective in 2026? +

It can support risk assessment, but reliability depends on the browser, privacy settings, and traffic population. Canvas, WebGL, audio, and network fingerprints describe parts of a client environment. None alone proves that a visitor is human or automated.

Does Chrome's Privacy Sandbox kill browser fingerprinting? +

User-Agent reduction removes some detailed browser and operating-system information. It does not eliminate every fingerprinting surface. Rendering APIs, Client Hints, and network observations have different capabilities and limits, so they need separate evaluation.

Can browser fingerprinting detect bots? +

It can expose inconsistencies or known automation markers, but real-browser automation can share legitimate browser fingerprints. Missing APIs or randomized values can also come from privacy protections. Combine signals with behavior and request context before taking action.

What is the most reliable browser fingerprinting technique in 2026? +

There is no universal winner. JA4 provides network context that page JavaScript cannot directly change, while canvas and WebGL provide rendering observations. Clients can share or imitate fingerprints. Measure each signal's coverage, stability, and false-positive rate on your own traffic.

Does a fingerprint persist after clearing cookies or switching browsers? +

Clearing cookies does not necessarily change rendering or network characteristics. Switching browsers, updating software, or enabling privacy protections can change them. A fingerprint is not a guaranteed persistent identity across browsers or devices.

Want to see WebDecoy in action?

Get a personalized demo from our team.

Request Demo