Skip to content
ProxyRaw
advancedFingerprinting

Canvas Fingerprinting

A browser fingerprinting technique that renders hidden text and geometric graphics on an HTML5 <canvas> element and hashes the sub-pixel rasterization variations to uniquely identify hardware.

Canvas fingerprinting is one of the most widespread and technically sophisticated client-side device identification techniques. First documented in academic research by Mowery and Shacham in 2012, canvas fingerprinting exploits the fact that the same graphic instructions produce subtly different pixel outputs across different machines.

Websites use canvas fingerprinting for cookieless user tracking, fraud prevention, and bot detection.

How Canvas Fingerprinting Works Under the Hood (link to this section)

The process executes entirely in client-side JavaScript in a few milliseconds:

  1. Creating the Canvas: A hidden HTML5 <canvas> element is created in the DOM (often with display: none or rendered offscreen).
  2. Drawing Complex Graphics: A JavaScript script draws a specific combination of:
  • Text strings containing varied unicode glyphs, punctuation, and complex ligatures (e.g., "Cwm fjordbank glyphs vext quiz, 😃").
  • Multiple font families and fallbacks (Arial, Times New Roman, system fonts).
  • Overlapping 2D geometric shapes with gradients, semi-transparent alpha blending, and radial fills.
  1. Extracting Pixel Data: The script calls canvas.toDataURL() to extract a base64-encoded PNG image, or calls ctx.getImageData() to access the raw 32-bit RGBA pixel array buffer.
  2. Hashing the Result: The pixel byte array is passed through a hashing function (such as MurmurHash3 or CRC32) to generate a compact hexadecimal token.
javascript
// Simplified canvas fingerprint extraction
function getCanvasFingerprint() {
  const canvas = document.createElement("canvas");
  canvas.width = 200;
  canvas.height = 50;
  const ctx = canvas.getContext("2d");
  
  ctx.textBaseline = "top";
  ctx.font = "14px 'Arial', sans-serif";
  ctx.fillStyle = "#f60";
  ctx.fillRect(125, 1, 62, 20);
  ctx.fillStyle = "#069";
  ctx.fillText("ProxyRaw Security 🔒", 2, 15);
  ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
  ctx.fillText("ProxyRaw Security 🔒", 4, 17);
  
  return canvas.toDataURL();
}

Why Every GPU Renders Pixels Differently (link to this section)

Even though modern browsers adhere to standard HTML5 specifications, the final rendered image varies at the sub-pixel level due to hardware and operating system variations:

  • GPU Hardware & Chipset Architecture: Different graphics cards (NVIDIA, AMD, Intel Iris, Apple Silicon M-series) implement rasterization pipelines and floating-point math rounding differently.
  • Operating System Font Rasterizers: Windows utilizes DirectWrite, macOS uses Core Graphics / Quartz, and Linux relies on FreeType. Each rasterizer handles sub-pixel anti-aliasing, font hinting, and kerning with distinct proprietary algorithms.
  • Display Driver Versions: Graphics driver updates can introduce slight adjustments to color space conversions and anti-aliasing curves.

These micro-differences are completely invisible to the human eye, but in a 32-bit RGBA pixel array, a shift in a single color channel from rgb(240, 102, 0) to rgb(240, 101, 0) produces an entirely different cryptographic hash.

The Canvas Poisoning Trap (link to this section)

When developers attempt to defeat canvas fingerprinting using simple browser extensions (like "Canvas Defender" or naive Puppeteer stealth scripts), they often use canvas noise injection: hooking toDataURL or getImageData and adding random mathematical noise to random pixels.

This is an immediate giveaway to anti-bot engines:

  • Detection scripts call toDataURL() twice within 5 milliseconds.
  • On a real human browser, identical draw instructions produce the exact same hash every single time.
  • If two consecutive calls produce different hashes, or if the canvas hash conflicts with the declared OS font engine, the client is instantly flagged as a spoofed bot.

Professional anti-detect browsers solve this by injecting deterministic, authentic hardware canvas profiles that remain 100% consistent throughout a profile's lifetime.

In practice

  • An anti-fraud service uniquely identifying a fraudulent buyer who cleared cookies, changed their IP address, and switched to Incognito mode, because their canvas hash remained identical.
  • Cloudflare Bot Management detecting an automated scraper running Puppeteer on a headless Linux server because the canvas rendered using software font rendering rather than a real GPU.
  • FingerprintJS computing a composite visitor identifier across 10,000 daily sessions where canvas provides 8 to 12 bits of identifying entropy.
  • An anti-detect browser successfully mimicking a MacBook Pro's Core Graphics canvas rendering signature while running on a Windows PC.

Common use cases

Cookieless cross-site device identificationWeb scraping bot detection and challenge issuanceBanking portal anti-fraud risk scoringMulti-accounting prevention on social media and e-commerceAffiliate marketing click-fraud prevention

Frequently asked

No. Canvas fingerprinting does not use cookies or local storage. It measures how your physical GPU and OS font rasterizer draw pixels, meaning the output remains identical in Incognito mode and across cookie resets.

Anti-bot scripts test for canvas poisoning by rendering the canvas twice. On real hardware, the hash is 100% deterministic. If an extension injects random noise on every call, the hashes differ, revealing the presence of an anti-fingerprinting tool.

SwiftShader is Google's software renderer used when Chromium runs in headless environments without a physical GPU (such as Linux cloud servers). Anti-bot systems immediately recognize SwiftShader's canvas rendering and flag the connection as an automated scraper.

No. Canvas fingerprinting identifies a specific device and browser configuration, not a person. If you switch from your desktop computer to your mobile phone, the two devices will produce completely different canvas fingerprints.

Related terms