# Clearcote — Full documentation bundle (for AI agents & LLMs) > This single file is the COMPLETE Clearcote documentation, flattened for pasting > into an AI coding agent (Claude, Codex, Cursor, etc.) so it has full project > context in one shot. Human docs live at https://clearcotelabs.com/docs and the > short machine summary at https://clearcotelabs.com/llms.txt > > Generated for: Clearcote Browser — open-source, de-Googled Chromium with > engine-level fingerprint controls. Drop-in for Playwright & Puppeteer. --- ## Project facts - Name: Clearcote (internal build codename "clearcoat" — never used publicly) - One-liner: Blend in. Stay clear. - Site: https://clearcotelabs.com - Repository: https://github.com/clearcotelabs/clearcote-browser - License: BSD-3-Clause (Clearcote's own code + patches; upstream keeps its licenses) - Status: pre-release (Windows + Linux v0.1.0-pre.21) - Engine: Chromium 149 (pinned 149.0.7827.114) - Platform: Windows x64 + Linux x64 (macOS on the roadmap) - Automation: drop-in for Playwright & Puppeteer via `executablePath` - SDK: clearcote 0.15.0 on npm + PyPI (Playwright drop-in; auto-downloads + SHA-256-verifies the right binary per OS) - Docker: `teamflatearth/clearcote` — `docker run -d -p 9222:9222 teamflatearth/clearcote` runs Clearcote as a stealth CDP endpoint on http://localhost:9222; any Playwright/Puppeteer/browser-use/Crawl4AI client attaches with `connect_over_cdp`. Persona via CC_* env vars (CC_PLATFORM windows|linux|macos|android, CC_FINGERPRINT, CC_BRAND, CC_ACCEPT_LANGUAGE, CC_TIMEZONE, CC_TLS_PROFILE). Bakes in the signed binary + base fonts + Windows metric-clone fonts; defaults to native Linux persona. CDP = full browser control, publish only to trusted networks. - New in v0.1.0-pre.21 + SDK 0.15.0: 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 v0.1.0-pre.20 + SDK 0.14.1: 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 v0.1.0-pre.19 + SDK 0.13.0: render-vs-string font coherence + a mobile (Android) persona. FONTS: a Windows/macOS persona on the Linux build now renders common Windows font families (Segoe UI, Calibri, Cambria, Georgia, Arial, Times, Courier, ...) present with correct advance widths via bundled metric-compatible open clones (Selawik=Segoe UI, Carlito=Calibri, Caladea=Cambria, Gelasio=Georgia, Arimo=Arial, Tinos=Times, Cousine=Courier, DejaVu Sans=Verdana, DejaVu Sans Condensed=Tahoma, Comic Neue=Trebuchet, Noto Sans=Comic Sans, Anton=Impact, Inconsolata=Consolas), 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 points FONTCONFIG_FILE at them on launch so they resolve on bare servers/containers, and a Linux persona correctly reports the Windows-only families absent (they are dropped from the basic-font passthrough). MOBILE: a best-effort Android persona (--fingerprint-platform=android / SDK platform="android") - mobile UA/UA-CH, touch, mobile viewport + (pointer:coarse)/(hover:none), portrait screen orientation, no PDF plugin, Mali/Adreno GPU string. Also: Edge brand coherence, a locale-coherent default timezone (derived from Accept-Language, no host-UTC datacenter leak, geoip/explicit override still win), and coherent WebGL MAX_VIEWPORT_DIMS (persona/D3D11 32767 instead of a software [8192,8192] leak). New in v0.1.0-pre.18 + SDK 0.12.0: 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 v0.1.0-pre.17 + SDK 0.11.0: the **first Linux x64 build**. Same de-Googled Chromium 149 + full coherent-persona stack as Windows, now Linux-native — with `--fingerprint-platform=linux` (the Linux binary's default) the persona emits Linux-shaped values instead of Windows ones: WebGL `UNMASKED_RENDERER` is an OpenGL/Mesa string (not Windows Direct3D11), `speechSynthesis.getVoices()` is the coherent Linux result (not `Microsoft David/Zira`), `enumerateDevices()` is a PulseAudio/PipeWire roster (`Default` / `Built-in Audio Analog Stereo` / `Monitor of…`, not Windows WASAPI/Realtek), and UA / `navigator.platform` / UA-CH are Linux. Verified: CreepJS `0% headless` / `0% stealth`, `navigator.webdriver=false`, WebRTC reports the proxy IP with no host-IP leak, stealth-coherence gate green. Opt-in **Widevine/EME (DRM)** works on Linux via the CDM **hint-file** mechanism (`libwidevinecdm.so`; no component-updater fast-update scan needed — the SDK's `_widevine` branches per OS). The **SDK is multi-platform**: `RELEASE` carries a per-platform pin (Windows→pre.16 zip, Linux→pre.17 tar.xz), `ensure_binary` picks + extracts the right archive per OS (tar.xz + `chmod +x` on Linux), and the launch guard allows Windows + Linux. Runtime deps on a minimal Linux host: `libnss3 libnspr4 libgbm1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libxfixes3 libxext6 libpango-1.0-0 libcairo2 libx11-6 libxcb1 libexpat1 libdbus-1-3`; in containers pass `--no-sandbox` (or setuid `chrome-sandbox`). - New in v0.1.0-pre.16 + SDK 0.10.4: fingerprint-coherence hardening — `measureText()` and the client-rect APIs (`getClientRects` / `getBoundingClientRect` / `Range`) now return truthful, on-grid values: text-metric widths sit on Chrome's native 1/512-px grid, `measureText` agrees between the main thread and an `OffscreenCanvas` worker, and `getBoundingClientRect` agrees with `Range` rects. The previous sub-grid scale/offset was a net-negative tell — negligible anonymity (those surfaces are determined by the spoofed font set) while breaking three reference-free invariants; per-eTLD+1 canvas/WebGL *pixel* farbling is unchanged. Ships with a self-referential **stealth-coherence regression gate** that launches the shipped binary on every release and fails the build if any invariant regresses (text on-grid, main == worker, BCR == Range, render bytes origin-stable, WebGPU↔WebGL vendor agreement). SDK 0.10.4 pins this browser build (no SDK API change). - New in SDK 0.10.3: a render-backend coherence probe — `check_render_coherence(page)` / `checkRenderCoherence(page)` (sync + async) reads the live page's (unmasked) WebGL vendor/renderer and flags a software-rasterizer fallback (SwiftShader/llvmpipe — a headless tell) or an incoherent GPU family, returning `{renderer, software_suspected, coherent, warnings}`. Hardened launch defaults: `--enable-automation` is dropped so the engine's `AutomationControlled` feature stays off (set before the Widevine helper so DRM launches keep it), and QUIC/HTTP-3 is disabled when a proxy is set so no UDP egresses around a TCP-only proxy. Deeper humanized input: the mouse glide is now a min-jerk sum-of-sub-movements (ballistic primary + corrective move — multi-peak velocity, not one symmetric bell), scrolling uses ease-out inertia with reading pauses, and typing is key-by-key with gaussian inter-key timing + word-boundary pauses, on top of the existing one-standard breadth (page + locator coverage, held-button drag, fat-finger correction). The async API reached input parity (the 0.10.2 async path was near-unhumanized). - New in pre.15: opt-in Widevine / EME (DRM). The build ships the EME plumbing (`enable_widevine`) but never the proprietary CDM; the SDK fetches the Widevine CDM on demand from Google's component server and seeds it into a persistent profile (`widevine=True` in Python, `widevine: true` in Node), so `navigator.requestMediaKeySystemAccess('com.widevine.alpha')` resolves and DRM streams play (software-secure / L3). Also carries a reworked canvas-farbling path (full-buffer hash + per-eTLD+1 seed + xorshift64) and a matured engine-level humanized cursor (min-jerk bowed-bézier sub-movements, viewport-correct overlay). - Identity model: engine-level (C++), coherent, per-site (eTLD+1) "farbling" - Distribution: GitHub Releases, SHA-256 checksummed + GPG-signed - Pinned signing key (ed25519): CA96 F185 F96A 693A EDB3 AC1F CB00 D851 B7A8 6B0F --- ## What it is A stock browser quietly exposes a unique, trackable fingerprint — canvas, WebGL, audio, fonts, locale, hardware and more. Clearcote moves control of those signals INTO THE ENGINE ITSELF, so a session presents one consistent, plausible identity instead of an accidentally hyper-unique one. It is built on ungoogled-chromium (Google integration and telemetry removed) plus a transparent stack of source patches. There is no magic binary: you can read every change, rebuild it yourself, and check that what you run matches what's published. It is an INDEPENDENT project — not affiliated with, endorsed by, or derived from any commercial product, and it ships no third-party proprietary code. ## Why it exists - Privacy is the default, not an add-on. De-Googled base, engine-level signal control, no built-in tracking or update beacons. - Trust through transparency. The "stealth browser" space is full of closed binaries that ask for blind faith. Clearcote's stance: don't trust us — verify us. - Built for builders. Clean repo layout, scriptable builds, and an AGENTS.md so humans AND automated tooling can navigate and contribute. - It's just Chromium. Native Playwright/Puppeteer support and the ecosystem you know. ## Principles | Principle | What it means | |---|---| | Open by default | 100% open source. Every patch is human-readable. No proprietary blobs in the tree. | | Engine-level, not script injection | Controls are compiled into the binary, not bolted on via brittle, self-revealing injected JavaScript. | | Coherent identity | Signals are controlled together so they stay internally consistent and stable per site. | | Reproducible & verifiable | Pinned upstream revision, deterministic patch set, checksummed and signed artifacts. | | Responsible by design | Built for privacy, testing and lawful automation. You are responsible for how you use it. | --- ## Architecture / how it works A thin, auditable stack — each layer is open and replaceable: ``` Chromium (Google, BSD-3) | ungoogled-chromium -> removes Google services, telemetry, integration | Clearcote patches -> engine-level identity & privacy controls | reproducible build -> checksummed, signed, rebuildable by anyone | Clearcote Browser + Playwright / Puppeteer drop-in ``` ### Engine-level, not script injection Most "stealth" tooling injects JavaScript to overwrite `navigator` properties at runtime. That is brittle and self-revealing — the overrides themselves become a fingerprint (wrong prototype chains, getter timing, missing native-code stringification). Clearcote instead modifies the C++ engine, so the values a page reads come from the same code paths Chromium always uses; there is no injected layer to detect, and it covers APIs JavaScript can't cleanly intercept. ### Coherent, per-site identity (farbling) Randomizing each signal independently produces an identity that doesn't add up — a dead giveaway. Clearcote derives all signals from a single seed combined with the site's registrable domain (eTLD+1), so values are: - Internally consistent — platform, GPU, timezone and locale agree with each other. - Stable per site — the same site sees the same identity across a session. - Decorrelated across sites — different domains see different values, so you aren't linkable across the web. This per-eTLD+1 model is inspired by Brave's farbling approach. ### Coherent persona model (one seed -> one believable machine) Clearcote goes a step beyond per-signal noise: a single `--fingerprint` seed derives one COHERENT Windows persona — a single believable machine whose properties agree with each other. From the seed it draws a hardware tier (CPU cores and RAM that ship together — never 20 cores with 4 GB), a matching screen resolution / available work area / colour depth / device pixel ratio, a coherent GPU (WebGL vendor + renderer + parameter limits), and a real Chrome version (used for the User-Agent and UA-CH). Hardware-class properties are CONSTANT for the session — a real machine doesn't change its core count or screen size between sites — while the noisy, per-render surfaces (canvas, WebGL pixels, audio) stay per-site farbled so you remain decorrelated across domains. Why this matters: the dominant modern bot signal isn't any single value, it's INTERNAL CONTRADICTION — a machine that claims one OS but renders like another, or pairs a 20-core CPU with 4 GB of RAM. Deriving every signal from one persona table guarantees they tell the same story. The persona is Windows-only by design: Clearcote ships a Windows binary, so every persona is a believable Windows PC. It is driven by the same `--fingerprint` seed you already pass — no new flags — so the same seed always yields the same machine. ### What it controls Canvas 2D · WebGL renderer + parameters · WebGPU adapter (GPUAdapterInfo + limits, coherent with WebGL) · AudioContext · Fonts · Timezone · primary navigator language + Accept-Language + Intl locale (--lang) · Speech-synthesis voices · User-Agent + UA-CH (incl. high-entropy bitness / wow64 / model) · hardwareConcurrency · deviceMemory · Screen geometry · storage.estimate() quota · MediaCapabilities.decodingInfo() codec matrix · enumerateDevices() media-device set · Client rects · navigator.webdriver · Headless hints · Closed shadow roots · WebRTC proxy-IP (fabricated srflx, no real STUN) · humanized CDP input — all drawn from one coherent persona. ### Fingerprint coherence (new in pre.6) A coherence pass makes the secondary surfaces agree with the persona and with a real Chrome-on-Windows desktop (coherent-spoof, not block): - WebGL `getParameter` LIMITS (WebGL1 + WebGL2) report the canonical ANGLE/D3D11 values a real Windows GPU returns (max texture / renderbuffer / uniform / UBO / etc.), not the host software-renderer caps. - WebGL UNMASKED_RENDERER / UNMASKED_VENDOR are SESSION-CONSTANT — the same GPU on every site (a real user has one GPU), tracking the persona instead of varying per origin. - `navigator.getBattery()` reports a coherent desktop (charging, level 1.0, no discharge). - `navigator.connection` reports a coherent residential profile (effectiveType 4g, rounded rtt/downlink, saveData off). - `navigator.keyboard.getLayoutMap()` returns a clean US-QWERTY map (Writing-System keys only — no Numpad/Intl/Space). - AudioContext sampleRate / baseLatency / outputLatency report coherent Windows-WASAPI metadata. - `window.getScreenDetails()` reports a single coherent monitor; CSS `@media (pointer: fine)` / `(hover: hover)` match a desktop with a mouse. - `new URL("C:/").protocol` returns `"file:"` (Windows-coherent), closing a host-OS tell. - `navigator.share` / `canShare` are exposed, coherent with the Windows UA. Validated on real Windows: BrowserScan bot-detection = "Normal" (no bot; webdriver/UA/CDP/navigator clean) and CreepJS 0% headless / 0% stealth. ### Cross-API coherence pass (pre.10) A further pass closes cross-surface contradictions where one API could leak the host while another showed the persona — the kind of internal disagreement strict bot detectors look for: - WebGPU ↔ WebGL GPU: `navigator.gpu` (GPUAdapterInfo `vendor` / `architecture` plus `adapter.limits`) is now coherent with the WebGL persona GPU for SEED-ONLY personas too. Previously a seed persona could leak the host's real discrete GPU through `navigator.gpu` while WebGL reported the spoofed one — now both tell the same story. - Locale (`--lang`): the SDK now also emits `--lang=` so `Intl.DateTimeFormat` / `NumberFormat` / `Collator` (on the main thread AND in workers) resolve to the same locale as `navigator.language` — no en-GB default leaking under an en-US persona. - Speech: when fingerprinting, the persona's voice set (en-US default) is served in place of the host's real SAPI voices, so `speechSynthesis.getVoices()` no longer leaks an en-GB default voice. Also new in pre.10: - UA-CH high-entropy hints: `bitness` = "64", `wow64` = false, and a coherent `model`. - `MediaCapabilities.decodingInfo()` returns a persona codec matrix (supported / smooth / power-efficient per persona) instead of the host's real codec support. - `enumerateDevices()` returns a persona media-device set (a microphone + a speaker, with seed-stable ids and empty labels before permission is granted). - A `storageQuota` SDK option sets `navigator.storage.estimate().quota` (in MB). ### Adversarially audited (pre.10) Re-audited against open fingerprint auditors: CreepJS-clean — `navigator.webdriver` = false, 0% headless, 0% stealth, and no API-tampering "lies" flagged (the overrides read as native because they ARE native engine code paths, not injected getters). ### Build target Windows x64 (cross-compiled from Linux with clang-cl / lld-link) and Linux x64 (native clang/lld, bundled bullseye sysroot → glibc 2.31 floor: Ubuntu 20.04+ / Debian 11+ / RHEL 9+), both against Chromium 149. --- ## Installation (Windows x64 + Linux x64) 1) Download from GitHub Releases (https://github.com/clearcotelabs/clearcote-browser/releases). Each release ships: - `clearcote--windows-x64.zip` — the build (Chromium + runtime + VC++ DLLs) - `...zip.sha256` and `SHA256SUMS.txt` — checksums - `...asc` + `clearcote-signing-key.asc` — GPG detached signatures and the public key 2) Verify (recommended) — see "Verification" below. Don't trust, verify. 3) Unzip & place the binary (the archive is self-contained; VC++ 2015–2022 runtime DLLs are bundled, so it runs on a clean Windows 10/11 box): ```powershell Expand-Archive clearcote-149.0.7827.114-windows-x64.zip -DestinationPath C:\clearcote # you now have: # C:\clearcote\chrome.exe # C:\clearcote\chrome.dll + runtime, locales, ICU, ANGLE, VC++ DLLs ``` 4) Smoke test: ```powershell C:\clearcote\chrome.exe --fingerprint=seed-123 --fingerprint-platform=windows ^ https://abrahamjuliot.github.io/creepjs/ ``` Same `--fingerprint` seed => the same identity every launch; a new seed => a fresh one. Requirements: Windows 10/11 x64; no separate VC++ redistributable needed; for automation, your existing Playwright or Puppeteer install (Clearcote replaces the browser, not the driver). --- ## Use it with Playwright / Puppeteer (drop-in, works today) Point your launcher at the Clearcote binary with `executablePath` (Node) / `executable_path` (Python) and pass identity options as `args`. Playwright (Python): ```python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch( executable_path=r"C:\clearcote\chrome.exe", headless=False, args=[ "--fingerprint=seed-123", "--fingerprint-platform=windows", "--timezone=America/New_York", ], ) page = browser.new_page() page.goto("https://abrahamjuliot.github.io/creepjs/") browser.close() ``` Playwright (Node): ```javascript import { chromium } from "playwright"; const browser = await chromium.launch({ executablePath: "C:\\clearcote\\chrome.exe", headless: false, args: ["--fingerprint=seed-123", "--fingerprint-platform=windows", "--timezone=America/New_York"], }); const page = await browser.newPage(); await page.goto("https://abrahamjuliot.github.io/creepjs/"); await browser.close(); ``` Puppeteer (Node): ```javascript import puppeteer from "puppeteer-core"; const browser = await puppeteer.launch({ executablePath: "C:\\clearcote\\chrome.exe", headless: false, args: ["--fingerprint=seed-123", "--fingerprint-platform=windows"], }); const page = await browser.newPage(); await page.goto("https://abrahamjuliot.github.io/creepjs/"); await browser.close(); ``` Profiles & persistence — reuse the same `--fingerprint` seed and a user-data dir: ```python browser = p.chromium.launch_persistent_context( user_data_dir=r"C:\clearcote\profiles\acme", executable_path=r"C:\clearcote\chrome.exe", headless=False, args=["--fingerprint=acme-tenant-7"], ) ``` ### SDK (shipped) — `clearcote` on npm + PyPI A thin `clearcote` package wraps the above: identity options become named arguments, the verified binary is auto-downloaded + SHA-256-checked on first use (cached), and `launch()` returns a standard Playwright Browser. Install `pip install clearcote` / `npm install clearcote` (no `playwright install` needed — Clearcote ships its own binary). ```python from clearcote import launch browser = launch( fingerprint="seed-123", platform="windows", timezone="America/New_York", proxy={"server": "http://host:8080", "username": "u", "password": "p"}, geoip=True, # auto-match timezone / language / geo / WebRTC-IP to the proxy's exit IP humanize=True, # human-like (bezier, trusted) mouse moves + clicks + scroll show_cursor=True, # draw a cursor dot so you can watch the motion ) page = browser.new_page(); page.goto("https://example.com"); browser.close() ``` For asyncio, use the async mirror `clearcote.async_api` (same options, returns Playwright async objects; the sync API raises inside a running loop): ```python import asyncio from clearcote.async_api import launch # also: launch_persistent_context, launch_agent, run_agent_task, Profile async def main(): browser = await launch(fingerprint="seed-123", platform="windows", geoip=True, humanize=True) page = await browser.new_page(); await page.goto("https://example.com"); await browser.close() asyncio.run(main()) ``` ```javascript import { launch } from "clearcote"; const browser = await launch({ fingerprint: "seed-123", platform: "windows", geoip: true, humanize: true }); const page = await browser.newPage(); await page.goto("https://example.com"); await browser.close(); ``` SDK-level options (on top of every flag below + all standard Playwright launch options): - `geoip` — resolve the proxy's exit IP and auto-fill any unset timezone / Accept-Language / location / WebRTC-IP so the whole identity matches the proxy's region (offline MaxMind lookup). - `acceptLanguage` / `accept_language` — sets the Accept-Language header and primary navigator language coherently (Chromium `--accept-lang`); the FULL `navigator.languages` array, `Intl.DateTimeFormat`, and `Number.toLocaleString` follow it too (the renderer's ICU/Intl default locale is aligned to the persona Accept-Language as of pre.20). - `webrtcIp` / `webrtc_ip` — WebRTC reports this IP; the engine FABRICATES the server-reflexive candidate at it and sends NO real STUN, so the real IP never leaks (not merely relabeled). - `humanize` — route clicks / moves / scroll / drag / type through trusted (`isTrusted===true`) humanized input across page and locator methods; `navigator.webdriver` stays false. The mouse path is a min-jerk sum-of-sub-movements (ballistic primary + corrective move — multi-peak velocity, not one symmetric bell), scrolling is ease-out inertia with reading pauses, and typing is key-by-key with gaussian inter-key timing + word-boundary pauses + the occasional fat-finger correction (bulk values over 200 chars stay atomic); held-button drags work (slider captchas). - `showCursor` / `show_cursor` — overlay a red cursor dot that tracks the humanized motion. - `check_render_coherence(page)` / `checkRenderCoherence(page)` — sync + async render-backend coherence probe: reads the live page's (unmasked) WebGL vendor/renderer and flags 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. - `storageQuota` / `storage_quota` — set the `navigator.storage.estimate().quota` reported to the page (in MB), so the persona's available storage is coherent and seed-stable. - `download()` / `executable_path()` / `executablePath()` — prefetch or resolve the verified chrome.exe without launching; `cache_dir` / `cacheDir` controls the cache. - `auto_update` / `autoUpdate` — opt in to resolving the latest GitHub release at runtime; SHA-256 is always checked and GPG is checked when available. - `launch_persistent_context` / `launchPersistentContext` — return a persistent Playwright BrowserContext. - `Profile`, `list_profiles` / `listProfiles`, `load_profile` / `loadProfile` — save launchable personas under `~/.clearcote/profiles` (or `CLEARCOTE_PROFILE_DIR`). - `canvas_bridge` / `canvasBridge` — first-class canvas bridge config with `url`, `auth`, `mode`, `allow`, `deny`, and `fallback`; enabling it auto-adds `--no-sandbox`. - `extensions` — a list of unpacked-extension directory paths (emits `--load-extension` + `--disable-extensions-except`). - `disable_privacy_sandbox` / `disablePrivacySandbox` — disable Privacy Sandbox + intrusive APIs (Topics / FLEDGE / WebUSB / SharedStorage / PrivateAggregation / FencedFrames). **Default true** (a de-Googled build shouldn't still answer `document.browsingTopics()` / `navigator.usb`); set false to keep them. - `agent_typing` / `agentTyping` — the agent's keystroke cadence: `human` (default; slower, less-uniform, and keeps long text typing key-by-key), `fast`, or `instant` (one-shot). Coherent launch defaults (all overridable): - 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 — put the auth on a local relay. - Headed launches default to no emulated viewport (`no_viewport` / `viewport: null`) so `window.innerWidth` tracks the real OS window (an emulated 1280x720 on a real window is an impossible-window tell). Pass an explicit `viewport` to override. - 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); on Widevine launches it's set before the CDM helper so the strip survives. Pass `ignore_default_args` / `ignoreDefaultArgs` to override. - 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`). - `humanize` runs an actionability pre-flight before each trusted click (visible / enabled / stable + an `elementFromPoint` covered-by check) and falls back to the native click, so a trusted click never fires under an overlay or mid-animation; its scroll pacing is off-protocol (no `waitForTimeout` CDP traffic). - Network fetches (binary + GeoIP DB + GitHub API) have idle timeouts so a stalled connection fails fast instead of hanging first-run launch. ### Examples / copy-paste recipes The human docs include `/docs/examples`, a recipe page for common integration work: - Launch a verified browser from the SDK. - Use one stable identity per account by combining a deterministic seed with a persistent profile directory. - Match timezone, language, geolocation and WebRTC IP to a proxy via `geoip`. - Save and reuse named `Profile` personas. - Use the canvas bridge in `allow` mode for selected origins with `fallback: "local"`. - Prefetch the verified browser in CI before running tests. - Run an opt-in agent task with a persistent profile, bounded `max_steps`, and JSON output. - Launch raw Playwright directly with `executablePath` when the SDK is not desired. Migration is a one-line import change — same objects, same methods. --- ## Fingerprint flags (full reference) Everything keys off `--fingerprint=`. The seed (an integer or any string) deterministically derives canvas, WebGL, audio, font and client-rect noise. - Same seed => same identity across launches (a returning visitor). - New seed => a fresh, plausible identity. - Signals are derived per site (farbling), so the same seed is decorrelated across domains rather than globally linkable. | Flag | Value | Description | |---|---|---| | `--fingerprint` | `` | Master seed (int or string). Drives canvas, WebGL, audio, fonts and client-rect noise. Same seed => same identity. | | `--fingerprint-platform` | `windows\|linux\|macos` | Spoof the OS reported to the page (navigator.platform + UA-CH). | | `--fingerprint-platform-version` | `` | Platform version reported via User-Agent Client Hints. | | `--fingerprint-brand` | `Chrome\|Edge\|Opera\|Vivaldi` | Browser brand presented in the UA and UA-CH brand list. | | `--fingerprint-brand-version` | `` | Brand version string. | | `--fingerprint-gpu-vendor` | `` | Override the WebGL UNMASKED_VENDOR string. | | `--fingerprint-gpu-renderer` | `` | Override the WebGL UNMASKED_RENDERER string. | | `--fingerprint-webgpu-vendor` | `` | Advanced: override WebGPU GPUAdapterInfo vendor. Normally derived from the WebGL persona or imported profile. | | `--fingerprint-webgpu-architecture` | `` | Advanced: override WebGPU GPUAdapterInfo architecture. Normally derived from the WebGL persona or imported profile. | | `--fingerprint-webgpu-device` | `` | Advanced: override WebGPU GPUAdapterInfo device. | | `--fingerprint-webgpu-description` | `` | Advanced: override WebGPU GPUAdapterInfo description. | | `--fingerprint-hardware-concurrency` | `` | Value reported by navigator.hardwareConcurrency. | | `--fingerprint-profile` | `` | Import a captured real-Chrome (or dataset) fingerprint profile. Fields present in the profile OVERRIDE the seed-derived persona; absent fields fall back to the `--fingerprint` seed, so partial profiles stay coherent. Gzip keeps a ~40 KB capture within the command-line limit (the SDK does the gzip+base64 for you). | | `--fingerprint-location` | `` | Geolocation coordinates returned to the page. | | `--timezone` | `` | IANA timezone, e.g. America/New_York. Sets the JS timezone coherently. | | `--accept-lang` | `` | Accept-Language + primary navigator language, e.g. `en-US,en`. Keep coherent with timezone/geo. | | `--webrtc-ip` | `` | WebRTC reports this IP (your proxy egress). The engine fabricates the srflx candidate at it and sends no real STUN, so the real IP never leaks — not a relabel. | | `--fingerprinting-canvas-image-data-noise` | — | Enable canvas image-data noise. | | `--fingerprinting-canvas-measuretext-noise` | — | Low-level canvas text-metric noise switch retained by the engine. | | `--fingerprinting-client-rects-noise` | — | Low-level client-rect noise switch retained by the engine. | | `--disable-gpu-fingerprint` | — | Disable the GPU/WebGL fingerprint spoof for this session. | | `--disable-fingerprint-noise` | — | Turn off per-site canvas/WebGL/audio/client-rect farbling noise while keeping identity spoofing on. | | `--fingerprint-storage-quota` | `` | navigator.storage.estimate().quota in megabytes. | | `--canvas-bridge-url` | `ws://host:port` | Enable the real-GPU canvas bridge. Requires `--no-sandbox`. | | `--canvas-bridge-auth` | `user:secret` | HTTP Basic credentials for the bridge endpoint. | | `--canvas-bridge-mode` | `off\|all\|allow\|deny` | Per-origin bridge policy. | | `--canvas-bridge-allow` / `--canvas-bridge-deny` | `a.com,b.com` | eTLD+1 lists for allow/deny bridge policies. | | `--canvas-bridge-fallback` | `block\|local` | Cold cache-miss behavior: wait for bridge or use local render. | | `--webrtc-ip-handling-policy` | `disable_non_proxied_udp` | WebRTC leak-proof floor; the SDK defaults to this unless `--webrtc-ip`/a policy is set. | | `--disable-features` | `BrowsingTopics,Fledge,…,WebUSB` | Disable Privacy Sandbox + intrusive APIs (SDK default; `disable_privacy_sandbox=False` to keep them). | | `--enable-features` | `GlicActorIncrementalTyping:` | Agent keystroke cadence (per-key keydown/keyup timing); `--disable-features=GlicActorIncrementalTyping` = instant/one-shot. | | `--load-extension` / `--disable-extensions-except` | `` | Load unpacked extensions (SDK `extensions` option). | Examples — a full, coherent Windows identity: ```bash --fingerprint=acme-tenant-7 \ --fingerprint-platform=windows \ --fingerprint-brand=Chrome \ --timezone=America/New_York \ --fingerprint-hardware-concurrency=8 ``` A macOS identity with custom GPU strings: ```bash --fingerprint=42 \ --fingerprint-platform=macos \ --fingerprint-gpu-vendor="Apple" \ --fingerprint-gpu-renderer="Apple M2" ``` Pin a location together with its timezone so geolocation and clock agree: ```bash --fingerprint=nyc-1 \ --timezone=America/New_York \ --fingerprint-location=40.7128,-74.0060 ``` Coherence matters more than any single value: keep platform, timezone, locale and GPU plausible TOGETHER. --- ## Fingerprint profile import (shipped, current as of v0.1.0-pre.12) Beyond the seed-derived synthetic persona, Clearcote can present a REAL machine's identity. Capture a fingerprint from a donor Chrome (or bootstrap one from an open-source dataset), then feed it in so the page reads that machine's hardware instead of the synthetic one. Capture options: - Collector: run `tools/fingerprint-collect/collect.html` on a donor Chrome and click Capture (it downloads a JSON profile), or paste `tools/fingerprint-collect/collect.js` + `snippet.js` into DevTools. It captures an exhaustive profile — navigator, screen, WebGL, audio, speech voices, fonts, codecs, CSS media, WebGPU, WebRTC, … - Dataset: bootstrap from the open-source 10k-record `chrome-fingerprints` dataset with `tools/fingerprint-collect/convert_dataset.py` (`pip install chrome-fingerprints; python convert_dataset.py --out ./profiles --count 100`). The converter imports the version-INDEPENDENT hardware identity and by default does NOT import the dataset's Chrome version (records are ~114/115 while the binary is 149, so importing it would mismatch the real UA — a tell). Use it — CLI: ```bash --fingerprint=seed-1 \ --fingerprint-profile= ``` Use it — SDK (it does the gzip+base64 for you, accepting a file path, object, or JSON string): ```python launch(fingerprint="seed-1", fingerprint_profile="profile.json") ``` ```javascript launch({ fingerprint: "seed-1", fingerprintProfile: "profile.json" }) ``` Semantics: fields present in the profile OVERRIDE the seed-derived persona; ABSENT fields fall back to the `--fingerprint` seed, so partial profiles stay coherent. The SDK also derives Accept-Language from the profile's `navigator.languages` when no explicit `accept_language` / `acceptLanguage` is given. What a profile drives (all shipped + verified): `hardwareConcurrency`, `deviceMemory`, screen geometry (width / height / avail / colorDepth / devicePixelRatio), WebGL unmasked vendor + renderer plus the full `getParameter` table (MAX_* limits, bit depths, aliased ranges, anisotropy) and `getSupportedExtensions` filtered to the profile's set, Web Audio sample-rate / latency, Chrome version (from collector captures), `speechSynthesis` voices, font enumeration (measureText), and CSS `@media` display characteristics (device-width / height, resolution, color depth, color-gamut). --- ## In-browser AI agent (new in v0.1.0-pre.10, optional, OFF by default) Clearcote can drive a page autonomously with an LLM that you point at your own OpenAI-compatible / OpenRouter endpoint (bring your own key). The agent perceives the live page, asks the model what to do next, and acts through Chrome's Actor framework with real, trusted input — the same humanized, `isTrusted===true` path the rest of the engine uses, so the identity and `navigator.webdriver=false` stance hold while the agent works. It is OPT-IN and INACTIVE by default: nothing changes unless you set the agent key (or the agent switches). It needs a regular / persistent profile (not incognito), it redacts password fields before they reach the model, and it never sends Clearcote any telemetry — the LLM endpoint is whatever you configure. The key is read from `--key`, then `$OPENROUTER_API_KEY`, then `$CLEARCOTE_AGENT_KEY` (first one set wins). SDK — launch an agent-enabled context and run a goal: ```python from clearcote import launch_agent ctx = launch_agent(fingerprint="seed-123") # returns a persistent BrowserContext page = ctx.new_page(); page.goto("https://example.com") run_agent_task(page, "find the pricing page and read me the cheapest plan") ``` ```javascript import { launchAgent, runAgentTask } from "clearcote"; const ctx = await launchAgent({ fingerprint: "seed-123" }); // persistent BrowserContext const page = await ctx.newPage(); await page.goto("https://example.com"); await runAgentTask(page, "find the pricing page and read me the cheapest plan"); ``` - `launch_agent` / `launchAgent` returns a persistent `BrowserContext` (agent-ready). - Agent launch options: `agent_llm_url` / `agentLlmUrl`, `agent_llm_key` / `agentLlmKey`, `agent_model` / `agentModel`, `agent_tool_mode` / `agentToolMode`, and `agent_typing` / `agentTyping` (`human` default / `fast` / `instant`) — the agent types with per-key keydown/keyup cadence via Chrome's incremental-typing engine; the `human` default also stops long text from being instant-pasted (which would emit zero keystroke events — a hard tell). - `run_agent_task` / `runAgentTask(page, goal, ...)` drives the given page toward a goal and returns `{ success, finalText, steps, stepsJson }`. Per-task options include model, max steps and plan JSON. CLI — a `clearcote-agent` command ships with the SDK: ```bash # one-shot: pursue a goal on a URL, then exit clearcote-agent --goal "sign in and open the billing page" --url https://example.com # interactive REPL: issue goals one after another against a live page clearcote-agent -i # endpoint/model/profile/proxy/step controls clearcote-agent --llm-url http://localhost:8000/v1 --model local/model \ --profile ~/.clearcote/agent-profile --proxy http://user:pass@host:8080 \ --max-steps 12 --tool-mode json --json \ --goal "open the dashboard" --url example.com ``` The key resolves the same way (`--key` > `$OPENROUTER_API_KEY` > `$CLEARCOTE_AGENT_KEY`). CLI options also include `--headless`, `--executable`, `--fingerprint`, and `--timezone`. --- ## Widevine / EME (DRM) (new in v0.1.0-pre.15, opt-in) Because Clearcote is 100% open source, the browser binary ships the EME/Widevine *plumbing* compiled in (`enable_widevine`) but NOT Google's proprietary CDM (that blob can't live in a FOSS package). Without a CDM, `navigator.requestMediaKeySystemAccess('com.widevine.alpha')` rejects — which is both a broken-DRM problem and a coherence tell (a real Chrome resolves it). How it works: the SDK lets you *opt in* to fetching the Widevine CDM at runtime — exactly how a stock Chrome receives it via the component updater. On a persistent context, `widevine=True` (Python) / `widevine: true` (Node) downloads the CDM once from Google's own component server, verifies its SHA-256 (a missing hash is refused — the CDM is a native DLL), seeds it into the profile, and enables it. The component updater is then un-suppressed (Playwright disables it by default) and forced to scan the pre-installed component (`--component-updater=fast-update`), so the engine registers the CDM and `requestMediaKeySystemAccess('com.widevine.alpha')` resolves + `createMediaKeys()` succeeds. DRM pages play. ```python from clearcote import launch_persistent_context ctx = launch_persistent_context("./profile-drm", widevine=True) # fetch + seed + enable the CDM ``` Notes: it is **opt-in** — the clearcote package never distributes Google's CDM; *you* trigger the download (cached under `~/.clearcote/WidevineCdm`; pre-fetch with `fetch_widevine()` / `fetchWidevine()`). Requires a **persistent** context (not the incognito `launch()`). Software-secure (L3) playback; hardware-secure (L1) is out of scope. Setup is best-effort — if the CDM can't be fetched, the launch proceeds without DRM rather than failing. ## Real-GPU canvas bridge (Canvas2D in v0.1.0-pre.11, WebGL in v0.1.0-pre.12; experimental, opt-in) The problem it solves: Clearcote renders canvas/WebGL on whatever GPU the host machine actually has. If a profile claims a *different* GPU than the host, strict anti-detect / browser-tampering checks that compare the rendered pixels against the claimed hardware can notice the mismatch (you cannot make one GPU emit another GPU's exact pixels in software). The fix: when `--canvas-bridge-url` is set, Blink forwards the canvas/WebGL OPERATIONS (not pre-recorded images) to a remote real-GPU host over WebSocket; the host renders them authentically and returns the pixels, which the readback APIs (`getImageData` / `toDataURL` / `readPixels` / `measureText`) return instead of the local render. Forwarding operations means it handles arbitrary, novel and procedurally-generated canvases — not just known probes. Opt-in: with no `--canvas-bridge-url`, Clearcote renders entirely locally, exactly as before. The render server is a headless Clearcote on the real-GPU host (same build/patches), so the returned pixels are exactly what a real Clearcote on that GPU produces — no approximation. Setup: - Server (on the real-GPU host): `python tools/canvas-bridge-server/server.py --backend local --chrome /path/to/chrome.exe --port 8443` (renders with the host's real GPU, no readback farble), or drive a remote real-GPU browser over the DevTools protocol with `--backend cdp --cdp-url ws://...`. - Tunnel: `ws://` is plaintext; put both hosts on a private network / Tailscale / WireGuard, or `ssh -N -L 8443:localhost:8443 user@bridge-host`. - Client: `--canvas-bridge-url=ws://127.0.0.1:8443 --canvas-bridge-auth=user:secret --no-sandbox --fingerprint=`. `--no-sandbox` is required (the client opens the socket from the renderer process). - Policy: `--canvas-bridge-mode=off|all|allow|deny`, `--canvas-bridge-allow=a.com,b.com`, `--canvas-bridge-deny=a.com,b.com`, and `--canvas-bridge-fallback=block|local`. - SDK: use `canvasBridge` / `canvas_bridge` with `url`, `auth`, `mode`, `allow`, `deny`, and `fallback`; setting `url` auto-adds `--no-sandbox`. Caveats: the canvas identity becomes the bridge host's GPU (every profile sharing one bridge host shares its canvas/WebGL hash — run one bridge host per identity group); procedural WebGL textures are bridged, while image/2D-canvas/video/ImageBitmap/3D texture sources fall back to local rendering for that canvas; each readback is a blocking round-trip (keep the host on the same LAN; 5s timeout then local fallback); plaintext transport (always tunnel). If the bridge is unreachable, Clearcote logs a warning and falls back to local rendering, so a misconfigured bridge never breaks the page. Full guide: https://github.com/clearcotelabs/clearcote-browser/blob/main/docs/CANVAS-BRIDGE.md --- ## Verification Every release is checksummed and GPG-signed against a single, out-of-band PINNED key. Verification = import the key, CONFIRM its fingerprint equals the pinned value, then check the signature. Never trust whatever key is merely attached to a release. Pinned signing key (ed25519): CA96 F185 F96A 693A EDB3 AC1F CB00 D851 B7A8 6B0F ```bash # 1. inspect the public key and CONFIRM the fingerprint matches the pinned value gpg --with-fingerprint --show-keys clearcote-signing-key.asc # 2. import it gpg --import clearcote-signing-key.asc # 3. verify the signed checksum file (expect: Good signature) gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt # 4. verify the archive's checksum (expect: OK) sha256sum -c clearcote-149.0.7827.114-windows-x64.zip.sha256 # 5. (optional) confirm the inner binary matches SHA256SUMS.txt unzip -p clearcote-149.0.7827.114-windows-x64.zip chrome.exe | sha256sum ``` A "this key is not certified with a trusted signature" warning on step 3 is expected — the proof is the FINGERPRINT MATCH plus the "Good signature", not a trust marker. Windows PowerShell hash-only check: ```powershell (Get-FileHash .\clearcote-149.0.7827.114-windows-x64.zip -Algorithm SHA256).Hash.ToLower() # must equal the zip line in SHA256SUMS.txt ``` Reproducibility: pinned upstream revision, a readable patch set, and a public `config/args.gn`. Chromium cross-builds are not yet bit-for-bit deterministic, so the guarantee today is "every change is an auditable patch and the config is public"; full hash-match attestation is on the roadmap. Canonical steps: docs/VERIFY.md. --- ## Build from source A Clearcote build is upstream Chromium plus a transparent, ordered patch set: 1. Fetch ungoogled-chromium at the pinned revision (Chromium 149). 2. Prune the source, then apply the ungoogled patch set (de-Googling). 3. Apply the Clearcote patches (engine-level identity controls). 4. Drop in the public `config/args.gn`. 5. `gn gen out/Default` then `ninja -C out/Default chrome`. ```bash git clone https://github.com/clearcotelabs/clearcote-browser cd clearcote-browser ./build.sh # or run scripts/00..05 individually ninja -C out/Default chrome ``` Windows is cross-built on Linux with clang-cl / lld-link (Windows SDK + CRT staging, toolchain shims) — every step and gotcha is documented to be reproducible. Canonical guides in the repo: - docs/BUILDING.md — full build-from-source guide - docs/PATCHES.md — what each patch in the set does - docs/RESEARCH-DOSSIER.md — deep cross-build notes - config/args.gn — the public build configuration Because the patch set and config are public and pinned, a build you produce should match the published artifact's behavior — and you can diff the patches against pristine upstream to see every single change. --- ## Roadmap Built in the open; dates omitted — milestones ship when verifiable. ([x] = done) Phase 0 — Foundations (shipped) - [x] Project scope, principles, and architecture - [x] De-Googled base via ungoogled-chromium, pinned to an exact upstream revision - [x] Reproducible source-prep pipeline (fetch -> prune -> patch -> verify) - [x] Clean, automated build from source on a commodity machine - [x] Published patch set: every change human-readable and individually documented Phase 1 — First public build (shipped) - [x] Windows x64 build as the first target - [x] Checksummed release artifacts (SHA-256) on GitHub Releases - [x] Reproducible build instructions a third party can follow to get a matching binary - [x] One-command source bootstrap for contributors Phase 2 — Coherent identity controls (in progress) - [x] Per-profile, deterministic identity seed (stable when you want, fresh when you don't) - [x] Engine-level controls for canvas, WebGL, audio, fonts, locale/timezone, navigator & hardware reporting - [x] Per-site coherence (farbling-style): same site stable, different sites uncorrelated - [x] Coherent persona model — one seed derives one believable Windows machine - [x] Leak-free WebRTC: reports the proxy egress IP (fabricated srflx, no real STUN), never the real IP - [x] WebGPU adapter coherent with the WebGL persona GPU - [x] UA reduced-major follows --fingerprint-brand-version; full screen-dimension spoofing - [x] Coherence pass: WebGL parameter limits, session-constant GPU, getBattery, connection, keyboard layout, AudioContext metadata, getScreenDetails, file: URL, navigator.share (pre.6) - [x] Full font-list spoofing - [x] Fingerprint profile import — present a real captured (or dataset) machine identity via --fingerprint-profile / SDK fingerprint_profile: drives hardware, screen, WebGL full getParameter table + extensions, audio, speech voices, fonts and CSS @media (pre.8) - [x] Cross-API coherence pass: WebGPU ↔ WebGL GPU for seed personas, Intl locale via --lang, speech default voice, UA-CH bitness/wow64/model, MediaCapabilities, enumerateDevices, storageQuota (pre.10) - [x] Real-GPU canvas bridge: Canvas2D + measureText (pre.11) and WebGL op-forwarding for geometry, shaders, uniforms, draws, procedural textures, readPixels and toDataURL (pre.12) - [x] Opt-in Widevine / EME (DRM): EME plumbing compiled in (enable_widevine), CDM fetched on demand by the SDK (never bundled) so requestMediaKeySystemAccess('com.widevine.alpha') resolves (pre.15) - [ ] Sensible, documented, privacy-respecting defaults Phase 3 — Automation SDK (in progress) - [x] Python + Node SDKs (clearcote on PyPI + npm), Playwright-first, with verified auto-download - [x] launch() returns a standard Playwright object — one-line migration - [x] Auto-download + local cache of the verified binary - [x] SDK v0.9.1 saved profiles, persistent contexts, binary prefetch helpers and opt-in auto-update with checksum/signature verification - [x] geoip auto-match (timezone / language / geo / WebRTC-IP) + humanized input + cursor overlay - [x] SDK 0.10.3: render-backend coherence probe (check_render_coherence / checkRenderCoherence), hardened defaults (drop --enable-automation, disable QUIC behind a proxy), humanized-input depth (min-jerk sum-of-sub-movements glide, ease-out scroll, gaussian typing) + async parity - [x] v0.1.0-pre.16 + SDK 0.10.4: grid-coherent text metrics + client rects (measureText on the 1/512 grid, main == OffscreenCanvas worker, getBoundingClientRect == Range) + a stealth-coherence regression gate that launches the shipped binary on every release - [x] Optional in-browser AI agent — launch_agent / run_agent_task + a clearcote-agent CLI (one-shot --goal/--url or -i REPL), bring-your-own OpenRouter key, OFF by default (pre.10) - [ ] Recipes: persistent profiles, proxy configuration, headless on servers Phase 4 — Trust & supply-chain (in progress) - [x] Signed releases — GPG detached signatures against a pinned key - [x] SHA-256 checksums + a SHA256SUMS manifest for every release - [ ] Build provenance / attestation (e.g. Sigstore-style) for every release - [ ] CI that builds, checksums, and publishes in the open Phase 5 — Beyond (planned) - [ ] Additional platforms (Linux, macOS) - [ ] A self-hostable profile manager for organizing identities and proxies - [ ] Integrations with common automation/agent frameworks - [ ] Hardening informed by open fingerprinting research --- ## FAQ Q: Is Clearcote legal to use? A: It's a privacy/automation tool for lawful purposes — protecting your own privacy, web/QA testing, research, accessibility, and automation you're authorized to run. You're responsible for how you use it; respect site terms and applicable laws. Q: Does it bypass a specific anti-bot service? A: It controls fingerprint SIGNALS so a session presents one coherent, plausible identity. It is not marketed against, and does not target, any specific detection product, and is not a guarantee of evading any system. Validate behavior yourself. Q: How is this different from JS-based stealth plugins? A: Those overwrite navigator properties at runtime with injected JavaScript — brittle and self-revealing. Clearcote changes the C++ engine, so values come from Chromium's own code paths; there's no injected layer to detect. Q: Is it undetectable? A: No tool is. Engine-level, coherent controls remove many common tells, but detection is an evolving space. Always validate against CreepJS, BrowserScan and Pixelscan for your use case. Q: Does it phone home or auto-update? A: No. It's built on ungoogled-chromium — Google services, telemetry and update beacons are removed. Q: Which platforms are supported? A: Windows x64 today. Additional platforms are on the roadmap. Q: Can I keep my existing Playwright/Puppeteer code? A: Yes — it's a drop-in browser. Point executablePath at the Clearcote binary. Q: How do I run multiple distinct identities? A: Use a different --fingerprint seed per identity (e.g. derived from a tenant/account id) and a separate user-data dir per profile for cookies/storage. Q: Is it really open source? A: Yes — BSD-3-Clause. Every patch is human-readable and the build is reproducible from source. Don't trust us, verify us. --- ## For agents & LLMs — integration recipe Machine-readable summary: https://clearcotelabs.com/llms.txt Repo conventions for contributors: AGENTS.md in the repository. ```json { "name": "Clearcote", "kind": "open-source anti-detect Chromium browser", "base": "ungoogled-chromium 149", "identity_model": "engine-level, coherent, per-site (farbling-style)", "automation": "drop-in for Playwright & Puppeteer (executablePath)", "platforms": ["windows-x64"], "license": "BSD-3-Clause", "repo": "https://github.com/clearcotelabs/clearcote-browser", "verify": "GPG-signed + sha256, pinned key", "control_via": "chromium command-line switches (args)" } ``` Minimal integration: 1. Resolve the binary path (e.g. C:\clearcote\chrome.exe). 2. Launch via your existing driver with executablePath. 3. Pass a deterministic --fingerprint= derived from the identity you're acting as. 4. Keep platform / timezone / locale coherent (see the flag reference). ```python from playwright.sync_api import sync_playwright SEED = "agent:" + task_id # stable, reproducible identity per task with sync_playwright() as p: browser = p.chromium.launch( executable_path=r"C:\clearcote\chrome.exe", args=[f"--fingerprint={SEED}", "--fingerprint-platform=windows"], ) page = browser.new_page() page.goto("https://example.com") ``` Tip: derive the seed from a stable id (tenant, account, task) so the same actor always gets the same browser fingerprint — reproducible and debuggable. --- ## Inspiration & credits - Chromium (BSD-3-Clause) — the engine. https://www.chromium.org/ - ungoogled-chromium (BSD-3-Clause) — the de-Googled base and patch tooling. https://github.com/ungoogled-software/ungoogled-chromium - fingerprint-chromium by adryfish (BSD-3-Clause) — pioneering engine-level fingerprint controls. https://github.com/adryfish/fingerprint-chromium - Brave — the per-site deterministic "farbling" model. https://brave.com/privacy-updates/3-fingerprint-randomization/ - Camoufox — a sibling open anti-detect browser (Firefox-based). https://github.com/daijro/camoufox ## Responsible use Clearcote is a privacy and automation tool intended for lawful purposes — protecting your own privacy, web/QA testing, research, accessibility, and automation you are authorized to run. You are responsible for how you use it. Respect website terms of service, applicable laws, and others' rights. Provided "as is", without warranty. --- Docs index: https://clearcotelabs.com/docs - Introduction: https://clearcotelabs.com/docs - Installation: https://clearcotelabs.com/docs/installation - Playwright/Puppeteer: https://clearcotelabs.com/docs/playwright - Fingerprint flags: https://clearcotelabs.com/docs/fingerprint - Architecture: https://clearcotelabs.com/docs/architecture - Verification: https://clearcotelabs.com/docs/verification - Build from source: https://clearcotelabs.com/docs/building - For agents & LLMs: https://clearcotelabs.com/docs/agents