Back to Blog
Getting Started

How to Verify Your Browser Fingerprint: Testing Guide

Test and validate browser fingerprint consistency using CreepJS, Pixelscan, Iphey, and automated verification scripts.

Introduction

Configuring BotBrowser with a profile and proxy is only half the job. Without verification, you have no way to confirm that your fingerprint is actually consistent, realistic, and free of internal contradictions. A timezone mismatch, a WebRTC leak, or a Canvas hash that changes between page loads can undermine your entire setup without any visible error.

Verification is the process of checking what your browser actually presents to websites and comparing it against what your profile claims. This guide walks through the major public fingerprint testing tools, explains what to look for in their results, and provides automated scripts for continuous validation in production environments.

Why Verification Matters

Fingerprint protection is not binary. It is not simply "on" or "off." A browser can present most of its fingerprint correctly while leaking a single inconsistent value that makes the entire identity suspicious. Common examples include a browser claiming to be on Windows while reporting a Linux-style font rendering, or a timezone set to Tokyo while the proxy IP geolocates to New York.

These inconsistencies are invisible to the user. The browser functions normally, pages load, and scripts execute. Nothing in the browser's behavior suggests a problem. Only by explicitly testing the fingerprint output can you catch these mismatches before they affect your work.

Verification also serves as a regression check. Browser updates, proxy changes, infrastructure migrations, and profile updates can all introduce subtle changes. Regular verification ensures that your fingerprint protection remains effective over time.

Launch Profile + Proxy Navigate Test Site Analyze Fingerprint Data Validate Consistency Check

Technical Background

What Fingerprint Tests Measure

Public fingerprint testing tools collect values from dozens of browser APIs and check them for internal consistency. The main categories include:

Navigator properties: userAgent, platform, hardwareConcurrency, deviceMemory, languages, and maxTouchPoints. These must agree with each other. A mobile User-Agent with maxTouchPoints: 0 is contradictory.

Display and screen: screen.width, screen.height, window.innerWidth, window.innerHeight, devicePixelRatio, and colorDepth. These should match a real device configuration.

Rendering engines: Canvas 2D output, WebGL parameters (vendor, renderer, extensions, shader precision), and WebGPU adapter info. These values must match the GPU claimed in the profile.

Audio processing: AudioContext properties including sample rate, channel count, and the output of offline audio rendering. These vary by platform and hardware.

Font enumeration: Available font families detected through rendering measurement. The font list should match the claimed operating system.

Network and location: Timezone (via Intl.DateTimeFormat), geolocation API, WebRTC ICE candidates (which can expose local IPs), and Client Hints headers.

Automation signals: navigator.webdriver, CDP artifacts, iframe permission anomalies, and other markers that indicate programmatic control.

Consistency vs. Uniqueness

A good fingerprint is not about being undetectable. It is about being consistent and realistic. Every value should align with a plausible device configuration. The timezone should match the IP geolocation. The GPU renderer should be compatible with the claimed operating system. The font list should include the default fonts for that OS.

Common Approaches and Limitations

Manual Spot Checks

Opening a fingerprint test site in a browser and visually inspecting the results is the most basic approach. It works for initial setup but fails at scale. You cannot manually check every instance in a fleet of 50 browsers, and you will miss subtle issues that are not highlighted in the UI.

Single-Tool Reliance

Each fingerprint testing tool checks different things and weights them differently. CreepJS focuses on hash consistency and trust scoring. Pixelscan checks for automation signals and environmental consistency. Iphey validates browser environment configuration. Relying on a single tool creates blind spots in areas that tool does not cover.

One-Time Testing

Verifying your setup once during initial configuration and never checking again is a common mistake. Browser updates, proxy provider changes, and profile updates can all introduce regressions. Verification needs to be a recurring process.

Ignoring Warnings

Some testing tools display warnings or yellow flags alongside green checkmarks. These partial issues, such as a slightly unusual font list or a non-standard screen resolution, are often dismissed as unimportant. In practice, they can contribute to a risk score that accumulates across multiple signals.

BotBrowser's Approach

BotBrowser controls fingerprint signals at the engine level, which means the values reported to testing tools are set before any page JavaScript executes. This gives BotBrowser a structural advantage over extension-based or injection-based approaches, but verification remains important because configuration errors can still occur.

Consistent Cross-Platform Output

The same profile loaded on Windows, macOS, or Linux produces identical fingerprint output. This means you can verify a profile once on any platform and trust that the results apply everywhere. However, proxy configuration and network-level settings still need per-environment verification.

Auto-Derived Settings

BotBrowser automatically derives timezone, locale, and language settings from your proxy IP. This eliminates an entire category of misconfiguration. When verification tools show a timezone mismatch, the issue is almost always with the proxy, not with BotBrowser.

Deterministic Noise

With --bot-noise-seed, Canvas and audio noise output becomes deterministic. This means the Canvas hash stays the same across page reloads and browser restarts, which is exactly what verification tools look for. Without a noise seed, noise is still applied but may vary slightly between sessions.

Configuration and Usage

CreepJS

CreepJS is the most comprehensive public fingerprint testing tool. Navigate to the site and wait for the analysis to complete. Look for:

  • A consistent trust score (the letter grade and percentage)
  • No red-highlighted sections, which indicate contradictions
  • Matching values between the "lies" section and actual API responses
  • A stable fingerprint hash across multiple page loads

Pixelscan

Pixelscan provides a quick overview of your browser environment. Check for:

  • Green status indicators across all categories
  • No automation detection flags
  • Consistent timezone and geolocation data
  • Matching OS detection between User-Agent and other signals

Iphey

Iphey focuses on browser environment validation. It provides color-coded results where green means consistent and red means problematic. Pay attention to the overall status and any specific warnings about mismatches.

BrowserScan

BrowserScan offers a summary view with WebRTC leak detection and basic fingerprint checks. It is useful as a quick secondary validation.

Automated Verification Script

For production environments, automate verification with a script:

const { chromium } = require('playwright-core');

async function verifyFingerprint(profilePath, proxy) {
  const browser = await chromium.launch({
    executablePath: '/opt/botbrowser/chrome',
    args: [
      `--bot-profile=${profilePath}`,
      `--proxy-server=${proxy}`,
    ],
    headless: true,
  });

  const context = await browser.newContext();
  const page = await context.newPage();

  // Check navigator properties
  const nav = await page.evaluate(() => ({
    userAgent: navigator.userAgent,
    platform: navigator.platform,
    hardwareConcurrency: navigator.hardwareConcurrency,
    deviceMemory: navigator.deviceMemory,
    languages: navigator.languages,
    maxTouchPoints: navigator.maxTouchPoints,
    webdriver: navigator.webdriver,
  }));
  console.log('Navigator:', JSON.stringify(nav, null, 2));

  // Check WebGL
  const webgl = await page.evaluate(() => {
    const canvas = document.createElement('canvas');
    const gl = canvas.getContext('webgl');
    if (!gl) return { error: 'WebGL not available' };
    const ext = gl.getExtension('WEBGL_debug_renderer_info');
    return {
      vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL),
      renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL),
    };
  });
  console.log('WebGL:', JSON.stringify(webgl, null, 2));

  // Check timezone
  const tz = await page.evaluate(() =>
    Intl.DateTimeFormat().resolvedOptions().timeZone
  );
  console.log('Timezone:', tz);

  // Check screen properties
  const screen = await page.evaluate(() => ({
    width: window.screen.width,
    height: window.screen.height,
    availWidth: window.screen.availWidth,
    availHeight: window.screen.availHeight,
    colorDepth: window.screen.colorDepth,
    pixelDepth: window.screen.pixelDepth,
    devicePixelRatio: window.devicePixelRatio,
  }));
  console.log('Screen:', JSON.stringify(screen, null, 2));

  // Check webdriver flag
  if (nav.webdriver === true) {
    console.error('WARNING: navigator.webdriver is true');
  }

  await browser.close();
  return { nav, webgl, tz, screen };
}

// Usage
verifyFingerprint(
  '/opt/profiles/windows-chrome-131.enc',
  'socks5://user:pass@proxy.example.com:1080'
);

Continuous Verification in CI/CD

Add verification to your deployment pipeline:

#!/bin/bash
DISPLAY=:10.0 node verify-fingerprint.js
if [ $? -ne 0 ]; then
  echo "Fingerprint verification failed"
  exit 1
fi
echo "Fingerprint verification passed"

Verification Checklist

Run through this checklist after any configuration change:

CheckToolWhat to Look For
Navigator consistencyCreepJSUA matches platform, touch points match device type
WebGL coherenceCreepJS, BrowserLeaksGPU renderer matches claimed OS
Timezone alignmentPixelscan, BrowserScanTimezone matches proxy IP geolocation
WebRTC privacyBrowserScanNo local IP exposure
Canvas stabilityCreepJSSame hash on multiple reloads
Automation signalsPixelscanNo webdriver or CDP flags
Font consistencyCreepJSFont list matches claimed OS
Audio fingerprintCreepJSConsistent audio hash

Best Practices

Test with multiple tools. No single tool covers everything. Use at least two from the list above for each verification pass.

Verify after every change. Any modification to profiles, proxies, CLI flags, or infrastructure warrants a new verification check.

Use deterministic noise seeds. Set --bot-noise-seed to get reproducible Canvas and audio output, making it easier to verify consistency across runs.

Match proxy to locale. If your proxy IP geolocates to Germany, let BotBrowser auto-derive German timezone and locale, or manually set --bot-config-timezone=Europe/Berlin and --bot-config-locale=de-DE.

Automate for production. Manual verification does not scale. Build verification into your CI/CD pipeline so every deployment is validated before it handles real traffic.

Keep a baseline. Save the output of your verification script as a reference. Compare future runs against this baseline to catch regressions early.

Frequently Asked Questions

How often should I run verification?

At minimum, verify after every configuration change, profile update, or infrastructure modification. For production environments, consider running an automated verification daily or on every deployment.

What if CreepJS shows a low trust score?

A low trust score usually indicates internal contradictions in your fingerprint. Check for timezone mismatches, locale/language inconsistencies, or WebGL values that do not match the claimed platform. Fix these with the appropriate --bot-config-* flags.

Does navigator.webdriver always return false with BotBrowser?

Yes. BotBrowser controls this value at the engine level. If you see navigator.webdriver: true in your verification output, the browser is likely not loading the profile correctly. Check that the profile path is absolute and the format matches your binary type (.enc for release, .json for source builds).

Why does my Canvas hash change between sessions?

Without --bot-noise-seed, BotBrowser applies fresh noise each session. The hash will differ between restarts but remain stable within a session. To get the same hash across restarts, set a fixed noise seed: --bot-noise-seed=12345.

Should I verify in headless or headed mode?

BotBrowser produces the same fingerprint in both modes. Verify in whichever mode your production environment uses. If you run headless in production, verify headless.

What about Client Hints headers?

Client Hints (Sec-CH-UA, Sec-CH-UA-Platform, etc.) are set at the network level and match the profile values. You can verify them by inspecting request headers in your browser's DevTools or by navigating to a site that displays received headers.

Can I verify profiles before deploying them?

Yes. Run the verification script locally with each new profile before adding it to your production environment. This catches any issues with the profile itself before it affects live operations.

What does a "good" verification result look like?

All navigator properties should be internally consistent. The timezone should match the proxy IP. WebGL vendor and renderer should be plausible for the claimed OS. Canvas hash should be stable across reloads. No automation flags should be present. All major testing tools should show green or passing status.

Summary

Verification is not optional in any fingerprint protection workflow. It is the difference between thinking your setup works and knowing it works. Use multiple public testing tools, automate your checks, and verify after every change to maintain consistent, realistic browser identities.

For related guides, see Profile Management for organizing your profiles, CLI Recipes for common flag combinations, and Automation Detection Prevention for eliminating framework signals.

#verification#testing#creepjs#fingerprint#tutorial