How to Run Multiple Browser Identities from a Single Docker Container Using CloakBrowser
CloakBrowser's cloakserve binary runs a single Chromium process that multiplexes independent browser instances through CDP connections, each configured via unique fingerprint seeds passed as URL query parameters.
CloakBrowser is a stealth browser automation platform that isolates browser identities through fingerprint randomization. By leveraging the cloakserve multiplexer inside a Docker container, you can spawn dozens of isolated browser contexts from one lightweight process rather than managing separate containers for each identity.
Understanding the CloakBrowser Architecture
The cloakserve CDP Multiplexer
At the core of this deployment is cloakserve, a lightweight binary located in bin/cloakserve within the CloakBrowser repository. Unlike traditional browser automation setups that launch a new Chromium instance per container, cloakserve initializes a single stealth-patched Chromium process that acts as a CDP (Chrome DevTools Protocol) multiplexer.
According to the CloakBrowser source code, when cloakserve receives an incoming WebSocket connection, it parses query parameters to determine the browser identity. Each unique connection spawns a new browser process (or reuses an existing one if the same fingerprint seed is supplied), allowing multiple simultaneous identities to operate from the same container without cross-contamination.
Configuring Browser Identities via Query Parameters
Fingerprint Seeds and Isolation
The fingerprint query parameter acts as the primary seed for generating browser identity characteristics. When you connect to http://localhost:9222?fingerprint=12345, CloakBrowser:
- Generates unique canvas noise patterns
- Randomizes WebGL parameters and hardware concurrency values
- Sets timezone, locale, and platform attributes
As implemented in cloakbrowser/browser.py, these parameters translate into --fingerprint-* arguments passed to the Chromium binary. Two connections using different seeds operate as completely independent identities, while identical seeds share processes to conserve resources.
Additional Configuration Flags
You can extend identity customization through additional query parameters:
timezone– Override the browser's timezone (e.g.,timezone=Asia/Tokyo)locale– Set Accept-Language headers and navigator.languageplatform– Manipulate navigator.platform and user-agent OS indicatorsproxy– Route traffic through specific proxies (HTTP/SOCKS5)user-data-dir– Persist cookies and localStorage across sessionsgeoip– Enable automatic geolocation spoofing based on IP
Docker Deployment Strategies
Docker Compose Setup
Create a docker-compose.yml file that exposes the CDP port and starts the multiplexer:
services:
cloakbrowser:
image: cloakhq/cloakbrowser
command: cloakserve
ports:
- "127.0.0.1:9222:9222"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9222/json/version"]
interval: 30s
timeout: 5s
retries: 3
This configuration makes the CDP endpoint available at http://localhost:9222, ready to accept multiple simultaneous connections with varying identity parameters.
Per-Connection Identity Isolation
The multiplexer distinguishes identities solely through URL query parameters. This architecture eliminates the need to spawn separate Docker containers for each browser profile, significantly reducing overhead while maintaining strict isolation between contexts.
Practical Implementation Examples
Python Playwright Integration
Connect multiple independent identities from a single Python script using Playwright:
from playwright.sync_api import sync_playwright
def launch_identity(seed, extra_params=""):
url = f"http://localhost:9222?fingerprint={seed}{extra_params}"
playwright = sync_playwright().start()
browser = playwright.chromium.connect_over_cdp(url)
context = browser.new_context()
page = context.new_page()
page.goto("https://example.com")
print(f"Seed {seed} → title:", page.title())
context.close()
browser.close()
playwright.stop()
# Launch three completely isolated browser identities
launch_identity(11111)
launch_identity(22222, "&timezone=Europe/London&proxy=http://proxy:8080")
launch_identity(33333, "&user-data-dir=/profile&geoip=true")
Node.js JavaScript Example
The same pattern works for Node.js automation using Playwright or Puppeteer:
import { chromium } from 'playwright';
async function launchIdentity(seed, extraParams = '') {
const url = `http://localhost:9222?fingerprint=${seed}${extraParams}`;
const browser = await chromium.connectOverCDP(url);
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
console.log(`Seed ${seed} → title:`, await page.title());
await context.close();
await browser.close();
}
// Execute multiple identities concurrently
await launchIdentity(11111);
await launchIdentity(22222, '&timezone=America/New_York&proxy=socks5://user:pass@proxy:1080');
await launchIdentity(33333, '&user-data-dir=/profile&locale=en-US');
One-Off Execution with docker run
For ephemeral automation tasks without Compose, mount a profile volume and execute inline:
docker run --rm -v $(pwd)/my-profile:/profile \
cloakhq/cloakbrowser python - <<'PY'
from cloakbrowser import launch
browser = launch(args=["--fingerprint=55555",
"--user-data-dir=/profile"])
page = browser.new_page()
page.goto('https://example.com')
print(page.title())
browser.close()
PY
This pattern mounts $(pwd)/my-profile to /profile inside the container, enabling cookie and session persistence across container restarts.
Persisting Profiles Across Sessions
When you need persistent storage rather than fresh incognito contexts, mount a host volume to /profile (or your preferred path) and pass the user-data-dir parameter. The examples/persistent_context.py file in the repository demonstrates mounting volumes to preserve:
- Cookies and localStorage data
- Browser cache and IndexedDB
- Authentication sessions
This configuration proves essential for workflows requiring "warm" profiles with existing login states, while still allowing multiple distinct profiles to operate simultaneously through different fingerprint seeds.
Resource Efficiency and Performance
Running multiple identities from a single container offers substantial resource savings compared to per-container deployments. According to the CloakBrowser documentation:
- One Chromium instance consumes approximately 190 MiB RAM when idle
- Each additional tab adds roughly 30 MiB of memory overhead
Rather than multiplying these costs across separate Docker containers, cloakserve amortizes the base memory requirement across all active identities, making it feasible to run 50+ concurrent browser contexts on modest hardware.
Summary
- Single-process architecture: The
cloakservebinary inbin/cloakserveruns one Chromium instance that multiplexes multiple browser identities via CDP connections - Seed-based isolation: The
fingerprintquery parameter generates unique browser characteristics (canvas noise, WebGL, hardware specs) per connection - Query parameter configuration: Pass
timezone,proxy,locale, anduser-data-dirdirectly in the connection URL to customize each identity - Volume persistence: Mount host directories to
/profileand specifyuser-data-dirto maintain state across container restarts - Resource efficiency: Share ~190 MiB base memory across unlimited identities rather than spawning separate containers
Frequently Asked Questions
What makes cloakserve more efficient than running separate Docker containers per browser?
cloakserve eliminates the overhead of multiple Chromium binaries and container layers by running a single stealth-patched process that handles all CDP connections. This architecture reduces base RAM consumption from multiples of ~190 MiB to a single instance, while the cloakbrowser wrapper in cloakbrowser/browser.py automatically manages process isolation through fingerprint seeds.
How does CloakBrowser ensure identities remain isolated when sharing the same Chromium process?
Each CDP connection receives a unique browser context determined by the fingerprint seed and other query parameters. The source code in bin/cloakserve parses these parameters to generate distinct browser fingerprints (canvas noise, WebGL signatures, hardware concurrency) and optionally spawns separate processes per seed, ensuring cookies, localStorage, and cache remain isolated between identities.
Can I persist browser profiles when running multiple identities from one container?
Yes. Mount a host volume to any container path (commonly /profile) and pass user-data-dir=/profile as a query parameter or launch argument. As shown in examples/persistent_context.py, this preserves cookies, authentication states, and localStorage across container restarts while allowing distinct profiles for each fingerprint seed.
Which automation frameworks support CloakBrowser's single-container multiplexer?
Any framework supporting CDP (Chrome DevTools Protocol) connections works with cloakserve, including Playwright (Python and Node.js), Puppeteer, and Selenium with CDP extensions. Connect via http://localhost:9222?fingerprint=YOUR_SEED rather than launching local browser binaries, and the framework will treat each connection as a standard Chromium instance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →