# Clearcote > Clearcote is an open-source, de-Googled Chromium build with engine-level fingerprint > controls. It presents one coherent, plausible browser identity instead of an accidentally > unique one, and is a drop-in for Playwright & Puppeteer. No opaque binaries: every change > is a readable patch and every build is reproducible and signed. Site: https://clearcotelabs.com Repository: https://github.com/clearcotelabs/clearcote-browser License: BSD-3-Clause Status: pre-release (Windows + Linux v0.1.0-pre.21), Chromium 149 (149.0.7827.114), Windows x64 + Linux x64. SDK: clearcote 0.15.0 (npm + PyPI). New in pre.21 + SDK 0.15.x: Network request-header hygiene - under a fingerprint persona the engine no longer emits redundant Cache-Control / Pragma request headers on navigations and reloads (a real Chrome cold navigation carries none; the effective cache mode is unchanged, and with no persona stock behavior is preserved). Humanized cursor - a shared, persona-seeded human-motion core (minimum-jerk submovements, Fitts-law duration, colored noise, endpoint dwells) now drives the sync and async humanizers, bit-identical across the Python and Node SDKs so one fingerprint maps to one stable motor identity, with an offline motion-score validator. New in pre.20 + SDK 0.14.x: Locale coherence - the renderer's Intl locale now follows the persona Accept-Language, so Intl.DateTimeFormat / Number.toLocaleString / date formatting agree with navigator.language (previously stuck at en-US). Plus a stealthy CDP endpoint: clearcote.serve() (Python AND Node) launches the binary directly (no --enable-automation, so navigator.webdriver stays false) and returns a .cdp_url any Playwright / Puppeteer / browser-use / Crawl4AI / Stagehand client attaches to over CDP; a clearcote-mcp server (pip install clearcote-mcp / npx clearcote-mcp) to drive Clearcote from Claude / Cursor / Cline; and an official Docker image (docker run -d --rm -p 9222:9222 teamflatearth/clearcote). New in pre.19: render-vs-string font coherence + a mobile persona - a Windows/macOS persona on the Linux build now renders common Windows font families (Segoe UI, Calibri, Cambria, Georgia, ...) present with correct advance widths via bundled metric-compatible open clones, each mapped to a DISTINCT clone so a reference-free width-equality check (width(Verdana)==width(Arial), impossible on real Windows) no longer fires; the clones ship with the Linux release and the SDK wires them in via FONTCONFIG on launch so they resolve on bare servers/containers, and a Linux persona correctly reports the Windows-only families absent. Also new: a best-effort mobile Android persona (--fingerprint-platform=android / SDK platform="android" - mobile UA/UA-CH, touch, mobile viewport + (pointer:coarse)/(hover:none), portrait orientation, no PDF plugin, Mali/Adreno GPU), Edge brand coherence, a locale-coherent default timezone (derived from Accept-Language so a server run does not leak the host's UTC), and coherent WebGL MAX_VIEWPORT_DIMS (persona/D3D11 32767 rather than a software [8192,8192]). New in pre.18: coherence-first TLS network persona - the browser can make the TLS ClientHello follow the persona's claimed Chrome version instead of always emitting the build's native (149) TLS. --fingerprint-tls-profile=chrome- (SDK tlsProfile, default match-persona) swaps only the version-variant fields: the post-quantum key-share group (X25519MLKEM768 >=131 / X25519Kyber768 124-130 / none <124) and the ALPS codepoint match that major, while the cipher list, TLS version bounds, signature algorithms, and per-connection extension permutation stay exactly real-Chrome (a fixed JA3 is itself a tell). Chromium-core only (Chrome/Edge/Brave/Opera); coherence, not arbitrary spoofing. Verified against an open TLS reflector. New in pre.17: the first Linux x64 build — de-Googled Chromium 149 with the full coherent-persona stack, now Linux-native: WebGL reports a Mesa/OpenGL renderer (not Windows Direct3D11), speechSynthesis.getVoices() returns the coherent Linux result (not Microsoft SAPI names), enumerateDevices() returns a PulseAudio/PipeWire roster (not Windows WASAPI/Realtek), UA/UA-CH = Linux. CreepJS 0% headless / 0% stealth; webdriver=false; WebRTC reports the proxy IP with no host-IP leak. Widevine/EME works on Linux via the CDM hint-file mechanism. The SDK (clearcote 0.11.0) auto-downloads the right binary per OS (tar.xz + chmod on Linux). New in pre.16: fingerprint-coherence hardening — measureText() and the client-rect APIs (getClientRects / getBoundingClientRect / Range) now return truthful, on-grid values (text-metric widths on Chrome's native 1/512-px grid; main thread == OffscreenCanvas worker; getBoundingClientRect == Range rects). The prior sub-grid perturbation was a net-negative tell; per-eTLD+1 canvas/WebGL pixel farbling is unchanged. A new stealth-coherence regression gate launches the shipped binary on every release so these invariants can't silently regress. New in SDK 0.10.3: a render-backend coherence probe (check_render_coherence / checkRenderCoherence reads the live WebGL renderer and flags a software-rasterizer fallback or an incoherent GPU family); hardened launch defaults that drop Playwright's --enable-automation and disable QUIC when a proxy is set; and deeper humanized input (min-jerk sum-of-sub-movements mouse glide, ease-out scroll inertia, gaussian inter-key typing). New in pre.15: opt-in Widevine / EME (DRM). The build ships the EME plumbing (enable_widevine) and the SDK fetches the Widevine CDM on demand from Google's component server (widevine=True in Python / widevine: true in Node, on a persistent context), so requestMediaKeySystemAccess('com.widevine.alpha') resolves and DRM streams play like a real Chrome — Clearcote never bundles Google's proprietary CDM. Also carries a reworked canvas-farbling path (full-buffer hash + per-eTLD+1 seed) and a matured engine-level humanized cursor. The opt-in real-GPU canvas bridge forwards Canvas2D + WebGL end-to-end (--canvas-bridge-mode). ## What it is - An independent project. Not affiliated with Google, Chromium, or any commercial browser. - Built on ungoogled-chromium (Google services/telemetry removed) + a transparent patch set. - Identity controls are compiled into the C++ engine, not injected via JavaScript. - Signals are derived per site (farbling-style) so they stay coherent and decorrelated across domains. ## Coherent persona A single `--fingerprint` seed derives one internally-consistent Windows persona: correlated CPU/RAM tier, screen geometry, color depth, GPU, Chrome version, locale/timezone, media devices, codecs, speech voices, storage quota and WebGPU/WebGL coherence. Hardware-class properties stay constant for the session while noisy render surfaces remain per-site farbled. ## Current controls Canvas 2D, WebGL renderer + getParameter table, WebGPU adapter info/limits, AudioContext, fonts, timezone, Accept-Language, Intl locale, speech voices, UA + UA-CH, hardwareConcurrency, deviceMemory, screen geometry, storage quota, MediaCapabilities, enumerateDevices, client rects, webdriver/headless hints, closed shadow roots, WebRTC proxy-IP, getBattery, navigator.connection, keyboard layout map, getScreenDetails, CSS pointer/hover media, navigator.share, humanized input, optional Widevine / EME (DRM) via an opt-in CDM fetch, optional in-browser AI agent, and optional real-GPU canvas bridge. Locale is fully coherent: `Accept-Language`, `navigator.language`, the full `navigator.languages` array, `Intl.DateTimeFormat`, and `Number.toLocaleString` all follow the persona's Accept-Language (the renderer's ICU/Intl default locale is aligned to it as of pre.20). ## Key binary flags - `--fingerprint=` master seed - `--fingerprint-platform=windows|linux|macos|android` (`android` = best-effort mobile persona: mobile UA/UA-CH, touch, mobile viewport/pointer/orientation, no PDF plugin, Mali/Adreno GPU) - `--fingerprint-platform-version=` - `--fingerprint-brand=Chrome|Edge|Opera|Vivaldi` - `--fingerprint-brand-version=` - `--fingerprint-gpu-vendor=` / `--fingerprint-gpu-renderer=` - `--fingerprint-webgpu-vendor=` / `--fingerprint-webgpu-architecture=` / `--fingerprint-webgpu-device=` / `--fingerprint-webgpu-description=` - `--fingerprint-hardware-concurrency=` - `--fingerprint-location=` - `--fingerprint-profile=` - `--fingerprint-storage-quota=` - `--timezone=` - `--accept-lang=` - `--webrtc-ip=` - `--disable-gpu-fingerprint` - `--disable-fingerprint-noise` - `--fingerprinting-canvas-image-data-noise` - `--fingerprinting-canvas-measuretext-noise` - `--fingerprinting-client-rects-noise` - `--canvas-bridge-url=ws://host:port` - `--canvas-bridge-auth=user:secret` - `--canvas-bridge-mode=off|all|allow|deny` - `--canvas-bridge-allow=a.com,b.com` - `--canvas-bridge-deny=a.com,b.com` - `--canvas-bridge-fallback=block|local` - `--agent-llm-url=` - `--agent-llm-key=` - `--agent-model=` - `--agent-tool-mode=tools|json` - `--enable-features=GlicActorIncrementalTyping:` agent keystroke cadence (per-key keydown/keyup timing; `--disable-features=GlicActorIncrementalTyping` for instant/one-shot) - `--webrtc-ip-handling-policy=disable_non_proxied_udp` WebRTC leak-proof floor - `--disable-features=BrowsingTopics,Fledge,InterestGroupStorage,PrivateAggregationApi,SharedStorageAPI,FencedFrames,WebUSB` disable Privacy Sandbox + intrusive APIs - `--load-extension=` / `--disable-extensions-except=` load unpacked extensions ## Launch hardening defaults (SDK) The SDK applies coherent defaults you can override: - Privacy Sandbox + intrusive APIs (Topics/FLEDGE/WebUSB/SharedStorage/PrivateAggregation/FencedFrames) are disabled by default — a de-Googled build shouldn't still answer `document.browsingTopics()`/`navigator.usb`. Pass `disable_privacy_sandbox=False` / `disablePrivacySandbox: false` to keep them. - WebRTC defaults to `disable_non_proxied_udp` unless a `webrtc_ip` / handling policy is set, so the real local IP can't leak via srflx. - Playwright's `--enable-automation` is dropped by default so the engine's `AutomationControlled` feature stays off (it otherwise flips `navigator.webdriver`-adjacent tells). Pass your own `ignore_default_args` / `ignoreDefaultArgs` to override. On Widevine launches the strip is applied before the CDM helper so it survives. - QUIC / HTTP-3 is disabled when a proxy is set, so no UDP egresses around a TCP-only SOCKS5/HTTP proxy — coherent with proxied Chrome. - A one-line coherence warning is printed to stderr for incoherent option combos the SDK can't auto-fix (silence with `quiet` / `CLEARCOTE_NO_WARN`). - Headed launches default to no emulated viewport (`no_viewport` / `viewport: null`) so `window.innerWidth` matches the real OS window (an emulated 1280x720 on a real window is an impossible-window tell). - A `socks5://user:pass@host:port` proxy is routed via `--proxy-server` (Playwright rejects credentials in its SOCKS descriptor); Chromium can't authenticate SOCKS5 so the credentials are dropped with a warning — use a local relay. - Overlapping `--enable-features` / `--disable-features` (the SDK's defaults plus your own) are merged into a single flag each (Chromium otherwise keeps only the last). ## SDK - clearcote 0.15.0 on npm + PyPI Install with `pip install clearcote` or `npm install clearcote`. `launch()` returns a standard Playwright Browser. The SDK resolves the browser as: explicit executable path, `CLEARCOTE_BINARY`, then auto-download + SHA-256 verification into a local cache. ## Docker - teamflatearth/clearcote `docker run -d --rm -p 9222:9222 teamflatearth/clearcote` runs Clearcote as a stealth CDP endpoint on http://localhost:9222. Connect any Playwright/Puppeteer/browser-use/Crawl4AI client with `connect_over_cdp("http://localhost:9222")` and keep your automation code. Configure the persona with env vars: CC_PLATFORM (windows|linux|macos|android), CC_FINGERPRINT (seed), CC_BRAND (Edge|Chrome…), CC_ACCEPT_LANGUAGE, CC_TIMEZONE, CC_TLS_PROFILE. The image bakes in the signed Linux binary + base fonts + the Windows metric-clone fonts; defaults to a coherent native Linux persona. The CDP endpoint is full browser control — publish only to trusted networks (`-p 127.0.0.1:9222:9222` keeps it host-local). Python: from clearcote import launch browser = launch(fingerprint="seed-123", platform="windows", geoip=True, humanize=True, show_cursor=True, proxy={"server": "http://host:8080", "username": "u", "password": "p"}) Async Python (inside an asyncio loop — same options, returns Playwright async objects): import asyncio from clearcote.async_api import launch async def main(): browser = await launch(fingerprint="seed-123", platform="windows") page = await browser.new_page(); await page.goto("https://example.com"); await browser.close() asyncio.run(main()) Node: import { launch } from "clearcote"; const browser = await launch({ fingerprint: "seed-123", platform: "windows", geoip: true }); SDK options/helpers: - `download()` / `executable_path()` / `executablePath()` prefetch or resolve the verified chrome.exe. - `auto_update` / `autoUpdate` opt in to resolving the latest GitHub release; checksums are verified and GPG is checked when available. - `cache_dir` / `cacheDir`, `quiet`, and `CLEARCOTE_CACHE` control download behavior. - `launch_persistent_context` / `launchPersistentContext` returns a persistent BrowserContext. - `Profile`, `list_profiles` / `listProfiles`, and `load_profile` / `loadProfile` save launchable personas under `~/.clearcote/profiles` (`CLEARCOTE_PROFILE_DIR` overrides). - `geoip` fills unset timezone, accept language, location and WebRTC IP from the proxy exit IP. - `accept_language` / `acceptLanguage`, `webrtc_ip` / `webrtcIp`, `storage_quota` / `storageQuota`. - `fingerprint_profile` / `fingerprintProfile` accepts a profile path, object or JSON string and gzip+base64 encodes it. - `fingerprint_noise=False` / `fingerprintNoise: false` emits `--disable-fingerprint-noise`. - `disable_gpu_fingerprint` / `disableGpuFingerprint` emits `--disable-gpu-fingerprint`. - `canvas_bridge` / `canvasBridge` emits all canvas bridge flags and auto-adds `--no-sandbox` when enabled. - `humanize` routes click/move/scroll/drag/type through trusted humanized input across page and locator methods: a continuous mouse path from the last cursor position walked as a min-jerk sum-of-sub-movements (ballistic primary + corrective move — multi-peak velocity, not one symmetric bell), ease-out scroll inertia with the occasional reading pause, and key-by-key gaussian-timed typing with word-boundary pauses and the occasional fat-finger correction (bulk values over 200 chars stay atomic). Clicks get an actionability pre-flight (visible/enabled/stable + an `elementFromPoint` covered-by check that falls back to the native click) so a trusted click never fires under an overlay; held-button drags work (slider captchas). `show_cursor` / `showCursor` overlays a cursor dot. - `check_render_coherence(page)` / `checkRenderCoherence(page)` (sync + async) probes the live page's (unmasked) WebGL vendor/renderer for a software-rasterizer fallback (SwiftShader/llvmpipe — a headless tell) or an incoherent GPU family, returning `{renderer, software_suspected, coherent, warnings}`; pass `claimed_gpu` / a second arg to also assert the rendered GPU family. - `extensions` is a list of unpacked-extension directory paths (emits `--load-extension` + `--disable-extensions-except`). - `disable_privacy_sandbox` / `disablePrivacySandbox` (default true) disables Privacy Sandbox + intrusive APIs; set false to keep them. - `agent_typing` / `agentTyping` (`human` default / `fast` / `instant`) tunes the agent's keystroke cadence. ## Examples page Human docs include `/docs/examples` with copy-paste recipes for: - SDK launch with a verified browser. - One stable identity per account with a persistent profile directory. - Proxy + `geoip` timezone/language/location/WebRTC matching. - Saved `Profile` reuse. - Canvas bridge allow-list mode with local fallback. - CI prefetch of the verified binary. - Agent task runs with bounded steps and JSON output. - Raw Playwright launch without the SDK. ## In-browser AI agent Optional and off by default. It drives a page through Chrome's Actor framework with trusted input and a user-supplied OpenAI-compatible/OpenRouter endpoint. It needs a regular/persistent profile, not incognito. - SDK: `launch_agent` / `launchAgent` returns a persistent BrowserContext; `run_agent_task` / `runAgentTask(page, goal, ...)` returns `{ success, finalText, steps, stepsJson }`. - Agent SDK options: `agent_llm_url` / `agentLlmUrl`, `agent_llm_key` / `agentLlmKey`, `agent_model` / `agentModel`, `agent_tool_mode` / `agentToolMode`, `agent_typing` / `agentTyping` (`human`/`fast`/`instant`). - Typed input uses Chrome's incremental-typing engine for per-key keydown/keyup cadence; the `human` default also keeps long text typing key-by-key instead of instant-pasting (a hard tell). - CLI: `clearcote-agent --goal "..." --url ...`, `clearcote-agent -i`, plus `--llm-url`, `--tool-mode`, `--max-steps`, `--profile`, `--headless`, `--executable`, `--fingerprint`, `--proxy`, `--timezone`, `--json`, and `--key`. ## Canvas bridge Run `python tools/canvas-bridge-server/server.py --backend local --chrome /path/to/chrome.exe --port 8443` on the real-GPU host, or use `--backend cdp --cdp-url ws://...` to drive a remote browser over DevTools. Client flags: `--canvas-bridge-url=ws://127.0.0.1:8443 --canvas-bridge-auth=user:secret --no-sandbox --fingerprint=`. The SDK `canvasBridge` / `canvas_bridge` object can also set `mode`, `allow`, `deny`, and `fallback`. ## Roadmap Phase 0 foundations and Phase 1 first build shipped. Phase 2 coherent identity controls are active, with WebRTC proxy-IP, profile import, WebGPU/WebGL coherence, secondary-surface coherence, storage quota and canvas bridge shipped. Phase 3 SDKs shipped with v0.9.1 helpers. Phase 4 supply-chain work continues with provenance/attestation and open CI remaining. Phase 5 tracks Linux/macOS, profile manager, integrations and research-driven hardening. ## Responsible use Intended for privacy, testing, research and lawful automation you are authorized to run. It is not marketed against, and does not target, any specific detection product, and is not a guarantee of evading any system. You are responsible for how you use it.