Skip to Content
Identity & SessionPer-Context Fingerprint

Per-Context Fingerprint (ENT Tier3)

Run multiple independent fingerprint identities within a single browser instance. Shared GPU/Network/Browser processes. Reduced resource overhead.

The Problem

Traditional approaches require launching a separate browser instance for each fingerprint profile. This architecture has significant overhead due to Chromium’s multi-process design.

Chromium Process Architecture

Each browser instance spawns multiple processes:

ProcessFunction
Browser processMain coordinator, UI, profile management
GPU processGraphics API calls, compositing, hardware acceleration
Network processHTTP/HTTPS requests, DNS resolution, WebSocket
Utility processesAudio, video decoding, extension services
Renderer processesWeb page execution, JavaScript, DOM

Running 50 browser instances means 50 GPU processes, 50 Network processes, and 50+ Utility processes, in addition to the renderer processes.

Process Startup Cost

  • Each browser instance requires full initialization: loading shared libraries, spawning GPU/Network/Utility processes, initializing the JavaScript engine, and establishing IPC channels
  • Disk I/O spikes occur as each instance reads profile data, cache structures, and font resources from storage
  • CPU-intensive work happens during V8 isolate creation, Blink initialization, and compositor setup

Per-Instance Resource Duplication

  • GPU process: shader cache, command buffers, GPU memory allocation duplicated per instance
  • Network process: connection pools, DNS cache, certificate cache duplicated per instance
  • Each instance maintains its own JavaScript VM heap (typically 64-128 MB minimum)
  • Internal caches (HTTP cache, font cache) cannot be shared across instances

Scaling Limitations

  • Running 50 profiles means 50 browser instances with 200+ total processes
  • CPU load scales with process count due to duplicated background tasks (garbage collection, network polling, GPU command processing)
  • OS scheduler overhead increases with process count

The Solution

Per-Context Fingerprint assigns a complete fingerprint bundle to each BrowserContext within a single browser instance. One browser process, one GPU process, one Network process, serving multiple fingerprint identities.

Shared Process, Isolated Fingerprint

BotBrowser modifies Chromium’s shared processes to be fingerprint-aware:

Shared ProcessPer-Context Isolation
GPU processCanvas/WebGL/WebGPU noise applied per-context
Network processProxy routing, IP detection per-context
Audio serviceAudioContext noise seed per-context
Browser processTimezone, locale, screen metrics per-context

Each context operates with its own:

  • Profile file (via --bot-profile)
  • User-Agent and userAgentData
  • Device model and platform
  • Screen resolution and color depth
  • Timezone, locale, and languages
  • Canvas/WebGL/Audio noise seeds
  • Proxy configuration and public IP
  • Most --bot-* CLI flags (see Supported Flags)

Contexts are isolated within BotBrowser’s fingerprint model. Pages in Context A cannot detect or influence the fingerprint of Context B. The shared GPU/Network/Utility processes route fingerprint-specific data to the correct context.

Why Per-Context Outperforms Multi-Instance

ResourceMulti-Instance (50 profiles)Per-Context (50 contexts)
Browser processes501
GPU processes501
Network processes501
Utility processes50+Shared
Renderer processes50+50+
Total process count200+~55
Browser startup I/O50x (shared libs, GPU init)1x
Add new identity1-3s (launch browser)Fast (create context)

Renderer processes scale with page count in both approaches. The key savings come from sharing GPU, Network, Browser, and Utility processes across all contexts.

For detailed scale benchmarks (memory, process count, creation time at 1/10/25/50 concurrent profiles), see BENCHMARK.md.

Worker Inheritance

Workers created within a BrowserContext automatically inherit that context’s fingerprint:

  • Dedicated Workers: Inherit parent context fingerprint
  • Shared Workers: Inherit parent context fingerprint
  • Service Workers: Inherit parent context fingerprint

No additional configuration needed. Fingerprint consistency is maintained across main thread, workers, and all execution contexts.

Quick Start

Via CDP (Runtime Configuration)

Configure fingerprint flags on an existing BrowserContext.

Critical: BotBrowser.setBrowserContextFlags must be called on a browser-level CDP session, and before any page is created in that context. The renderer process reads its flags at startup. If a page already exists, the flags will not take effect.

const puppeteer = require('puppeteer-core'); const browser = await puppeteer.launch({ executablePath: '/path/to/botbrowser', args: ['--bot-profile=/path/to/base-profile.enc'] }); // Browser-level CDP session (required for BotBrowser.* commands) const client = await browser.target().createCDPSession(); // Create a new browser context const context = await browser.createBrowserContext(); // Set per-context fingerprint flags BEFORE creating any page // Load a different profile and customize locale settings await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: context._contextId, botbrowserFlags: [ '--bot-profile=/path/to/android-profile.enc', '--bot-config-timezone=Asia/Tokyo', '--bot-config-languages=ja-JP,en-US', '--bot-config-locale=ja-JP' ] }); // NOW create a page. The renderer will start with the correct flags. const page = await context.newPage(); await page.goto('https://example.com');

Via Target.createBrowserContext

Pass fingerprint and proxy flags when creating the context:

const client = await browser.target().createCDPSession(); // Fingerprint-only context const { browserContextId } = await client.send('Target.createBrowserContext', { botbrowserFlags: [ '--bot-profile=/path/to/windows-profile.enc', '--bot-config-timezone=America/New_York', '--bot-config-languages=en-US' ] }); // Context with proxy configured at creation time const { browserContextId: ctxWithProxy } = await client.send('Target.createBrowserContext', { botbrowserFlags: [ '--bot-profile=/path/to/profile.enc', '--proxy-server=socks5://user:pass@proxy.example.com:1080', '--proxy-ip=203.0.113.1', '--proxy-bypass-list=localhost;127.0.0.1', '--proxy-bypass-rgx=\\.example\\.com$' ] }); const { targetId } = await client.send('Target.createTarget', { url: 'about:blank', browserContextId });

Multiple Contexts Example

// Browser-level CDP session (reuse for all contexts) const client = await browser.target().createCDPSession(); // Context 1: Windows profile with US location const ctx1 = await browser.createBrowserContext(); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx1._contextId, botbrowserFlags: [ '--bot-profile=/path/to/windows-profile.enc', '--bot-config-timezone=America/Chicago', '--bot-config-languages=en-US' ] }); const page1 = await ctx1.newPage(); // Context 2: macOS profile with UK location const ctx2 = await browser.createBrowserContext(); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx2._contextId, botbrowserFlags: [ '--bot-profile=/path/to/macos-profile.enc', '--bot-config-timezone=Europe/London', '--bot-config-languages=en-GB' ] }); const page2 = await ctx2.newPage(); // Both contexts run simultaneously with completely different fingerprints await Promise.all([ page1.goto('https://example.com'), page2.goto('https://example.com') ]);

Per-Context Proxy with Known IP

Pass the proxy via context creation options, and set --proxy-ip via CDP to skip IP lookups.

Note: Puppeteer uses proxyServer, Playwright uses proxy: { server }. See examples/  for framework-specific syntax.

// Puppeteer example const client = await browser.target().createCDPSession(); // Context 1: US proxy with known IP const ctx1 = await browser.createBrowserContext({ proxyServer: 'socks5://user:pass@us-proxy.example.com:1080' }); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx1._contextId, botbrowserFlags: [ '--bot-profile=/path/to/profile.enc', '--proxy-ip=203.0.113.1' ] }); const page1 = await ctx1.newPage(); // Context 2: UK proxy with known IP const ctx2 = await browser.createBrowserContext({ proxyServer: 'socks5://user:pass@uk-proxy.example.com:1080' }); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx2._contextId, botbrowserFlags: [ '--bot-profile=/path/to/profile.enc', '--proxy-ip=198.51.100.1' ] }); const page2 = await ctx2.newPage(); // All contexts navigate without IP lookup overhead // BotBrowser derives timezone and locale from the provided proxy IP await Promise.all([ page1.goto('https://example.com'), page2.goto('https://example.com') ]);

Per-Context Proxy via botbrowserFlags

Configure proxy and other settings together through botbrowserFlags:

const client = await browser.target().createCDPSession(); // Context 1: US proxy via botbrowserFlags const ctx1 = await browser.createBrowserContext(); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx1._contextId, botbrowserFlags: [ '--bot-profile=/path/to/profile.enc', '--proxy-server=socks5://user:pass@us-proxy.example.com:1080', '--proxy-ip=203.0.113.1', '--proxy-bypass-list=localhost;127.0.0.1', '--bot-config-timezone=America/Chicago' ] }); const page1 = await ctx1.newPage(); // Context 2: UK proxy via botbrowserFlags (with regex bypass) const ctx2 = await browser.createBrowserContext(); await client.send('BotBrowser.setBrowserContextFlags', { browserContextId: ctx2._contextId, botbrowserFlags: [ '--bot-profile=/path/to/profile.enc', '--proxy-server=socks5://user:pass@uk-proxy.example.com:1080', '--proxy-ip=198.51.100.1', '--proxy-bypass-rgx=\\.static\\.example\\.com$', '--bot-config-timezone=Europe/London' ] }); const page2 = await ctx2.newPage(); // Both contexts run with different proxies and settings await Promise.all([ page1.goto('https://example.com'), page2.goto('https://example.com') ]);

Configure proxy directly in botbrowserFlags for unified proxy and fingerprint settings in a single call. Supported proxy flags: --proxy-server, --proxy-ip, --proxy-bypass-list, --proxy-bypass-rgx.

Tip: Need to switch proxies at runtime without restarting a context? See Dynamic Proxy Switching (ENT Tier3) in Advanced Features.

Supported Flags

Most --bot-* flags from CLI_FLAGS.md work with per-context configuration. Browser-level exceptions are noted in Important Notes.

CategoryExample Flags
Profile--bot-profile (load a completely different profile per context)
Noise Seed--bot-noise-seed for deterministic fingerprint variance
Timing--bot-time-scale for performance timing control, --bot-time-seed for deterministic timing diversity, --bot-stack-seed for stack depth variation, --bot-fps for frame rate control
Network--bot-network-info-override for profile-defined navigator.connection values
WebRTC--bot-webrtc-ice for ICE endpoint control
Window--bot-always-active to maintain active window state
Session--bot-inject-random-history for session authenticity (supports precise count, e.g., =15)
Google Headers--bot-enable-variations-in-context for X-Client-Data consistency in incognito contexts (ENT Tier2)
Proxy--proxy-server (configure proxy per-context via botbrowserFlags), --proxy-ip to skip IP lookups
HTTP--bot-custom-headers for custom HTTP request headers per context
Config--bot-config-platform, --bot-config-timezone, --bot-config-noise-canvas, etc.

See CLI_FLAGS.md for the complete flag reference.

Use Cases

Privacy Research at Scale

  • Run fingerprint protection validation across multiple configurations simultaneously
  • Compare behavior across different platform/locale combinations
  • Study tracking mechanisms with controlled, isolated contexts

Cross-Platform Testing

  • Validate application behavior across different platform fingerprints
  • Test localization across multiple locales in parallel
  • Verify responsive behavior across device configurations

Resource-Efficient Automation

  • Reduce infrastructure costs by consolidating browser instances
  • Scale research capacity on CPU-limited environments (VPS, containers)
  • Enable high-concurrency scenarios previously blocked by resource constraints

Important Notes

⚠️ BotBrowser.setBrowserContextFlags must be called on a browser-level CDP session (browser.target().createCDPSession() in Puppeteer, browser.newBrowserCDPSession() in Playwright). Page-level CDP sessions (page.createCDPSession()) do not have access to the BotBrowser domain.

⚠️ setBrowserContextFlags must be called before creating any page in that context. The renderer process reads its flags at startup. If a page already exists, the new flags will not apply to that renderer. Correct order: createBrowserContextsetBrowserContextFlagsnewPage.

⚠️ Per-context proxy via botbrowserFlags or createBrowserContext must be set before navigation. To switch proxies at runtime, use BotBrowser.setBrowserContextProxy (ENT Tier3). See Dynamic Proxy Switching.

⚠️ Some network-layer settings (--bot-local-dns, UDP proxy support) apply at the browser level and cannot be configured per-context.

⚠️ Each context can load a completely different profile (--bot-profile), or use --bot-config-* flags to override specific settings from the browser’s base profile.

Related guides: Multi-Account Isolation, Per-Context Proxy, Dynamic Proxy Switching


Legal Disclaimer & Terms of Use Responsible Use Guidelines . BotBrowser is for authorized fingerprint protection and privacy research only.