50% OFF Residential Proxies for 9 months — use code IPR50 at checkout

Get The Deal
Back to blog

How to Use CreepJS to Bypass Browser Fingerprinting

Vilius Dumcius

Last updated -
How to

Key Takeaways

  • CreepJS shows where your browser fingerprints are exposed.

  • CreepJS integrates well with popular browser automation tools for scraping, testing, or research.

  • CreepJS helps developers inspect real browser environments to validate spoofing tools or test privacy setups.

Ready to get started?

Register now

Every time you open a browser and visit a website, your device leaves behind tiny marks. These marks form a digital ID called a browser fingerprint. Many websites use this ID to track, identify, or analyze users.

CreepJS is a tool that helps users defend against this kind of tracking. It analyzes how the browser behaves by showing exposed details to each tracking element. After that, you can use specific tools to make it harder for websites to recognize you in different sessions.

Here, you will learn what browser fingerprinting is, how CreepJS works, and how developers can use it safely and effectively.

What is Browser Fingerprinting?

Browser fingerprinting is a method used by websites to collect details about your device and browser. These details can include screen size, installed fonts, plugins, system time zone, GPU model, and much more. When combined, these traits form a browser fingerprint that’s uniquely yours.

Technically, these traits are collected using scripts. The collected data is run through hashing algorithms, which turn it into a fingerprint ID. It essentially functions as a digital label, tracking you across various websites, even without cookies.

Here are some common browser fingerprinting techniques:

  • Canvas fingerprinting (drawing invisible images)
  • Font detection and plugin checks
  • Audio context fingerprinting
  • Time zone and language settings
  • User-agent and OS data
  • Web graphics library fingerprints

Websites use browser fingerprints to detect fraud, stop bots, and serve targeted content. But they can also track users without their consent.

That’s where tools like CreepJS come in handy, analyzing where you’re exposed. Then, you can use browser automation tools to tweak those browser fingerprints so they don’t trace back to you.

Introduction to CreepJS

CreepJS is an open-source fingerprint analysis tool. It’s built on top of Puppeteer, one of the most popular browser automation tools. In crude terms, CreepJS shows the data that your browser exposes to scripts.

Once you have analyzed the fingerprint data, you can use browser automation tools like Puppeteer to modify the browser fingerprints with plugins to help you browse more privately.

It works by tweaking various parts of the browser environment, such as:

  • Canvas data
  • Audio signals
  • Plugin lists
  • Fonts
  • WebGL fingerprints

These tweaks help prevent your browser from being uniquely identified. CreepJS is especially useful in security testing, research, and browser automation tools.

Setting Up Puppeteer with Stealth Plugin for Fingerprint Spoofing

Here, we will cover the necessary tools and provide a working script to spoof browser fingerprints using Puppeteer and the stealth plugin.

Before you start, install the following:

  • Node.js: a JavaScript runtime environment that allows you to run scripts locally.
  • npm: Node’s package manager used to install libraries such as Puppeteer.
  • Puppeteer: a headless browser automation library built by Google.
  • puppeteer-extra and puppeteer-extra-plugin-stealth: tools that add fingerprint spoofing capabilities to Puppeteer.

How to Install It

In your terminal, run this command:

npm install puppeteer-extra puppeteer-extra-plugin-stealth

Note: if Puppeteer is not included in your package, you can also run:

npm install puppeteer

Example Setup Script

import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';

puppeteer.use(StealthPlugin());

(async () => {
  const browser = await puppeteer.launch({
    headless: false // Set to true if you don't need to see the browser
  });

  const page = await browser.newPage();

  await page.goto('https://abrahamjuliot.github.io/creepjs/');

  // Wait for 10 seconds using a Promise
 await page.goto('https://abrahamjuliot.github.io/creepjs/', {
  waitUntil: 'networkidle2'
});
    await new Promise(resolve => setTimeout(resolve, 10000));
    
    // Take a screenshot of the page   
    await page.screenshot({ path: 'creepjs_screenshot.png' });
    await browser.close();
})();

This script launches a new browser, spoofs the browser environment, and opens a website with altered browser fingerprint data. If you wish, you can modify it even further for scraping, automation, or privacy testing.

How CreepJS Can Be Used to Bypass Fingerprinting

First of all, CreepJS is a browser fingerprint analysis tool - it doesn’t spoof fingerprints itself but instead reveals what data your browser exposes. Developers and researchers use it to inspect how detectable a browser is based on traits like:

  • Canvas rendering output
  • Audio context properties
  • WebGL fingerprinting
  • Plugin and font detection
  • Timezone, language, and device data.

These details are gathered and displayed in structured form, allowing users to understand how unique their browser appears to tracking systems.

Below is a hypothetical example of how fingerprinting traits can change when spoofing is applied using tools such as puppeteer-extra-plugin-stealth.

1. Default Browser Fingerprinting

{
  "canvas": "hash123abc",
  "webgl": "Intel HD Graphics 4000",
  "plugins": ["Chrome PDF Viewer", "Native Client"],
  "fonts": ["Arial", "Verdana"],
  "timezone": "UTC+3"
}

2. With a Fingerprint Spoofing Tool

{
  "canvas": "hash789xyz",
  "webgl": "AMD Radeon 5600",
  "plugins": [],
  "fonts": ["Roboto", "Courier"],
  "timezone": "UTC-5"
}

These changes result in completely different browser fingerprinting data, which makes it difficult for tracking systems to link you to your past activities.

So, CreepJS doesn’t spoof the fingerprint itself. Instead, it reveals what’s exposed, and then you can use other tools for actual spoofing, such as puppeteer-extra-plugin-stealth.

These tools use custom scripts behind the scenes to adjust each browser trait. The goal is not just to hide but to look believable at the same time. That means that the analyzed browser fingerprint still appears normal, even though it’s fake.

If you want to see how a fingerprinting checker works, try this TCP/IP fingerprint checker tool .

Here’s an easy setup for fingerprint spoofing and checking:

import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';

puppeteer.use(StealthPlugin());

// ===== CUSTOMIZABLE FINGERPRINT CONFIGURATION =====
const FINGERPRINT_CONFIG = {
  // User Agent - Customize to match different browsers/OS
  userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  
  // Screen dimensions
  screen: {
    width: 1920,
    height: 1080,
    colorDepth: 24,
    pixelDepth: 24
  },
  
  // Viewport size
  viewport: {
    width: 1366,
    height: 768
  },
  
  // Timezone spoofing
  timezone: 'America/New_York', // Options: 'Europe/London', 'Asia/Tokyo', 'America/Los_Angeles', etc.
  
  // Language settings
  languages: ['en-US', 'en'],
  
  // Geolocation (if enabled)
  geolocation: {
    latitude: 40.7128,
    longitude: -74.0060,
    accuracy: 100
  },
  
  // Canvas fingerprint spoofing
  spoofCanvas: true,
  
  // WebGL fingerprint spoofing
  spoofWebGL: true,
  webglVendor: 'Intel Inc.',
  webglRenderer: 'Intel(R) UHD Graphics 620',
  
  // Memory spoofing
  deviceMemory: 8, // GB
  hardwareConcurrency: 4, // CPU cores
  
  // Platform spoofing
  platform: 'Win32',
  
  // Enable/disable various spoofing methods
  enableSpoofing: {
    userAgent: true,
    screen: true,
    timezone: true,
    canvas: true,
    webgl: true,
    fonts: true,
    plugins: true,
    hardware: true,
    battery: true
  }
};

(async () => {
  console.log('🎭 Starting Customizable Fingerprint Spoofer...');
  console.log('📋 Current Configuration:');
  console.log(JSON.stringify(FINGERPRINT_CONFIG, null, 2));
  
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-blink-features=AutomationControlled',
      `--lang=${FINGERPRINT_CONFIG.languages[0]}`
    ]
  });

  const page = await browser.newPage();

  // Apply fingerprint spoofing
  await applyFingerprintSpoofing(page, FINGERPRINT_CONFIG);
  
  console.log('🔍 Navigating to CreepJS...');
  
  try {
    await page.goto('https://abrahamjuliot.github.io/creepjs/');
    console.log('✅ Page loaded successfully');
    console.log('⏳ Waiting 20 seconds for fingerprint analysis...');
    
    // Wait for analysis to complete
    await new Promise(resolve => setTimeout(resolve, 20000));
    
    // Extract some basic results
    const results = await page.evaluate(() => {
      const trustScore = document.querySelector('#fingerprint-data .visitor-entropy');
      const lies = Array.from(document.querySelectorAll('.lies')).map(el => el.textContent.trim());
      
      return {
        trustScore: trustScore ? trustScore.textContent.trim() : 'Not found',
        detectedLies: lies.length > 0 ? lies : ['None detected'],
        url: window.location.href,
        userAgent: navigator.userAgent
      };
    });
    
    console.log('📊 Quick Results:');
    console.log(`Trust Score: ${results.trustScore}`);
    console.log(`Detected Issues: ${results.detectedLies.length > 1 ? results.detectedLies.join(', ') : 'None'}`);
    
    // Take screenshot
    await page.screenshot({ 
      path: 'fingerprint_spoofed_results.png', 
      fullPage: true 
    });
    
    console.log('📸 Screenshot saved to: fingerprint_spoofed_results.png');
    console.log('🎯 Analysis complete! Check the browser window and screenshot for detailed results.');
    
  } catch (error) {
    console.error('❌ Error:', error.message);
  }
  
  // Keep browser open for manual inspection
  console.log('🔍 Browser will remain open for manual inspection. Close when done.');
  
  // Uncomment the line below to auto-close after 60 seconds
  // setTimeout(() => browser.close(), 60000);
})();

// ===== FINGERPRINT SPOOFING FUNCTIONS =====
async function applyFingerprintSpoofing(page, config) {
  console.log('🎭 Applying fingerprint spoofing...');
  
  // Set User Agent
  if (config.enableSpoofing.userAgent) {
    await page.setUserAgent(config.userAgent);
    console.log('✅ User Agent spoofed');
  }
  
  // Set Viewport
  await page.setViewport(config.viewport);
  
  // Set Geolocation
  await page.setGeolocation(config.geolocation);
  
  // Set Language
  await page.setExtraHTTPHeaders({
    'Accept-Language': config.languages.join(',')
  });
  
  // Advanced spoofing via page.evaluateOnNewDocument
  await page.evaluateOnNewDocument((config) => {
    // Screen spoofing
    if (config.enableSpoofing.screen) {
      Object.defineProperty(screen, 'width', { value: config.screen.width });
      Object.defineProperty(screen, 'height', { value: config.screen.height });
      Object.defineProperty(screen, 'colorDepth', { value: config.screen.colorDepth });
      Object.defineProperty(screen, 'pixelDepth', { value: config.screen.pixelDepth });
    }
    
    // Hardware spoofing
    if (config.enableSpoofing.hardware) {
      Object.defineProperty(navigator, 'deviceMemory', { value: config.deviceMemory });
      Object.defineProperty(navigator, 'hardwareConcurrency', { value: config.hardwareConcurrency });
      Object.defineProperty(navigator, 'platform', { value: config.platform });
    }
    
    // Timezone spoofing
    if (config.enableSpoofing.timezone) {
      const originalDateTimeFormat = Intl.DateTimeFormat;
      Intl.DateTimeFormat = function(...args) {
        if (args.length === 0 || (args[0] && args[0].timeZone === undefined)) {
          args[1] = args[1] || {};
          args[1].timeZone = config.timezone;
        }
        return new originalDateTimeFormat(...args);
      };
      
      // Spoof Date.prototype.getTimezoneOffset
      const originalGetTimezoneOffset = Date.prototype.getTimezoneOffset;
      Date.prototype.getTimezoneOffset = function() {
        // Return offset for spoofed timezone (simplified)
        const timezoneOffsets = {
          'America/New_York': 300, // EST
          'Europe/London': 0,      // GMT
          'Asia/Tokyo': -540,      // JST
          'America/Los_Angeles': 480 // PST
        };
        return timezoneOffsets[config.timezone] || originalGetTimezoneOffset.call(this);
      };
    }
    
    // Canvas fingerprint spoofing
    if (config.enableSpoofing.canvas) {
      const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
      const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
      
      HTMLCanvasElement.prototype.toDataURL = function(...args) {
        // Add slight noise to canvas output
        const originalResult = originalToDataURL.apply(this, args);
        return originalResult.replace(/.$/, Math.random().toString(36).substr(2, 1));
      };
      
      CanvasRenderingContext2D.prototype.getImageData = function(...args) {
        const imageData = originalGetImageData.apply(this, args);
        // Add minimal noise to image data
        for (let i = 0; i < imageData.data.length; i += 4) {
          if (Math.random() < 0.001) { // Very small chance to modify pixel
            imageData.data[i] = Math.min(255, imageData.data[i] + Math.floor(Math.random() * 3) - 1);
          }
        }
        return imageData;
      };
    }
    
    // WebGL spoofing
    if (config.enableSpoofing.webgl) {
      const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
      WebGLRenderingContext.prototype.getParameter = function(parameter) {
        if (parameter === 37445) { // UNMASKED_VENDOR_WEBGL
          return config.webglVendor;
        }
        if (parameter === 37446) { // UNMASKED_RENDERER_WEBGL
          return config.webglRenderer;
        }
        return originalGetParameter.call(this, parameter);
      };
    }
    
    // Plugin spoofing
    if (config.enableSpoofing.plugins) {
      Object.defineProperty(navigator, 'plugins', {
        value: [
          {
            name: 'Chrome PDF Plugin',
            filename: 'internal-pdf-viewer',
            description: 'Portable Document Format'
          }
        ]
      });
    }
    
    // Battery API spoofing
    if (config.enableSpoofing.battery && 'getBattery' in navigator) {
      const originalGetBattery = navigator.getBattery;
      navigator.getBattery = async function() {
        const battery = await originalGetBattery.call(this);
        return {
          ...battery,
          level: 0.85,
          charging: true,
          chargingTime: 3600,
          dischargingTime: Infinity
        };
      };
    }
    
    // Languages spoofing
    Object.defineProperty(navigator, 'languages', { value: config.languages });
    Object.defineProperty(navigator, 'language', { value: config.languages[0] });
    
  }, config);
  
  console.log('✅ Advanced fingerprint spoofing applied');
}

// ===== USAGE INSTRUCTIONS =====
/*
HOW TO CUSTOMIZE:

1. CHANGE USER AGENT:
   - Modify `FINGERPRINT_CONFIG.userAgent`
   - Use different browser signatures from: https://www.whatismybrowser.com/guides/the-latest-user-agent/

2. CHANGE SCREEN RESOLUTION:
   - Modify `FINGERPRINT_CONFIG.screen` values
   - Common resolutions: 1920x1080, 1366x768, 1440x900

3. CHANGE TIMEZONE:
   - Modify `FINGERPRINT_CONFIG.timezone`
   - Valid zones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

4. CHANGE LOCATION:
   - Modify `FINGERPRINT_CONFIG.geolocation`
   - Use coordinates from Google Maps

5. ENABLE/DISABLE SPOOFING:
   - Toggle options in `FINGERPRINT_CONFIG.enableSpoofing`

6. WEBGL SPOOFING:
   - Change webglVendor and webglRenderer to match different graphics cards
   - Examples: "NVIDIA Corporation" / "GeForce GTX 1060"

TESTING DIFFERENT PROFILES:
- Create multiple config objects for different "personas"
- Test mobile vs desktop fingerprints
- Compare results with and without spoofing
*/

Use Cases for Developers and Researchers

CreepJS is a helpful tool in many development and research environments:

  • Privacy exposure analysis. Developers use CreepJS to see what data their apps or browsers expose to fingerprinting scripts.
  • Stealth plugin validation. Researchers can use CreepJS to verify whether spoofing tools (like stealth plugins or anti-detect browsers) are working as expected.
  • Environment fingerprint comparison. QA teams can compare fingerprint outputs across different setups to understand behavioral differences in browser detection.

If you’re interested in exploring similar tools, check out our list of top anti-detect browsers .

Conclusion

CreepJS is a powerful tool for analyzing browser fingerprints. It lets users and developers understand what identifying traits are exposed to websites. While it doesn’t spoof or modify browser fingerprints, it’s an essential tool in testing and validating privacy setups or anti-fingerprinting tools.

Create Account

Author

Vilius Dumcius

Product Owner

With six years of programming experience, Vilius specializes in full-stack web development with PHP (Laravel), MySQL, Docker, Vue.js, and Typescript. Managing a skilled team at IPRoyal for years, he excels in overseeing diverse web projects and custom solutions. Vilius plays a critical role in managing proxy-related tasks for the company, serving as the lead programmer involved in every aspect of the business. Outside of his professional duties, Vilius channels his passion for personal and professional growth, balancing his tech expertise with a commitment to continuous improvement.

Learn More About Vilius Dumcius
Share on

Related articles