Back to Blog
Getting Started

Playwright Browser Automation with Fingerprint Profiles

Complete guide to integrating Playwright with fingerprint-consistent browser profiles, proxy support, and multi-context automation.

Introduction

Playwright is Microsoft's open-source browser automation framework, known for its reliable auto-waiting, multi-browser support, and powerful API for controlling browser behavior. BotBrowser replaces the standard Chromium binary with one that produces consistent fingerprint output controlled by profile files. Together, Playwright handles the automation logic while BotBrowser handles the browser identity layer.

This guide covers everything you need to get started: installation, basic launch configuration, proxy setup, multiple browser contexts, viewport management, common pitfalls, and production deployment patterns. By the end, you will have a working setup that combines Playwright's automation capabilities with BotBrowser's fingerprint control.

Privacy Impact: Why Playwright + BotBrowser

Standard Playwright uses a stock Chromium binary that exposes the real system's fingerprint. Every browser instance reveals the same host machine characteristics: the same GPU, the same fonts, the same screen resolution, and automation-specific signals that indicate the browser is being controlled programmatically.

BotBrowser changes this equation. Each browser instance can load a different fingerprint profile, presenting a unique browser identity that is consistent across all signals. The automation framework handles navigation, data extraction, and interaction logic. The browser identity layer handles making each instance look like a distinct, legitimate browser session.

This separation of concerns is clean and practical. You do not need to modify your Playwright automation code to work with BotBrowser. The integration happens at the launch configuration level, and everything else, page interactions, selectors, assertions, network interception, works exactly as it does with standard Playwright.

Technical Background

Why playwright-core, Not playwright

The standard playwright npm package bundles its own Chromium binary. When you install playwright, it downloads and manages browser binaries automatically. This is convenient for general use but conflicts with BotBrowser, which provides its own modified Chromium binary.

The playwright-core package provides the same API without bundled browsers. It requires you to specify an executablePath when launching, which is exactly what you need to point Playwright at the BotBrowser binary.

# Install playwright-core, not playwright
npm install playwright-core

How Launch Configuration Works

When you call chromium.launch(), Playwright spawns a Chrome process with the specified arguments. BotBrowser-specific arguments (--bot-profile, --bot-config-*, etc.) are passed through the args array and processed by the BotBrowser binary during initialization.

The launch process:

  1. Playwright calls the BotBrowser executable with the provided arguments
  2. BotBrowser loads the specified profile and applies all fingerprint settings
  3. BotBrowser starts the Chrome DevTools Protocol (CDP) server
  4. Playwright connects to the CDP server and takes control of automation
  5. From this point, all Playwright operations work as normal

Browser Contexts in Playwright

Playwright's browser context is an isolated browser session with its own cookies, storage, and cache. Each context within a browser instance shares the same fingerprint profile (since the profile is loaded at the browser level), but has independent state.

For different fingerprint identities, you launch separate browser instances, each with its own profile. For multiple sessions sharing the same identity, you create multiple contexts within a single browser instance.

Common Approaches and Their Limitations

Using Playwright's Built-in Browsers

Playwright's bundled Chromium works for general automation but has no fingerprint control. Every instance has the same fingerprint (the host machine's), and automation indicators like navigator.webdriver are present.

Using Custom Chromium Builds

Some teams build custom Chromium with specific patches. This requires maintaining a build pipeline, tracking upstream Chromium updates, and managing binary distribution. BotBrowser handles all of this, providing ready-to-use binaries with fingerprint control built in.

JavaScript-Level Fingerprint Overrides

Injecting JavaScript to override navigator properties, canvas rendering, and other signals is a common approach. However, JavaScript injection operates after page creation and can be detected through timing analysis, prototype chain inspection, and other methods. BotBrowser applies fingerprint control at the engine level, before any JavaScript executes.

BotBrowser's Approach

BotBrowser integrates with Playwright through the standard executablePath parameter. No Playwright plugins, patches, or special APIs are needed.

Minimal Integration

The simplest integration requires three things:

  1. playwright-core installed (not playwright)
  2. The BotBrowser binary path
  3. A fingerprint profile file

Everything else is standard Playwright code.

Engine-Level Control

Because BotBrowser modifies the Chromium engine itself, all fingerprint control happens before Playwright connects. By the time your Playwright script starts running, the browser already has its complete fingerprint identity. This means:

  • Fingerprint signals are present from the first page load
  • No "setup" phase is needed in your automation code
  • All Playwright features (contexts, pages, network interception) work as documented

Configuration and Usage

Prerequisites

  • BotBrowser binary (download from GitHub)
  • A fingerprint profile file (.enc format)
  • Node.js 18+
  • npm install playwright-core

Ensure the BotBrowser binary has execute permissions:

chmod +x /path/to/botbrowser/chrome

Basic Launch

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

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
    ],
    headless: true,
  });

  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://example.com');

  // Your automation logic here
  const title = await page.title();
  console.log('Page title:', title);

  await browser.close();
})();

Profile + Proxy + Locale

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--proxy-server=socks5://user:pass@proxy:1080',
    '--bot-config-timezone=America/New_York',
    '--bot-config-locale=en-US',
    '--bot-config-languages=en-US,en',
  ],
  headless: true,
});

Multiple Contexts (Same Identity)

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
  ],
  headless: true,
});

// Two isolated sessions sharing the same fingerprint
const context1 = await browser.newContext();
const context2 = await browser.newContext();

const page1 = await context1.newPage();
const page2 = await context2.newPage();

await page1.goto('https://example.com');
await page2.goto('https://example.org');

// Each context has independent cookies and storage
// Both share the same fingerprint profile

Multiple Identities (Separate Browsers)

async function createIdentity(profilePath, proxyUrl) {
  const args = [
    `--bot-profile=${profilePath}`,
  ];
  if (proxyUrl) args.push(`--proxy-server=${proxyUrl}`);

  return chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args,
    headless: true,
  });
}

const identity1 = await createIdentity(
  '/profiles/win11-us.enc',
  'socks5://user:pass@us-proxy:1080'
);
const identity2 = await createIdentity(
  '/profiles/win11-de.enc',
  'socks5://user:pass@de-proxy:1080'
);

// Each browser instance has a unique fingerprint

Network Interception

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

// Intercept requests - works the same as standard Playwright
await page.route('**/*.png', route => route.abort());
await page.route('**/api/**', route => {
  console.log('API request:', route.request().url());
  route.continue();
});

await page.goto('https://example.com');

Viewport Management

// Option 1: Let the profile control viewport (recommended)
const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
  ],
  headless: true,
});
const context = await browser.newContext(); // No viewport override

// Option 2: Explicit viewport (may conflict with mobile profiles)
const context2 = await browser.newContext({
  viewport: { width: 1920, height: 1080 },
});

Screenshots and PDF

const page = await context.newPage();
await page.goto('https://example.com');

// Screenshot - works as normal
await page.screenshot({ path: 'screenshot.png', fullPage: true });

// PDF generation
await page.pdf({ path: 'page.pdf', format: 'A4' });

Verification

Verify the integration is working by checking fingerprint signals:

const page = await context.newPage();
await page.goto('https://example.com');

const fingerprint = await page.evaluate(() => ({
  userAgent: navigator.userAgent,
  platform: navigator.platform,
  languages: navigator.languages,
  hardwareConcurrency: navigator.hardwareConcurrency,
  deviceMemory: navigator.deviceMemory,
  webdriver: navigator.webdriver,
  maxTouchPoints: navigator.maxTouchPoints,
  screenWidth: screen.width,
  screenHeight: screen.height,
  dpr: devicePixelRatio,
}));

console.log('Browser fingerprint:', JSON.stringify(fingerprint, null, 2));
Playwright + BotBrowser Architecture Your Script Automation logic Playwright CDP protocol BotBrowser Identity layer Script controls behavior. Playwright controls automation. BotBrowser controls identity. Standard Playwright API - no plugins or patches needed

Best Practices

  • Use playwright-core, not the full playwright package. The full package downloads its own Chromium, which you do not need.
  • Use absolute paths for --bot-profile. Relative paths may resolve incorrectly depending on the working directory.
  • Do not set viewport on browser contexts unless you specifically need to override the profile's viewport. Let the profile control display dimensions.
  • Set DISPLAY=:10.0 when running on Linux servers, even in headless mode.
  • Use separate browser instances for separate identities. Browser contexts share the same fingerprint. For different identities, launch different browsers.
  • Close browsers when done. Each browser instance is a Chrome process. Unclosed instances consume memory and CPU.
  • Handle launch errors. Check that the binary path is correct and the binary has execute permissions if launch fails.

Frequently Asked Questions

Can I use the full playwright package instead of playwright-core?

Technically yes, but it will download an unnecessary Chromium binary. Use playwright-core to avoid the extra download and to make it clear that you are using a custom browser binary.

Do I need to disable navigator.webdriver?

BotBrowser handles automation signal control through the profile. You do not need to add JavaScript to modify navigator.webdriver or other automation indicators.

Can I use Playwright's codegen or inspector with BotBrowser?

Yes. Playwright's codegen tool works with BotBrowser when you specify the executable path. Run npx playwright codegen --browser-channel=chromium and configure the custom executable in your Playwright config.

How do I run BotBrowser with Playwright on Ubuntu?

Set the DISPLAY environment variable and install required libraries:

export DISPLAY=:10.0
# Install dependencies if needed
apt-get install -y libnss3 libatk-bridge2.0-0 libdrm2 libxrandr2 libgbm1

Can I use Playwright's per-context proxy with BotBrowser?

BotBrowser supports per-context proxy through its own mechanism. Using --proxy-server sets the browser-level proxy. For per-context proxy, use BotBrowser's per-context fingerprint feature (ENT Tier1), which auto-derives geographic information. Avoid Playwright's page.authenticate() for proxy auth, as it can interfere with BotBrowser's geo-detection.

How many concurrent browser instances can I run?

This depends on your system resources. Each BotBrowser instance is a Chrome process that typically uses 200-500 MB of RAM. A server with 32 GB of RAM can comfortably run 30-60 concurrent instances, depending on page complexity.

Does Playwright's tracing and debugging work with BotBrowser?

Yes. Playwright's trace viewer (context.tracing.start()), screenshots, and video recording all work normally with BotBrowser.

Can I use TypeScript with playwright-core?

Yes. playwright-core includes TypeScript type definitions. Use it the same way as standard Playwright with TypeScript:

import { chromium, Browser, Page } from 'playwright-core';

Summary

Integrating BotBrowser with Playwright requires minimal changes to standard Playwright code: install playwright-core, point executablePath to the BotBrowser binary, and add --bot-profile to the launch arguments. Everything else, page interactions, network interception, screenshots, assertions, works exactly as documented in Playwright's API.

For related topics, see Getting Started with Puppeteer for the Puppeteer equivalent, CLI Recipes for more flag combinations, and Profile Management for organizing profiles.

#playwright#automation#getting-started#tutorial