The exact fingerprint stack every Browsa browser emits. Published so you can audit it, not just trust the marketing copy.
Why a public spec? Every other "AI agent browser cloud" markets "stealth" or "advanced anti-detect" as a feature but never tells you what's in it. Detection vendors test against published specs — opaque vendors are easier to bucket. This page lists every value we patch, the layer it lives at, and the verification path for each.
If something on this page doesn't match what our burner actually emits, that's a bug — file it at support@browsa.io.
| Layer | What we patch | Where |
|---|---|---|
navigator | UA, platform, languages, vendor, webdriver, hardware_concurrency, deviceMemory | Chromium C++ patch + V8 binding override |
screen | width, height, availHeight, colorDepth, pixelDepth, devicePixelRatio | Chromium C++ patch |
WebGL | UNMASKED_VENDOR, UNMASKED_RENDERER, getShaderPrecisionFormat, WEBGL_debug_renderer_info, extensions | Chromium C++ patch with per-OS values (Apple Inc. / ANGLE-Apple-M2 for macOS, Google Inc. / Intel UHD for Windows) |
Canvas | Per-session deterministic noise on toDataURL / getImageData (canvas-session-ID plumbed end-to-end per profile) | Chromium C++ patch (Skia path) |
Audio | AudioBuffer noise injection, hardware-coherent baseLatency derived from sample_rate / buffer_size | Chromium C++ patch (Blink AudioContext) |
Fonts | Real OS font list (not the "Docker SwiftShader stub" that gives bots away) | Phantom Docker image includes the real macOS/Windows font set |
CDP signal | navigator.webdriver = false, all cdc_* properties stripped, Runtime.evaluate non-detection | Chromium C++ patch + STEALTH_MODE flags |
TLS / JA3 | Client Hello fingerprint matches real Chrome 147 — utls MITM proxy emits the same SNI extension order, GREASE values, cipher list | Phase 4 sidecar (ja3-proxy / phantom-forwarder) |
HTTP/2 settings | SETTINGS frame order + values match Chrome 147 | Phase 4 sidecar |
Timezone / locale | Derived from proxy.country at burner boot — primary_language + accept_languages + Intl.DateTimeFormat all coherent | cloud-runner boot-time env injection |
The exact strings we emit per os_type. GET /v1/agents/{id}/fingerprint returns this shape for any provisioned agent.
navigator.userAgent | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.7727.25 Safari/537.36 |
navigator.platform | MacIntel |
WebGL UNMASKED_VENDOR | Apple Inc. |
WebGL UNMASKED_RENDERER | ANGLE (Apple, ANGLE Metal Renderer: Apple M2, Unspecified Version) |
screen.colorDepth | 30 (matches real M-series Macs) |
screen.pixelDepth | 30 |
hardware_concurrency | 8 |
deviceMemory | 8 |
navigator.userAgent | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.7727.25 Safari/537.36 |
navigator.platform | Win32 |
WebGL UNMASKED_VENDOR | Google Inc. (Intel) |
WebGL UNMASKED_RENDERER | ANGLE (Intel, Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0, D3D11) |
screen.colorDepth | 24 |
We run every Phantom build through an automated harness against the major detection sites. Current pass rate on a fresh burner (no warmup, US proxy):
| Detector | Verdict | Notes |
|---|---|---|
| antoinevastel.com/bots | PASS | Full clean — no headless signal |
| fingerprint.com BotD (open source) | PASS | bot: false with STEALTH_MODE |
| fingerprint.com Pro demo | PASS | Suspect Score 29 (≤30 = not flagged) |
| browserleaks.com | PASS | Clean across UA, fonts, WebGL, audio |
| creepjs (abrahamjuliot) | SUSPICIOUS | Trust ~38% — improvement on persistent identities with warmup recipe |
| iphey.com BROWSER | SUSPICIOUS | Missing-API signals (navigator.share, contentIndex, contacts) — fix in next Phantom build |
Trust Score reflects this signal: burner default ~870-890; persistent identities with warmup land in the 900-940 range. See trust_score docs.
Most customers should let the platform pick a coherent combination (this is what Trust Score is calibrated against). When you need finer control, six override knobs are exposed at agent-creation time. Empty = platform default; invalid values silently degrade to the default rather than refusing the provision.
| Override | Accepted values | Default |
|---|---|---|
screen_resolution | 1366x768, 1440x900, 1536x864, 1600x900, 1920x1080 (default), 2560x1440, 3840x2160, mobile-iphone (390x844), mobile-android-pixel (412x915), or custom WxH (320≤W,H≤7680) | 1920x1080 |
webrtc_mode | masked · real · disabled | masked |
geolocation_mode | prompt · allow · block | prompt |
geolocation_data | "lat,lng" string (lat∈[-90,90], lng∈[-180,180]) — used when geolocation_mode="allow" | derived from country |
media_devices_mode | masked · real | masked |
port_scan_protection | masked · real | masked |
Set them on the agent at create time:
curl https://browsa.io/v1/agents \
-H "X-API-Key: agt_live_..." \
-d '{
"mode": "burner",
"os_type": "OS_TYPE_MACOS",
"country": "de",
"screen_resolution": "2560x1440",
"geolocation_mode": "allow",
"geolocation_data": "52.5200,13.4050"
}'
Coherence matters. The platform doesn't refuse incoherent combinations (some advanced use cases want a mobile resolution on a macOS UA), but it surfaces them in the warnings array on GET /v1/agents/{id}/fingerprint:
{
"screen": { "width": 390, "height": 844, ... },
"warnings": [
"screen_resolution looks mobile-shaped but os_type is desktop — detection sites cross-check; trust_score may drop",
"media_devices_mode=real returns the host's device list — in Phantom Docker this is 0 devices, which is itself a detection signal"
],
...
}
Four ways to audit the fingerprint without taking our word for it:
GET /v1/agents/{id}/fingerprint — the wire-level preview for any provisioned agent.GET /v1/agents/{id}/trust — the per-factor trust-score breakdown.GET /v1/agents/{id}/detection-signal — the most-recent detection-harness verdict for your identity's fingerprint shape (sites_tested + sites_passed + per-site verdicts). The empirical data behind the score number.c.connect(agent_id) in the SDK) and run any detection-site URL through it — we publish that we pass; you can confirm it.from browsa import Client c = Client(api_key="agt_live_...") agent = c.create_agent(country="us", os_type="OS_TYPE_MACOS") print(c.fingerprint(agent["id"])) # full wire spec print(c.trust_breakdown(agent["id"])) # why the score is what it is print(c.connect(agent["id"])) # paste-ready Playwright snippet
Anti-detect platforms that hide behind "Advanced stealth" marketing eventually lose to vendors that ship verifiable specs. We'd rather you find a gap and tell us than have a detection site find it and silently bucket your traffic. If a value on this page doesn't match what our burners emit, that's a P0 — email support@browsa.io with your agent_id and we fix it.