How to Run Cloakserve CDP Multiplexer with Per-Connection Fingerprint Seeds
Cloakserve rewrites Chrome DevTools Protocol URLs to embed unique fingerprint seeds per connection, enabling deterministic browser fingerprinting by accepting a fingerprint query parameter that injects the seed into WebSocket paths.
Cloakserve is the CDP multiplexer that ships with CloakBrowser, acting as a transparent proxy between automation clients and Chrome instances. By parsing per-connection fingerprint seeds from incoming requests, it allows each WebSocket connection to receive a deterministic, unique browser identity without spawning separate Chrome processes.
Understanding Fingerprint Seed Architecture
The multiplexer intercepts standard Chrome debugging endpoints (e.g., ws://127.0.0.1:9222/devtools/browser/…) and modifies the returned JSON to include connection-specific identifiers. According to the CloakHQ/CloakBrowser source code, this transformation happens at the WebSocket level, where a seed value drives the human-interaction layer (mouse movements, keyboard timing, hardware concurrency) to produce reproducible fingerprints.
The system operates through two primary mechanisms:
- Per-connection seeds: Extracted from HTTP query parameters (
?fingerprint=<seed>) viaparse_connection_params - Default global seeds: Set via command-line arguments (
--fingerprint=<seed>) parsed byparse_cli_args
Parsing Connection Parameters
The parse_connection_params function in tests/test_cloakserve.py (lines 31-66) handles the extraction of query-string parameters from client requests. When a client connects to http://localhost:9222?fingerprint=12345, this function:
- Parses the query string for a
fingerprintkey - Stores the value as a
seedfor URL rewriting - Builds additional Chrome flags from other fingerprint-related parameters (proxy, timezone, locale)
Without an explicit seed parameter, the system falls back to the global default configured at startup.
Starting the Multiplexer
Launch Cloakserve using the cloakserve binary found in bin/cloakserve. The executable wires together parse_cli_args, initializes an aiohttp server, and forwards filtered arguments to Chrome.
# Start with default port 9222 and visible Chrome window
cloakserve --port=9222 --headless=false
The parse_cli_args function (defined in tests/test_cloakserve.py, lines 84-112) consumes the --fingerprint=<seed> flag as a default seed. This guarantees that connections omitting query parameters still receive deterministic fingerprints:
# Apply seed 9999 to all connections without explicit query params
cloakserve --port=9222 --fingerprint=9999
Connecting Clients with Unique Seeds
Each client identifies itself by appending ?fingerprint=<seed> to the HTTP endpoint. The multiplexer rewrites the returned DevTools URLs to embed the seed in the path structure:
- Without seed:
ws://host:9222/devtools/browser/<guid> - With seed:
ws://host:9222/fingerprint/12345/devtools/browser/<guid>
Request distinct fingerprints by varying the query string:
# Session A with seed 111
curl http://localhost:9222?fingerprint=111
# Session B with seed 222
curl http://localhost:9222?fingerprint=222
Separate browser tabs or automation scripts can therefore request different platform signatures, GPU vendors, and hardware concurrency values simply by changing the seed value, while sharing a single Chrome binary instance managed by the ChromePool in cloakbrowser/browser.py.
Configuring Per-Connection Chrome Flags
Beyond seeds, Cloakserve accepts additional fingerprint-modifying parameters via query string. As implemented in cloakbrowser/human/config.py, these parameters translate into Chrome command-line flags at connection time:
# Combine fingerprint seed with proxy and locale settings
curl "http://localhost:9222?fingerprint=123&proxy=http://myproxy:8080&locale=fr-FR"
The parse_connection_params function aggregates these options alongside the seed value, ensuring each connection receives a tailored Chrome launch configuration without affecting other active sessions.
Key Implementation Files
| Path | Role |
|---|---|
bin/cloakserve |
Executable entry point that initializes the aiohttp server and wires argument parsing |
tests/test_cloakserve.py |
Contains parse_connection_params (lines 31-66) and parse_cli_args (lines 84-112) logic |
cloakbrowser/config.py |
Global configuration schema including default_seed entries |
cloakbrowser/human/config.py |
Per-connection fingerprint options mapped to Chrome flags |
cloakbrowser/browser.py |
ChromePool implementation for spawning Chrome instances |
Summary
- Cloakserve acts as a CDP multiplexer that injects fingerprint seeds into WebSocket URLs returned to clients
- Use
?fingerprint=<seed>in HTTP requests to assign specific seeds to individual connections - Set global defaults with
--fingerprint=<seed>when launching the multiplexer to handle connections without explicit parameters - The
parse_connection_paramsfunction intests/test_cloakserve.pyextracts seeds and builds Chrome flag lists from query strings - URL rewriting transforms standard DevTools endpoints to include
/fingerprint/<seed>/paths, enabling deterministic fingerprinting per connection
Frequently Asked Questions
How does Cloakserve handle connections without a fingerprint parameter?
If a client connects without specifying ?fingerprint=<seed>, Cloakserve falls back to the default seed provided via the --fingerprint command-line argument parsed by parse_cli_args. If no default is configured, the system assigns seeds according to the logic defined in cloakbrowser/config.py, ensuring every connection maintains deterministic fingerprinting behavior.
Can different connections use different proxy or locale settings simultaneously?
Yes. The parse_connection_params function processes multiple query parameters concurrently. Each connection can specify unique combinations of fingerprint, proxy, locale, and timezone parameters, with the multiplexer translating these into isolated Chrome command-line flags for that specific WebSocket session without affecting other active connections.
Where does the URL rewriting logic reside?
The URL transformation logic that converts ws://host:9222/devtools/browser/<guid> to ws://host:9222/fingerprint/<seed>/devtools/browser/<guid> is exercised in tests/test_cloakserve.py under the TestURLRewriting test cases. The production implementation handles this rewrite when returning the JSON list of available DevTools pages to the client.
What is the relationship between fingerprint seeds and the ChromePool?
The ChromePool class in cloakbrowser/browser.py manages Chrome instance spawning. When a client connects with a specific fingerprint seed, the multiplexer communicates that seed and associated flags to the pool, which launches or reuses a Chrome process configured with those specific parameters. This allows multiple connections with different seeds to share Chrome infrastructure while maintaining isolated fingerprint identities.
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 →