Section 1: Introduction to Browser Fingerprinting
What is Browser Fingerprinting?
Browser fingerprinting is a powerful tracking technique used to identify and track users based on unique traits of their browsers and devices. Unlike cookies, which require storage on a user's device and are often easy to clear or block, browser fingerprinting gathers information through various browser APIs to build a unique identifier or "fingerprint" for each user.
This fingerprint remains persistent across different browsing sessions, making it a more reliable method for tracking. When you visit a website, scripts embedded within the page collect details like your operating system, installed plugins, screen resolution, fonts, and even hardware details like your graphics card. These data points are then combined to create a unique fingerprint, which can be used to track your activity across multiple websites, even if you have cleared your cookies or use incognito mode.
Key Data Points Used in Browser Fingerprinting
To understand how detailed a fingerprint can be, let's break down the types of information collected during the fingerprinting process:
- Browser details: User-agent string, browser version, and type (Chrome, Firefox, etc.).
- Operating system: The operating system version (Windows, macOS, Linux).
- Screen characteristics: Screen resolution, color depth, and available screen size.
- Installed plugins: List of browser plugins or extensions like Flash or PDF readers.
- Fonts: Installed fonts on your device, which can be highly unique depending on your operating system and software.
- Canvas API data: Image rendering characteristics, such as how text and images are drawn on your screen, collected through the HTML5 Canvas element.
- WebGL API data: Details on how your system renders 3D graphics, including your graphics card model and the specific drivers your system uses.Â
- Audio and media APIs: Information from audio signals processed by the browser, which can vary between devices. Here’s an example of how JavaScript can gather some of this information from your browser:
// Collect browser details
var browserDetails = {
userAgent: navigator.userAgent,
screenResolution: window.screen.width + "x" + window.screen.height,
colorDepth: window.screen.colorDepth,
language: navigator.language,
platform: navigator.platform,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
};
console.log(browserDetails);
This simple script collects the user-agent string, screen resolution, color depth, system language, and the platform (Windows, Mac, etc.) as well as your current time zone. Each piece of information by itself might seem harmless, but when combined, it forms a unique profile that can be used for tracking purposes.
Why is Browser Fingerprinting More Persistent than Cookies?
Cookies have traditionally been the primary method of tracking users across websites, but they are becoming less effective due to browser privacy enhancements and legislation like GDPR. Browsers now allow users to block or clear cookies, and many sites need user consent to use cookies, limiting their scope for tracking. In contrast, browser fingerprinting doesn’t require any explicit permission from the user. It works by collecting passive information through scripts that run when a website is loaded.
Because this technique doesn't rely on storage mechanisms like cookies, it can track users even if they switch browsers, use private browsing modes, or frequently delete their cookies. Additionally, browser fingerprints are harder to evade because they are built on how your specific hardware and software interact with web technologies. For example, the way your device renders a simple graphic on the screen (via the Canvas API) is influenced by factors such as your operating system, browser version, and even your graphics card, making this information difficult to spoof or hide effectively.
Real-World Example of Browser Fingerprinting
Imagine you’re using a regular browser like Google Chrome to visit a website that uses CreepJS, an advanced fingerprinting tool. The moment you load the website, CreepJS runs a series of tests to gather information about your device and browser.
For instance, it might use the WebGL API to collect details about your graphics card, the Canvas API to capture how your system renders images, and even detect the exact version of your browser and operating system. The resulting fingerprint could look something like this:
{
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36",
"screenResolution": "1920x1080",
"colorDepth": 24,
"platform": "Win32",
"timezone": "America/New_York",
"webGLRenderer": "ANGLE (Intel(R) UHD Graphics Direct3D11 vs_5_0 ps_5_0)",
"canvasHash": "9e107d9d372bb6826bd81d3542a419d6"
}
Even if you clear your cookies or switch to incognito mode, this fingerprint remains largely the same when you revisit the website, allowing it to recognize you.
Common Use Cases for Browser Fingerprinting
Browser fingerprinting has several legitimate and questionable use cases. On the one hand, companies use it to secure websites by detecting fraud, ensuring that the same device is used throughout a transaction process. On the other hand, it can be used to build detailed user profiles for targeted advertising without user consent, raising privacy concerns. Here are some common applications:
- Fraud detection: Fingerprints help detect when a different device tries to access a user’s account.
- Ad targeting: Marketers use fingerprints to track user behavior and serve personalized ads.
- Account security: Multi-factor authentication systems use fingerprinting to ensure that a login request comes from a trusted device. In all these cases, the persistent nature of fingerprints means that users can be tracked across the web, often without their knowledge or consent.
Conclusion
Browser fingerprinting is an increasingly popular method for identifying and tracking users online, surpassing cookies in its persistence and stealth. Tools like CreepJS gather high-entropy data from your browser and device, making it almost impossible to evade detection without advanced privacy tools. In the next section, we will dive deeper into how CreepJS works, examining the specific techniques it uses to create a fingerprint and how it exploits various browser APIs.
Section 2: How CreepJS Works
Overview of CreepJS as an Advanced Fingerprinting Tool
CreepJS is an open-source JavaScript-based fingerprinting tool designed to detect browser vulnerabilities and analyze privacy risks. It stands out due to its comprehensive approach to browser fingerprinting, leveraging numerous browser APIs to collect high-entropy data from a wide range of sources. By gathering detailed information about a user’s browser and device, CreepJS creates unique and persistent fingerprints, making it difficult for users to hide their identity even when using privacy tools or anti-fingerprinting techniques.
CreepJS is especially effective at revealing “lies” or inconsistencies caused by privacy tools attempting to obfuscate fingerprint data. This tool is not just useful for detecting users but also serves as a valuable resource for testing the robustness of anti-fingerprinting extensions and privacy
Data Collection Process in CreepJS
CreepJS gathers information through various browser APIs that are often overlooked by users. Here’s a step-by-step breakdown of how the tool collects, processes, and analyzes data to create a fingerprint:
1. Gathering Data from Browser APIs
CreepJS interacts with a multitude of browser APIs to gather as much data as possible. These include:
- Canvas API: Collects information by rendering text or images on a hidden canvas element. Variations in how devices render these elements help distinguish between different systems.
- WebGL API: Gathers data on how the browser renders 3D graphics, including GPU model, rendering capabilities, and other graphical settings.
- Audio API: Captures data on how audio is processed by the device, including frequency data and audio signal characteristics.
- Navigator API: Retrieves basic information like the user-agent, language, platform, and browser version.
- Media Devices API:Â Extracts information about connected media devices, such as cameras or microphones. This JavaScript snippet demonstrates how CreepJS might collect data using the Canvas and WebGL APIs:
// Collecting Canvas Fingerprinting Data
function getCanvasFingerprint() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('CreepJS Fingerprinting', 10, 50);
return canvas.toDataURL();
}
// Collecting WebGL Fingerprinting Data
function getWebGLFingerprint() {
var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl');
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
return gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
}
console.log('Canvas Fingerprint: ' + getCanvasFingerprint());
console.log('WebGL Renderer: ' + getWebGLFingerprint());
2. Hashing and Processing Data
Once the data is collected, CreepJS uses various hashing algorithms to transform this raw information into a compact fingerprint. Hashing is an essential process because it converts large amounts of data into a fixed-size identifier. For example, a user’s screen resolution, font list, and WebGL data are combined and hashed into a string of characters that uniquely identifies the browser environment. This is an example of how a hashed fingerprint might look:
{
"fingerprint": "b8e57d5a9b102037d234a75b0d492d0f"
}
CreepJS uses advanced hashing techniques to ensure that even slight changes in the collected data (such as switching devices or browsers) result in a different hash, preventing the same fingerprint from being used across varying environments
3. Fingerprint Creation and Categorization
Once the data is hashed, CreepJS organizes it into categories based on the type of information collected. For example, the final fingerprint might include sections for:
- Browser Features: User-agent, supported browser APIs, installed plugins.
- Screen Properties: Resolution, available screen space, color depth.
- Rendering Capabilities: Information from the Canvas and WebGL APIs, like text rendering styles and GPU details.
- Device Properties: Operating system, platform, and hardware details. This categorization allows CreepJS to create a highly detailed profile of the user's environment, making the fingerprint unique and difficult to spoof.
4. Entropy Analysis
An important aspect of CreepJS’s operation is its entropy analysis. Entropy measures the uniqueness or randomness of the fingerprint. The more unique data points CreepJS can collect, the higher the entropy and the more difficult it becomes for the user to mask their identity. For instance, a combination of a rare font, an uncommon screen resolution, and specific WebGL parameters can make a browser’s fingerprint extremely distinctive. Higher entropy means that even small data points, like a unique GPU or an odd browser configuration, can contribute to a more detailed and unique fingerprint. CreepJS calculates the entropy of each component, helping identify which traits are the most valuable for tracking users
How CreepJS Detects Privacy Evasion Techniques
One of the standout features of CreepJS is its ability to detect when users are attempting to hide their true fingerprint. Many anti-fingerprinting tools, such as those built into privacy-focused browsers like Tor or Brave, attempt to spoof browser properties to make users less trackable. CreepJS, however, can identify these “lies” or inconsistencies by comparing the reported browser data against expected values.
For example, if a browser claims to be running on a Windows system but reports a GPU that only exists on macOS, CreepJS flags this as a lie. The tool then adjusts the user’s trust score, making it easier to detect whether the user is running a genuine browser or employing privacy tools to mask their identity. Here’s a simplified example:
// Checking for inconsistencies in the GPU
function checkGPUConsistency() {
var gpu = getWebGLFingerprint();
var platform = navigator.platform;
if (platform === 'Win32' && gpu.includes('Apple')) {
console.log('Suspicious behavior: GPU does not match platform.');
} else {
console.log('No inconsistencies detected.');
}
}
checkGPUConsistency();
This ability to detect and expose privacy evasion techniques is what makes CreepJS particularly effective at fingerprinting, even in environments that are using privacy tools​.
Large-Scale Data Collection and Cross-Browser Testing
CreepJS is designed to operate at scale, making it capable of simulating data collection across a wide variety of browsers and platforms. By testing its fingerprinting methods on multiple devices, CreepJS validates the robustness of its techniques and ensures that fingerprints remain accurate across different environments, including mobile and desktop.
The tool compares data collected from different browsers to identify vulnerabilities and discrepancies in how they handle fingerprinting attempts. For example, CreepJS may find that a certain browser version on mobile devices leaks more identifiable data than its desktop counterpart, and it adjusts its fingerprinting methods accordingly.
Conclusion
CreepJS is a highly sophisticated fingerprinting tool that collects data from a wide range of browser APIs to build unique and persistent browser fingerprints. It uses advanced techniques like hashing and entropy analysis to create detailed profiles of users while detecting any attempts to spoof or obfuscate browser data. In the next section, we will explore the specific browser fingerprinting techniques used by CreepJS, such as Canvas and WebGL fingerprinting, and how they contribute to the accuracy and uniqueness of each fingerprint.
Section 3: Browser Fingerprinting Techniques in CreepJS
Canvas Fingerprinting
Canvas fingerprinting is one of the most effective and widely used techniques in browser fingerprinting. It exploits the way different devices and browsers render graphics using the HTML5 `<canvas>` element. Since every device has unique hardware and software configurations, even rendering the same image or text on two devices can produce slight variations. CreepJS leverages this by drawing a graphic or some text on a hidden canvas and then analyzing the output. When the browser renders this graphic, the output is converted into image data, which is then hashed into a unique string.
The subtle differences in how the browser’s graphics processing unit (GPU) renders text, colors, and shapes result in a unique identifier for that specific device. Here’s an example of how CreepJS might implement canvas fingerprinting:
// Function to capture Canvas fingerprint
function getCanvasFingerprint() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('CreepJS Fingerprinting', 10, 50);
return canvas.toDataURL();
}
console.log('Canvas Fingerprint: ' + getCanvasFingerprint());
By capturing how your browser renders the canvas, CreepJS creates a fingerprint that can be used for tracking, even across different sessions and websites. These fingerprints are especially persistent because they are based on device-specific rendering capabilities, making them harder to spoof​.
Why Canvas Fingerprinting is Difficult to Spoof
Canvas fingerprinting is particularly hard to evade because it taps into low-level rendering operations that vary across different devices and environments. Even small changes, like updating your graphics card driver or switching to a different device, can alter how the canvas is rendered, which will change the resulting fingerprint. Some privacy tools attempt to block or spoof canvas fingerprinting by either preventing the canvas element from being accessed or by returning a generic, non-unique output.
However, CreepJS is designed to detect such tampering by analyzing the consistency of the output and comparing it to other system parameters, which makes it harder for users to disguise their true fingerprint​.
WebGL Fingerprinting
WebGL (Web Graphics Library) fingerprinting is another powerful technique used by CreepJS to gather information about the user’s graphics rendering capabilities. WebGL allows web browsers to render 3D graphics directly, and it provides detailed information about the underlying hardware, including the GPU model, supported extensions, and rendering performance. These details are used to create a unique fingerprint.
WebGL fingerprinting works by rendering complex 3D scenes and capturing the differences in how each device processes and displays these scenes. Since GPUs vary widely between devices (e.g., an Intel integrated GPU vs. an NVIDIA discrete GPU), the variations in rendering output can be used to generate a unique identifier. Here’s an example of WebGL fingerprinting in action:
// Function to capture WebGL fingerprint
function getWebGLFingerprint() {
var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl');
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
return {
renderer: renderer,
vendor: vendor
};
}
console.log('WebGL Fingerprint: ', getWebGLFingerprint());
This script collects data about the GPU and its vendor, which are critical components of the WebGL fingerprint. Because each GPU and graphics driver has its own unique quirks in how it renders 3D graphics, WebGL data is an invaluable tool for creating highly unique fingerprints​
How WebGL Fingerprinting Enhances Uniqueness
WebGL fingerprinting goes beyond the basic browser details like user-agent and screen resolution, delving into the hardware layer. The information retrieved includes:
- GPU Model and Vendor: Specifics about the graphics card in use (e.g., NVIDIA, Intel, AMD).
- Supported Extensions: Details about the supported WebGL extensions, which vary based on the GPU and driver version.
- Rendering Differences: Subtle variations in how different GPUs render 3D objects, making it harder for users to spoof their environment. Even privacy-focused browsers, such as Tor, which attempt to neutralize some forms of browser fingerprinting, often struggle to fully obfuscate WebGL data. This makes WebGL fingerprinting a reliable and persistent method for tracking​
Audio Fingerprinting
CreepJS also uses the Web Audio API to gather information for audio fingerprinting. Audio fingerprinting works by playing a sound or generating an audio signal in the browser and analyzing how the device processes it. Different devices have varying audio hardware and software configurations, which affect how audio signals are handled, processed, and output.
CreepJS captures these variations by analyzing specific audio properties such as gain reduction, frequency responses, and time-domain data, generating a unique audio fingerprint for each device. Here’s an example of how CreepJS might implement audio fingerprinting:
// Function to capture Audio fingerprint
function getAudioFingerprint() {
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = audioCtx.createOscillator();
oscillator.type = 'triangle';
oscillator.frequency.setValueAtTime(1000, audioCtx.currentTime);
var compressor = audioCtx.createDynamicsCompressor();
compressor.threshold.setValueAtTime(-50, audioCtx.currentTime);
compressor.knee.setValueAtTime(40, audioCtx.currentTime);
compressor.ratio.setValueAtTime(12, audioCtx.currentTime);
compressor.attack.setValueAtTime(0, audioCtx.currentTime);
compressor.release.setValueAtTime(0.25, audioCtx.currentTime);
oscillator.connect(compressor);
compressor.connect(audioCtx.destination);
oscillator.start(0);
return compressor.reduction.value;
}
console.log('Audio Fingerprint: ' + getAudioFingerprint());
Why Audio Fingerprinting is Effective
Just like with Canvas and WebGL, audio fingerprinting leverages the unique characteristics of each device’s hardware to generate a fingerprint. Since every sound card, processor, and even browser version can influence how audio signals are processed, CreepJS uses this variability to build a highly distinctive identifier. This makes it particularly effective for tracking users across websites​.
Screen Fingerprinting
Screen fingerprinting focuses on gathering detailed information about the user’s display properties. CreepJS collects data such as screen resolution, color depth, available screen space, and device pixel ratio to add another layer of uniqueness to the fingerprint. These characteristics vary based on the device’s hardware and user configuration, making them useful for distinguishing between different users. The following script illustrates how CreepJS collects screen-related information:
// Function to capture screen fingerprint
function getScreenFingerprint() {
return {
resolution: window.screen.width + 'x' + window.screen.height,
colorDepth: window.screen.colorDepth,
pixelRatio: window.devicePixelRatio
};
}
console.log('Screen Fingerprint: ', getScreenFingerprint());
Why Screen Fingerprinting is Important
Screen properties might seem like generic information, but they provide an additional data layer that strengthens the overall fingerprint. For instance, users with specific screen resolutions (e.g., those with 4K displays) can be more easily identified, especially when combined with other data points like WebGL or audio fingerprints. This makes screen fingerprinting a valuable component in creating a persistent and accurate browser fingerprint.
Conclusion
CreepJS employs a wide array of sophisticated fingerprinting techniques, including Canvas, WebGL, audio, and screen fingerprinting, to create highly unique and persistent profiles of users. Each technique taps into different aspects of the user's hardware and software configuration, making it nearly impossible to avoid detection. In the next section, we will explore strategies for defending against CreepJS and similar fingerprinting tools, including stealth techniques and browser automation tools that can help evade detection.
Section 4: Defending Against CreepJS
Challenges of Bypassing CreepJS
CreepJS is a sophisticated browser fingerprinting tool designed to detect attempts to alter or mask the user’s true browser identity. As we’ve seen, it uses a range of techniques like Canvas, WebGL, and Audio fingerprinting, each targeting different components of the browser and hardware. The challenge with bypassing CreepJS lies in its ability to detect lies or inconsistencies in how the browser presents itself. For instance, privacy tools that attempt to spoof browser details are often detected by CreepJS, which can compare browser reports with expected values and flag any discrepancies​.
Furthermore, even privacy-focused browsers like Tor, Brave, and Firefox with enhanced privacy settings struggle to fully mask the data that CreepJS gathers. This creates an ongoing "cat and mouse" game between developers of anti-fingerprinting tools and sophisticated trackers like CreepJS. Despite this, there are several strategies for defending against CreepJS and similar fingerprinting tools.
Using Browser Automation Tools to Evade CreepJS
One of the more popular ways to deal with browser fingerprinting and CreepJS detection is by using browser automation tools like Puppeteer, Selenium, and Playwright. These tools allow users to programmatically control browsers, which is especially useful for scraping data from websites without getting flagged as a bot. However, CreepJS is designed to detect browsers controlled by automation frameworks, making it necessary to use stealth techniques.
Puppeteer Stealth Plugin
The Puppeteer Stealth plugin is a powerful extension for Puppeteer that helps bypass anti-bot systems by mimicking natural browsing behavior and masking telltale signs of automation. For example, vanilla Puppeteer can leak obvious bot-like signals, such as a `navigator.webdriver` property being set to `true`, or using the "HeadlessChrome" user-agent string, both of which CreepJS can detect. To mitigate this, the Puppeteer Stealth plugin patches these issues by altering the browser's behavior to appear more natural. Here’s an example of how to implement Puppeteer Stealth:
// Using Puppeteer Stealth to evade detection
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://abrahamjuliot.github.io/creepjs/');
// Wait for the page to load and screenshot the result
await page.screenshot({ path: 'stealth-screenshot.png', fullPage: true });
await browser.close();
})();
This script launches Puppeteer in stealth mode, reducing the chances of CreepJS detecting automation. It modifies several browser properties, such as `navigator.webdriver`, user-agent strings, and other signals, making it harder for fingerprinting tools to identify the browser as automated​.
Playwright and Selenium Stealth Techniques
Playwright and Selenium are other widely used browser automation tools. Similar to Puppeteer, they require stealth techniques to avoid detection by CreepJS. Playwright can be enhanced with stealth features using libraries like playwright-extra, while Selenium has its counterpart, undetected-chromedriver, which modifies the default WebDriver behavior to evade detection. Here’s how you can implement a stealth technique in Playwright:
// Playwright stealth evasion script
const { chromium } = require('playwright-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://abrahamjuliot.github.io/creepjs/');
// Wait and take a screenshot
await page.screenshot({ path: 'playwright-screenshot.png', fullPage: true });
await browser.close();
})();
These tools adjust browser behaviors that are commonly flagged by anti-fingerprinting systems. They modify properties such as `navigator.platform`, `navigator.language`, and others that CreepJS monitors for consistency.
Stealth Libraries and Plugins
Several stealth libraries and plugins have been developed to help evade detection by advanced fingerprinting tools like CreepJS. Below are some popular options:
- playwright-extra: A lightweight plugin framework for Playwright that includes stealth features.
- undetected-chromedriver: A Selenium-based WebDriver modification designed to bypass anti-bot systems.
- puppeteer-extra-plugin-stealth: Adds stealth capabilities to Puppeteer, masking many detectable browser properties.Â
These tools typically work by:
- Masking or randomizing fingerprinting-sensitive fields like `navigator.webdriver`.
- Modifying or hiding headless browsing signatures (like “HeadlessChrome”).
- Controlling JavaScript features such as WebGL, Canvas, and Audio APIs, where fingerprinting scripts gather data.
Limitations of Stealth Techniques
While stealth techniques can significantly reduce the chances of detection, they are not foolproof. Advanced fingerprinting tools like CreepJS are constantly evolving, adapting to new evasion strategies. Additionally, these techniques can be resource-intensive, requiring constant updates to stay ahead of fingerprinting systems. Moreover, the more a browser deviates from natural behavior (e.g., via stealth plugins), the higher the risk that sophisticated tools like CreepJS will eventually detect the deception​.
Alternative Defenses: Privacy-Focused Browsers and Extensions
Some users rely on privacy-focused browsers like Tor, Brave, or Firefox with enhanced privacy settings to reduce the risk of fingerprinting. While these browsers come with built-in anti-fingerprinting features, they are not entirely immune to detection by tools like CreepJS, which is designed to bypass many of these protections. Nonetheless, they offer an additional layer of defense against fingerprinting:
- Tor Browser: Attempts to standardize browser configurations across all users, making it harder to generate unique fingerprints.
- Brave Browser: Blocks third-party trackers by default and attempts to reduce fingerprinting by randomizing certain browser properties.
- Firefox (Resist Fingerprinting): Offers a setting to combat fingerprinting by limiting the data shared through APIs like Canvas and WebGL.
Conclusion
Defending against CreepJS and similar browser fingerprinting tools is a challenging task due to the sophisticated techniques they use to collect high-entropy data from various browser and hardware APIs. Browser automation tools like Puppeteer and Playwright can evade detection with the help of stealth plugins, while privacy-focused browsers offer some protection. However, as fingerprinting methods become more advanced, the battle between user privacy and fingerprinting techniques will continue to evolve. Staying updated with the latest stealth strategies and using privacy-enhancing tools can help reduce your exposure, but complete anonymity remains difficult to achieve.