Docs · Under the hood

Launch identity

Launch identity keeps BetterWright's managed browser coherent across the two layers that sites score. It replaces the old "Cloaking V2" layer; the browser is always the managed BetterChromium fork (see chromium-fork.md). For a browser that is not the managed fork, see browser-providers.md.

  1. Chromium layer - the fork's source-level patches, a stable fingerprint seed, and native locale/timezone flags.
  2. IP layer - an optional upstream egress proxy chained through the local policy guard, with locale/timezone resolved to match the egress geography.

The model API is unchanged: snippets, snapshots, human.*, captcha.*, credentials, and proof captures work as before.

The fork presents the host it runs on

The identity layer deliberately does not mask the operating system. A Linux host is a Linux browser: navigator.platform, the UA, UA-CH client hints, screen geometry, and GPU strings all report the real platform, kept coherent by the fork's source patches. Masking a Linux process as a consumer Mac made every mismatch (fonts, WebGL renderer, media codecs, worker behavior) a separate tell; the fork's patches keep a headless Linux browser coherent as a Linux desktop browser instead. The explicit platform option remains for pinning a specific identity, but nothing defaults away from the host.

The identity layer does not monkey-patch browser APIs in the page world. The managed binary remains authoritative for canvas, WebGL, audio, fonts, plugins, hardware, automation markers, and client hints.

SurfaceBehavior
GeometryNative fork geometry; headed-invisible parks a real window off-screen
Locale--lang, --fingerprint-locale, and Accept-Language
Timezone--bw-timezone, so Intl and Date agree
Platform--fingerprint-platform=<host> — the real host OS
GPU, plugins, hardwareFork source-level fingerprint patches
JavaScript APIsLeft native; no replacement getters or functions
Service workersAllowed natively; traffic still crosses the policy guard

Forcing page-world values made a synthetic probe look perfect once, but live reCAPTCHA checks stalled. Leaving the APIs native restored server-verified 0.9 in both true-headless and headed modes.

Launch modes

  • Headless (default): a real --headless fork process with a realistic desktop viewport. This is not an off-screen headed substitute.
  • Headed (--headed): a normal visible browser window.
  • Headed-invisible (headedInvisible: true / --headed-invisible): a headed window parked off-screen for workflows that explicitly need native window compositing.

Egress proxy

const browser = new BetterWright({
  upstreamProxy: "socks5://user:pass@residential-egress:1080",
  geoip: true,
});
  • Supports http:// and socks5:// upstreams with optional credentials.
  • Every connection is still policy-checked and DNS-validated locally.
  • The guard tunnels to the validated literal IP, preserving DNS-rebinding protection while the target observes the upstream IP.
  • WebRTC is forced onto the proxied path.
  • geoip: true resolves locale/timezone through the upstream. Explicit locale and timezone values always win.

Verification

Compile the harness first with npm run build:harness.

node research/stealth-report.js
node research/stealth-report.js --live
node research/stealth-report.js --live --site recaptcha-v3-score

The local fixture checks roughly 30 browser surfaces against stock-Chrome behavior. Live acceptance uses server-verified score endpoints:

CheckTrue headlessHeaded
Local fixturestock-Chrome paritystock-Chrome parity
antcpt.com/score_detector0.90.9
democaptcha.com0.90.9

recaptcha-demo.appspot.com is not an acceptance gate. Its widget currently reports that the site exceeded its Enterprise free quota, so an unresolved request there does not establish browser detection.

Interactive CAPTCHA issuance is a separate gate. In the current public-demo runs, Turnstile remained at processing without a token in both modes, while reCAPTCHA v2 escalated to an image grid that requires vision. The report prints tokenIssued explicitly so those outcomes cannot be mistaken for a pass.

Configuration

OptionDefaultMeaning
launchIdentitytrueCoherent locale/timezone identity layer. CLI: --no-launch-identity
upstreamProxy-http:// / socks5:// egress proxy. CLI: --upstream-proxy
geoipfalseLocale/timezone from egress IP. CLI: --geoip
locale-Explicit BCP 47 locale. CLI: --locale
timezone-Explicit IANA timezone. CLI: --timezone
platformhostIdentity platform pin (default: the real host OS). CLI: --platform
headedInvisiblefalseOff-screen headed window. CLI: --headed-invisible
stealthRuntimeFixfalseOptional patchright isolated-world execution
Edit this page on GitHubSynced from commit 5ba586f on 2026-09-02