User identification on the web has long relied heavily on client-side storage such as cookies, localStorage, or indexedDB. However, the emergence of strict privacy policies (Safari's ITP, Chrome's Privacy Sandbox), incognito mode, and users' periodic cookie deletion have made traditional methods less stable.
Browser Fingerprinting has emerged as a technique for identifying devices based entirely on hardware characteristics, operating system, and browser rendering engine. This article will break down each component that constitutes a high-quality fingerprint, while analyzing why removing resolution (screen resolution) is the key to unlocking countless real-world use cases.
Browser Fingerprinting is a method of collecting a set of public attributes that the browser provides through standard Web APIs. By hashing all these signals together, the system creates a unique identifier (Visitor ID) representing that device.
This technique possesses outstanding advantages:
A robust fingerprint system does not rely on a single parameter but combines multiple layers of entropy from hardware to software.
Most modern devices use a GPU for web graphics rendering. Through WebGL:
WEBGL_debug_renderer_info, applications can directly read the chipset name and graphics card driver (e.g., Apple M2 Max, NVIDIA GeForce RTX 4070 Laptop GPU, AMD Radeon RX 7800 XT).Similar to WebGL, Canvas 2D draws a sample text containing special characters, emojis, and Bezier curves.
AudioContext fingerprinting does not record from a microphone or emit external noise. This technique operates entirely in memory using OfflineAudioContext:
sampleHash value for the device.The IEEE-754 standard for floating-point arithmetic allows for tiny errors in the final decimal places when calculating complex trigonometric functions.
Math.sin, Math.cos, Math.tan, Math.asin, Math.acos, and especially large values (Math.largeTan, Math.largeCos), different processor architectures (Intel Core x86_64, AMD Zen, Apple Silicon ARM64, Qualcomm Snapdragon) yield results that differ from the 16th decimal place onward.Each system has a unique collection of fonts installed over time (graphic fonts, office fonts, local fonts).
monospace, sans-serif), the system can accurately determine which fonts actually exist on the user's machine.Basic physical configuration parameters:
navigator.deviceMemory).navigator.hardwareConcurrency).navigator.languages), e.g., ["en-US", "en", "vi-VN"].Asia/Ho_Chi_Minh) and UTC offset.Resolution Unlocks Countless Real-World Use Cases?According to the traditional approach, most basic fingerprint libraries include screen.width, screen.height, and screen.resolution in the identification hash string. However, in real production environments, resolution is an extremely fragile entropy attribute.
Removing screen.resolution from the hash entropy to create a Resilient Fingerprint brings a significant leap in stability for the following scenarios:
This is the most common scenario for office workers and developers:
resolution parameters are completely replaced.In a multi-monitor setup (Dual/Triple Monitor), users frequently drag browser windows from the primary monitor to a secondary monitor with different resolutions and scale ratios. Resilient Fingerprint ensures no interruptions or session breaks when users move windows.
On smartphones and tablets (iPhone, iPad, Android):
iPad users (Stage Manager / Split View), Windows users (Snap Assist), or Linux/macOS users (i3, Hyprland, Yabai) frequently work with split or dynamically resized frames. Decoupling resolution makes the system completely immune to such size changes.
Users often change DPI scaling on Windows (100% → 125% → 150%) or use Ctrl + / Ctrl - to zoom in and out of the interface. Removing resolution ensures identification is not dependent on individual vision or screen zoom preferences.
To create a Resilient Fingerprint, you can use the @feelai/thumbmark library with a configuration that excludes screen.resolution:
```typescript import { Thumbmark } from "@feelai/thumbmark"; import { UAParser } from "ua-parser-js";
export const getResilientFingerprint = async () => { // Exclude the fragile resolution attribute const client = new Thumbmark({ exclude: ["screen.resolution"], });
const info = await client.get(); const ua = UAParser(navigator.userAgent); info.platform = ua.os.name ?? "Unknown";
return { thumbmarkId: info.thumbmark, platform: info.platform, components: info.components, version: info.version, }; }; ```
To enhance uniqueness, the server (Cloudflare Worker or Next.js Edge Route) can combine client-sent data with unforgeable network headers:
```typescript export const createServerMasterFingerprint = async ( req: Request, clientData: any, ) => { const serverInfo = { requestIp: req.headers.get("CF-Connecting-IP") || "127.0.0.1", country: (req as any).cf?.country || req.headers.get("cf-ipcountry") || "", region: (req as any).cf?.region || req.headers.get("x-cf-region") || "", timezone: (req as any).cf?.timezone || req.headers.get("x-cf-timezone") || "", };
// Remove resolution from the screen object before calculating the hash const { screen, ...otherComponents } = clientData.components || {}; const cleanScreen = screen ? { ...screen, resolution: undefined } : {};
const entropyComponents = [ serverInfo.requestIp, serverInfo.country, serverInfo.region, serverInfo.timezone, clientData.platform, clientData.thumbmarkId, JSON.stringify(otherComponents.audio), JSON.stringify(otherComponents.fonts), JSON.stringify(otherComponents.hardware), JSON.stringify(otherComponents.locales), JSON.stringify(otherComponents.math), JSON.stringify(cleanScreen), JSON.stringify(otherComponents.webgl), ];
const encoder = new TextEncoder(); const digestBuffer = await crypto.subtle.digest( "SHA-256", encoder.encode(entropyComponents.join("|")), );
const hashHex = Array.from(new Uint8Array(digestBuffer)) .map((b) => b.toString(16).padStart(2, "0")) .join("");
return { masterFingerprint: hashHex.slice(0, 32), serverInfo, }; }; ```
You can directly observe all WebGL, AudioContext, differential CPU error, and font list parameters of the device you are using with the FeelAI Fingerprint Inspector tool:
👉 Experience it now at: FeelAI Fingerprint Inspector
The tool allows you to flexibly switch between Standard Hash (including resolution) and Resilient Hash (excluding resolution) to directly verify the mechanism of maintaining identity when resizing or changing displays.