[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-95":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":9,"totalLinesOfCode":9,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":9,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":45,"readmeContent":46,"aiSummary":47,"trendingCount":16,"starSnapshotCount":16,"syncStatus":48,"lastSyncTime":49,"discoverSource":50},95,"CloakBrowser","CloakHQ\u002FCloakBrowser","CloakHQ","Stealth Chromium that passes every bot detection test. Drop-in Playwright replacement with source-level fingerprint patches. 30\u002F30 tests passed.",null,"https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser","Python",25544,2029,125,101,0,193,1689,19219,1047,44.92,false,"main",[25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"anti-detect","bot-detection","browser-automation","chromium","cloudflare","fingerprint","playwright","recaptcha","stealth-browser","web-scraping","ai-agents","antidetect-browser","captcha-bypass","cloudflare-bypass","headless-browser","puppeteer","python","selenium","undetected","webscraping","2026-06-12 02:00:07","\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002Fcqkp6fG.png\" width=\"500\" alt=\"CloakBrowser\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Ca href=\"https:\u002F\u002Fpypi.org\u002Fproject\u002Fcloakbrowser\u002F\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fv\u002Fcloakbrowser\" alt=\"PyPI\">\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcloakbrowser\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fcloakbrowser\" alt=\"npm\">\u003C\u002Fa>\n\u003Ca href=\"LICENSE\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Fcloakhq\u002Fcloakbrowser?v=1\" alt=\"License\">\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flast-commit\u002Fcloakhq\u002Fcloakbrowser\" alt=\"Last Commit\">\u003C\u002Fa>\n\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Fcloakhq\u002Fcloakbrowser\" alt=\"Stars\">\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fpypi.org\u002Fproject\u002Fcloakbrowser\u002F\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fpepy\u002Fdt\u002Fcloakbrowser?label=pypi&logo=pypi&logoColor=white\" alt=\"PyPI Downloads\">\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcloakbrowser\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Fcloakbrowser?label=npm&logo=npm&logoColor=white\" alt=\"npm Downloads\">\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fhub.docker.com\u002Fr\u002Fcloakhq\u002Fcloakbrowser\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fpulls\u002Fcloakhq\u002Fcloakbrowser?label=docker&logo=docker&logoColor=white\" alt=\"Docker Pulls\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Ca href=\"https:\u002F\u002Fko-fi.com\u002Fcloakhq\">\u003Cimg src=\"https:\u002F\u002Fko-fi.com\u002Fimg\u002Fgithubbutton_sm.svg\" alt=\"Support on Ko-fi\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cbr>\n\n\u003Ch3 align=\"center\">Stealth Chromium that passes every bot detection test.\u003C\u002Fh3>\n\n\u003Ctable>\u003Ctr>\u003Ctd>\nNot a patched config. Not a JS injection. A real Chromium binary with fingerprints modified at the C++ source level. Antibot systems score it as a normal browser — because it \u003Cem>is\u003C\u002Fem> a normal browser.\n\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftable>\n\n\u003Cbr>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FIvB0It7.gif\" width=\"600\" alt=\"Cloudflare Turnstile — 3 Tests Passing\">\n\u003Cbr>\u003Cem>Cloudflare Turnstile — 3 live tests passing (headed mode, macOS)\u003C\u002Fem>\n\u003C\u002Fp>\n\n\u003Cbr>\n\n\u003Cp align=\"center\">\nDrop-in Playwright\u002FPuppeteer replacement for Python and JavaScript.\u003Cbr>\nSame API, same code — just swap the import. \u003Cstrong>3 lines of code, 30 seconds to unblock.\u003C\u002Fstrong>\n\u003C\u002Fp>\n\n- **49 source-level C++ patches** — canvas, WebGL, audio, fonts, GPU, screen, WebRTC, network timing, automation signals, CDP input behavior\n- **`humanize=True`** — human-like mouse curves, keyboard timing, and scroll patterns. One flag, behavioral detection passes\n- **0.9 reCAPTCHA v3 score** — human-level, server-verified\n- **Passes Cloudflare Turnstile**, FingerprintJS, BrowserScan — tested against 30+ detection sites\n- **Auto-updating binary** — background update checks, always on the latest stealth build\n- **`pip install cloakbrowser`** or **`npm install cloakbrowser`** — binary auto-downloads, zero config\n- **Free and open source** — no subscriptions, no usage limits\n\n**Try it now** — no install needed:\n```bash\ndocker run --rm cloakhq\u002Fcloakbrowser cloaktest\n```\n\n**Python:**\n```python\nfrom cloakbrowser import launch\n\nbrowser = launch()\npage = browser.new_page()\npage.goto(\"https:\u002F\u002Fprotected-site.com\")  # no more blocks\nbrowser.close()\n```\n\n**JavaScript (Playwright):**\n```javascript\nimport { launch } from 'cloakbrowser';\n\nconst browser = await launch();\nconst page = await browser.newPage();\nawait page.goto('https:\u002F\u002Fprotected-site.com');\nawait browser.close();\n```\n\nAlso works with Puppeteer: `import { launch } from 'cloakbrowser\u002Fpuppeteer'` ([details](#puppeteer))\n\n## Install\n\n**Python:**\n```bash\npip install cloakbrowser\n```\n\n**JavaScript \u002F Node.js:**\n```bash\n# With Playwright\nnpm install cloakbrowser playwright-core\n\n# With Puppeteer\nnpm install cloakbrowser puppeteer-core\n```\n\nOn first run, the stealth Chromium binary is automatically downloaded (~200MB, cached locally).\n\n**Optional:** Auto-detect timezone\u002Flocale from proxy IP:\n```bash\npip install cloakbrowser[geoip]\n```\n\n**Migrating from Playwright?** One-line change:\n\n```diff\n- from playwright.sync_api import sync_playwright\n- pw = sync_playwright().start()\n- browser = pw.chromium.launch()\n+ from cloakbrowser import launch\n+ browser = launch()\n\npage = browser.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")\n# ... rest of your code works unchanged\n```\n\n> ⭐ **Star** to show support — **[Watch releases](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fsubscription)** to get notified when new builds drop.\n\n## Browser Profile Manager\n\nSelf-hosted alternative to Multilogin, GoLogin, and AdsPower. Create browser profiles with unique fingerprints, proxies, and persistent sessions. Launch and interact with them in your browser via noVNC.\n\n```bash\ndocker run -p 8080:8080 -v cloakprofiles:\u002Fdata cloakhq\u002Fcloakbrowser-manager\n```\n\nOpen [http:\u002F\u002Flocalhost:8080](http:\u002F\u002Flocalhost:8080). Create a profile. Click **Launch**. Done.\n\n→ **[CloakBrowser Manager](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser-Manager)** — free, open source (MIT)\n\n---\n\n## Latest: v0.3.26 (Chromium 146.0.7680.177.4)\n\n- **`launch_context_async()`** — async counterpart to `launch_context()`. Forwards kwargs to `browser.new_context()` for `storage_state`, `permissions`, `extra_http_headers` without a persistent profile folder.\n- **JS `contextOptions` escape hatch** — forward arbitrary options (including `storageState`) to Playwright's `newContext()` from `launchContext()` \u002F `launchPersistentContext()`.\n- **Native SOCKS5 proxy** — `proxy=\"socks5:\u002F\u002Fuser:pass@host:port\"` works directly in all launch functions, Python + JS. QUIC\u002FHTTP3 tunnels through SOCKS5 via UDP ASSOCIATE.\n- **Chromium 146 upgrade** — rebased all patches from 145.0.7632.x to 146.0.7680.177\n- **57 fingerprint patches** — additional detection-vector coverage (WebAuthn, AAC audio, window position) and WebGL\u002Fcanvas consistency fixes\n- **WebRTC IP spoofing** — `--fingerprint-webrtc-ip=auto` resolves your proxy's exit IP and spoofs WebRTC ICE candidates. Auto-injected when using `geoip=True` (no extra network call)\n- **Proxy signal removal** — DNS\u002Fconnect\u002FSSL timing zeroed, proxy cache headers stripped, Proxy-Connection header leak removed\n- **`cloakserve` CDP multiplexer** — rewritten as a multi-connection CDP proxy with per-connection fingerprint seeds\n- **Humanize CDP isolation** — keyboard events now use isolated worlds and trusted dispatch for better behavioral stealth\n- **`humanize=True`** — one flag makes all mouse, keyboard, and scroll interactions behave like a real user. Bézier curves, per-character typing, realistic scroll patterns\n- **Stealthy with zero flags** — binary auto-generates a random fingerprint seed at startup. No configuration required\n- **Timezone & locale from proxy IP** — `launch(proxy=\"...\", geoip=True)` auto-detects timezone and locale\n- **Persistent profiles** — `launch_persistent_context()` keeps cookies and localStorage across sessions, bypasses incognito detection\n\nSee the full [CHANGELOG.md](CHANGELOG.md) for details.\n\n## Why CloakBrowser?\n\n- **Config-level patches break** — `playwright-stealth`, `undetected-chromedriver`, and `puppeteer-extra` inject JavaScript or tweak flags. Every Chrome update breaks them. Antibot systems detect the patches themselves.\n- **CloakBrowser patches Chromium source code** — fingerprints are modified at the C++ level, compiled into the binary. Detection sites see a real browser because it *is* a real browser.\n- **Source-level stealth** — C++ patches handle fingerprints (GPU, screen, UA, hardware reporting) at the binary level. No JavaScript injection, no config-level hacks. Most stealth tools only patch at the surface.\n- **Same behavior everywhere** — works identically local, in Docker, and on VPS. No environment-specific patches or config needed.\n- **Works with AI agents and automation frameworks** — drop-in stealth for browser-use, Crawl4AI, Scrapling, Stagehand, LangChain, Selenium, and more. See [integrations](#framework-integrations).\n\nCloakBrowser doesn't solve CAPTCHAs — it prevents them from appearing. No CAPTCHA-solving services, no proxy rotation built in — bring your own proxies, use the Playwright API you already know.\n\n## Test Results\n\nAll tests verified against live detection services. Last tested: Apr 2026 (Chromium 146).\n\n| Detection Service | Stock Playwright | CloakBrowser | Notes |\n|---|---|---|---|\n| **reCAPTCHA v3** | 0.1 (bot) | **0.9** (human) | Server-side verified |\n| **Cloudflare Turnstile** (non-interactive) | FAIL | **PASS** | Auto-resolve |\n| **Cloudflare Turnstile** (managed) | FAIL | **PASS** | Single click |\n| **ShieldSquare** | BLOCKED | **PASS** | Production site |\n| **FingerprintJS** bot detection | DETECTED | **PASS** | demo.fingerprint.com |\n| **BrowserScan** bot detection | DETECTED | **NORMAL** (4\u002F4) | browserscan.net |\n| **bot.incolumitas.com** | 13 fails | **1 fail** | WEBDRIVER spec only |\n| **deviceandbrowserinfo.com** | 6 true flags | **0 true flags** | `isBot: false` |\n| `navigator.webdriver` | `true` | **`false`** | Source-level patch |\n| `navigator.plugins.length` | 0 | **5** | Real plugin list |\n| `window.chrome` | `undefined` | **`object`** | Present like real Chrome |\n| UA string | `HeadlessChrome` | **`Chrome\u002F146.0.0.0`** | No headless leak |\n| CDP detection | Detected | **Not detected** | `isAutomatedWithCDP: false` |\n| TLS fingerprint | Mismatch | **Identical to Chrome** | ja3n\u002Fja4\u002Fakamai match |\n| | | **Tested against 30+ detection sites** | |\n\n### Proof\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FhvIQyMv.png\" width=\"600\" alt=\"reCAPTCHA v3 — Score 0.9\">\n\u003Cbr>\u003Cem>reCAPTCHA v3 score 0.9 — server-side verified (human-level)\u003C\u002Fem>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FqMIRfhq.png\" width=\"600\" alt=\"Cloudflare Turnstile — Success\">\n\u003Cbr>\u003Cem>Cloudflare Turnstile non-interactive challenge — auto-resolved\u003C\u002Fem>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FPRsw6rT.png\" width=\"600\" alt=\"BrowserScan — Normal\">\n\u003Cbr>\u003Cem>BrowserScan bot detection — NORMAL (4\u002F4 checks passed)\u003C\u002Fem>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002F9n2C7tu.png\" width=\"600\" alt=\"FingerprintJS — Passed\">\n\u003Cbr>\u003Cem>FingerprintJS web-scraping demo — data served, not blocked\u003C\u002Fem>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FsrCcFtK.png\" width=\"600\" alt=\"deviceandbrowserinfo.com — You are human!\">\n\u003Cbr>\u003Cem>deviceandbrowserinfo.com behavioral bot detection — \"You are human!\" with humanize=True (24\u002F24 signals passed)\u003C\u002Fem>\n\u003C\u002Fp>\n\n## Comparison\n\n| Feature | Playwright | playwright-stealth | undetected-chromedriver | Camoufox | CloakBrowser |\n|---|---|---|---|---|---|\n| reCAPTCHA v3 score | 0.1 | 0.3-0.5 | 0.3-0.7 | 0.7-0.9 | **0.9** |\n| Cloudflare Turnstile | Fail | Sometimes | Sometimes | Pass | **Pass** |\n| Patch level | None | JS injection | Config patches | C++ (Firefox) | **C++ (Chromium)** |\n| Survives Chrome updates | N\u002FA | Breaks often | Breaks often | Yes | **Yes** |\n| Maintained | Yes | Stale | Stale | Unstable | **Active** |\n| Browser engine | Chromium | Chromium | Chrome | Firefox | **Chromium** |\n| Playwright API | Native | Native | No (Selenium) | No | **Native** |\n\n## How It Works\n\nCloakBrowser is a thin wrapper (Python + JavaScript) around a custom-built Chromium binary:\n\n1. **You install** → `pip install cloakbrowser` or `npm install cloakbrowser`\n2. **First launch** → binary auto-downloads for your platform (Chromium 146)\n3. **Every launch** → Playwright or Puppeteer starts with our binary + stealth args\n4. **You write code** → standard Playwright\u002FPuppeteer API, nothing new to learn\n\nThe binary includes 49 source-level patches covering canvas, WebGL, audio, fonts, GPU, screen properties, WebRTC, network timing, hardware reporting, automation signal removal, and CDP input behavior mimicking.\n\nThese are compiled into the Chromium binary — not injected via JavaScript, not set via flags.\n\nBinary downloads are verified with SHA-256 checksums to ensure integrity.\n\n## API\n\n### `launch()`\n\n```python\nfrom cloakbrowser import launch\n\n# Basic — headless, default stealth config\nbrowser = launch()\n\n# Headed mode (see the browser window)\nbrowser = launch(headless=False)\n\n# With proxy (HTTP or SOCKS5)\nbrowser = launch(proxy=\"http:\u002F\u002Fuser:pass@proxy:8080\")\nbrowser = launch(proxy=\"socks5:\u002F\u002Fuser:pass@proxy:1080\")\n\n# With proxy dict (bypass, separate auth fields)\nbrowser = launch(proxy={\"server\": \"http:\u002F\u002Fproxy:8080\", \"bypass\": \".google.com\", \"username\": \"user\", \"password\": \"pass\"})\n\n# With extra Chrome args\nbrowser = launch(args=[\"--disable-gpu\"])\n\n# With timezone and locale (sets binary flags — no detectable CDP emulation)\nbrowser = launch(timezone=\"America\u002FNew_York\", locale=\"en-US\")\n\n# Auto-detect timezone\u002Flocale from proxy IP (requires: pip install cloakbrowser[geoip])\n# Also auto-injects --fingerprint-webrtc-ip to prevent WebRTC IP leaks (no extra cost)\n# Note: makes HTTP calls through your proxy to resolve exit IP (ipify.org, checkip.amazonaws.com)\nbrowser = launch(proxy=\"http:\u002F\u002Fproxy:8080\", geoip=True)\n\n# Explicit timezone\u002Flocale always win over auto-detection\nbrowser = launch(proxy=\"http:\u002F\u002Fproxy:8080\", geoip=True, timezone=\"Europe\u002FLondon\")\n\n# WebRTC IP spoofing only (no geoip dep needed — resolves exit IP via HTTP call through proxy)\nbrowser = launch(proxy=\"http:\u002F\u002Fproxy:8080\", args=[\"--fingerprint-webrtc-ip=auto\"])\n\n# Explicit WebRTC IP (no network call)\nbrowser = launch(proxy=\"http:\u002F\u002Fproxy:8080\", args=[\"--fingerprint-webrtc-ip=1.2.3.4\"])\n\n# Human-like mouse, keyboard, and scroll behavior\nbrowser = launch(humanize=True)\n\n# With slower, more deliberate movements\nbrowser = launch(humanize=True, human_preset=\"careful\")\n\n# Without default stealth args (bring your own fingerprint flags)\nbrowser = launch(stealth_args=False, args=[\"--fingerprint=12345\"])\n```\n\nReturns a standard Playwright `Browser` object. All Playwright methods work: `new_page()`, `new_context()`, `close()`, etc.\n\n### `launch_async()`\n\n```python\nimport asyncio\nfrom cloakbrowser import launch_async\n\nasync def main():\n    browser = await launch_async()\n    page = await browser.new_page()\n    await page.goto(\"https:\u002F\u002Fexample.com\")\n    print(await page.title())\n    await browser.close()\n\nasyncio.run(main())\n```\n\n### `launch_context()`\n\nConvenience function that creates browser + context in one call with user agent, viewport, locale, and timezone:\n\n```python\nfrom cloakbrowser import launch_context\n\ncontext = launch_context(\n    user_agent=\"Custom UA\",\n    viewport={\"width\": 1920, \"height\": 1080},\n    locale=\"en-US\",\n    timezone=\"America\u002FNew_York\",\n)\npage = context.new_page()\npage.goto(\"https:\u002F\u002Fprotected-site.com\")\ncontext.close()\n```\n\nExtra kwargs are forwarded to Playwright's `browser.new_context()` — use this for `storage_state`, `permissions`, `extra_http_headers`, etc. without needing a persistent profile folder:\n\n```python\nfrom cloakbrowser import launch_context\n\n# Restore a saved session (cookies, localStorage) from a JSON file\ncontext = launch_context(storage_state=\"state.json\")\npage = context.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")\n# Save state back for next run\ncontext.storage_state(path=\"state.json\")\ncontext.close()\n```\n\n### `launch_context_async()`\n\nAsync counterpart to `launch_context()`. Same signature and kwargs forwarding:\n\n```python\nimport asyncio\nfrom cloakbrowser import launch_context_async\n\nasync def main():\n    ctx = await launch_context_async(storage_state=\"state.json\")\n    page = await ctx.new_page()\n    await page.goto(\"https:\u002F\u002Fexample.com\")\n    await ctx.storage_state(path=\"state.json\")\n    await ctx.close()\n\nasyncio.run(main())\n```\n\n### `launch_persistent_context()`\n\nSame as `launch_context()`, but with a persistent user profile. Cookies, localStorage, and cache persist across sessions.\n\nUse this when you need to:\n- **Stay logged in** across runs (cookies\u002Fsessions survive restarts)\n- **Bypass incognito detection** (some sites flag empty, ephemeral profiles)\n- **Load Chrome extensions** (extensions only work from a real user data dir)\n- **Build natural browsing history** (cached fonts, service workers, IndexedDB accumulate over time, making the profile look more realistic)\n\n```python\nfrom cloakbrowser import launch_persistent_context\n\n# First run — creates the profile\nctx = launch_persistent_context(\".\u002Fmy-profile\", headless=False)\npage = ctx.new_page()\npage.goto(\"https:\u002F\u002Fprotected-site.com\")\nctx.close()  # profile saved\n\n# Next run — cookies, localStorage restored automatically\nctx = launch_persistent_context(\".\u002Fmy-profile\", headless=False)\n```\n\nSupports all the same options as `launch_context()`: `proxy`, `user_agent`, `viewport`, `locale`, `timezone`, `color_scheme`, `geoip`.\n\nAsync version: `launch_persistent_context_async()`.\n\n**Storage quota and detection tradeoff:** By default, the binary normalizes storage quota to pass FingerprintJS, which blocks persistent contexts that report non-incognito quota values. This means detection services that penalize incognito mode (like BrowserScan's `notPrivate` check, -10 points) will still flag it. If your target site penalizes incognito but doesn't use FingerprintJS, set a higher quota to appear as a regular profile:\n\n```python\nctx = launch_persistent_context(\".\u002Fmy-profile\", args=[\"--fingerprint-storage-quota=5000\"])\n```\n\n| Quota setting | FingerprintJS | BrowserScan `notPrivate` |\n|---|---|---|\n| Default (auto, ~500MB) | PASS | -10 (flagged as incognito) |\n| `--fingerprint-storage-quota=5000` | May trigger detection | PASS (appears non-incognito) |\n\n### CLI\n\nPre-download the binary or check installation status from the command line:\n\n```bash\npython -m cloakbrowser install      # Download binary with progress output\npython -m cloakbrowser info         # Show version, path, platform\npython -m cloakbrowser update       # Check for and download newer binary\npython -m cloakbrowser clear-cache  # Remove cached binaries\n```\n\n### Utility Functions\n\n```python\nfrom cloakbrowser import binary_info, clear_cache, ensure_binary\n\n# Check binary installation status\nprint(binary_info())\n# {'version': '146.0.7680.177.3', 'platform': 'linux-x64', 'installed': True, ...}\n\n# Force re-download\nclear_cache()\n\n# Pre-download binary (e.g., during Docker build)\nensure_binary()\n```\n\n## JavaScript \u002F Node.js API\n\nCloakBrowser ships a TypeScript package with full type definitions. Choose Playwright or Puppeteer — same stealth binary underneath.\n\n### Playwright (default)\n\n```javascript\nimport { launch, launchContext, launchPersistentContext } from 'cloakbrowser';\n\n\u002F\u002F Basic\nconst browser = await launch();\n\n\u002F\u002F With options\nconst browser = await launch({\n  headless: false,\n  proxy: 'http:\u002F\u002Fuser:pass@proxy:8080',\n  args: ['--fingerprint=12345'],\n  timezone: 'America\u002FNew_York',\n  locale: 'en-US',\n  humanize: true,\n});\n\n\u002F\u002F Convenience: browser + context in one call\nconst context = await launchContext({\n  userAgent: 'Custom UA',\n  viewport: { width: 1920, height: 1080 },\n  locale: 'en-US',\n  timezone: 'America\u002FNew_York',\n});\nconst page = await context.newPage();\n\n\u002F\u002F Persistent profile — cookies\u002FlocalStorage survive restarts, avoids incognito detection\nconst ctx = await launchPersistentContext({\n  userDataDir: '.\u002Fchrome-profile',\n  headless: false,\n  proxy: 'http:\u002F\u002Fuser:pass@proxy:8080',\n});\n```\n\n> **Note:** Each example above is standalone — not meant to run as one block.\n\nAll Python options work in JS: `stealthArgs: false` to disable defaults, `geoip: true` to auto-detect timezone\u002Flocale from proxy IP.\n\n### Puppeteer\n\n> **Note:** The Playwright wrapper is recommended for sites with reCAPTCHA Enterprise. Puppeteer's CDP protocol leaks automation signals that reCAPTCHA Enterprise can detect, causing intermittent 403 errors. This is a known Puppeteer limitation, not specific to CloakBrowser. Use Playwright for best results.\n\n```javascript\nimport { launch } from 'cloakbrowser\u002Fpuppeteer';\n\nconst browser = await launch({ headless: true });\nconst page = await browser.newPage();\nawait page.goto('https:\u002F\u002Fexample.com');\nawait browser.close();\n```\n\n### Utility Functions (JS)\n\n```javascript\nimport { ensureBinary, clearCache, binaryInfo } from 'cloakbrowser';\n\n\u002F\u002F Pre-download binary (e.g., during Docker build)\nawait ensureBinary();\n\n\u002F\u002F Check installation status\nconsole.log(binaryInfo());\n\n\u002F\u002F Force re-download\nclearCache();\n```\n\n## Human Behavior\n\nPass `humanize=True` to make all mouse, keyboard, and scroll interactions indistinguishable from real users. All Playwright calls (`page.click()`, `page.fill()`, `page.type()`, `page.mouse.*`, `page.keyboard.*`, Locator API) and Puppeteer calls (`page.click()`, `page.type()`, `page.mouse.*`, `page.keyboard.*`, ElementHandle API) are automatically replaced with human-like equivalents. No code changes needed.\n\n```python\nbrowser = launch(humanize=True)\npage = browser.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")\npage.locator(\"#email\").fill(\"user@example.com\")  # per-character timing, thinking pauses\npage.locator(\"button[type=submit]\").click()       # Bézier curve, realistic aim point\n```\n\n```javascript\n\u002F\u002F Playwright\nimport { launch } from 'cloakbrowser';\nconst browser = await launch({ humanize: true });\n```\n\n```javascript\n\u002F\u002F Puppeteer\nimport { launch } from 'cloakbrowser\u002Fpuppeteer';\nconst browser = await launch({ humanize: true });\n```\n\n**What changes:**\n\n| Interaction | Default | With `humanize=True` |\n|---|---|---|\n| Mouse movement | Instant teleport | Bézier curve with easing and slight overshoot |\n| Clicks | Instant | Realistic aim point + hold duration |\n| Keyboard | Instant fill | Per-character timing, thinking pauses, occasional typos with self-correction |\n| Scroll | Jump | Accelerate → cruise → decelerate micro-steps |\n| `fill()` | Instant value set | Clears existing content, types character by character |\n\n**Presets** — `default` (normal speed) or `careful` (slower, more deliberate, idle micro-movements between actions):\n\n```python\nbrowser = launch(humanize=True, human_preset=\"careful\")\n```\n\n```javascript\nconst browser = await launch({ humanize: true, humanPreset: 'careful' });\n```\n\n**Custom config** — override any parameter:\n\n```python\nbrowser = launch(humanize=True, human_config={\n    \"mistype_chance\": 0.05,              # 5% typo rate with self-correction\n    \"typing_delay\": 100,                 # slower typing (ms per character)\n    \"idle_between_actions\": True,        # micro-movements between clicks\n    \"idle_between_duration\": [0.3, 0.8], # idle duration range (seconds)\n})\n```\n\n```javascript\nconst browser = await launch({\n    humanize: true,\n    humanConfig: {\n        mistype_chance: 0.05,\n        typing_delay: 100,\n        idle_between_actions: true,\n        idle_between_duration: [0.3, 0.8],\n    }\n});\n```\n\nAccess the original un-patched Playwright page at `page._original` if you need raw speed for a specific call.\n\n> **Note (Playwright):** Always use `page.click(selector)`, `page.type(selector, text)`, `page.hover(selector)`, or `page.locator(selector).*` — these go through the full humanize pipeline. Avoid `page.query_selector()` — `ElementHandle` objects bypass all patches, so mouse movement teleports, keyboard events fire without timing, and scroll has no human curve.\n>\n> **Note (Puppeteer):** Both selector-based methods (`page.click()`, `page.type()`) and ElementHandle methods (`el.click()`, `el.type()`) are fully humanized. `page.$()`, `page.$$()`, and `page.waitForSelector()` return patched handles automatically.\n\n> Contributed by [@evelaa123](https:\u002F\u002Fgithub.com\u002Fevelaa123) — full Playwright and Puppeteer API coverage.\n\n## Configuration\n\n| Env Variable | Default | Description |\n|---|---|---|\n| `CLOAKBROWSER_BINARY_PATH` | — | Skip download, use a local Chromium binary |\n| `CLOAKBROWSER_CACHE_DIR` | `~\u002F.cloakbrowser` | Binary cache directory |\n| `CLOAKBROWSER_DOWNLOAD_URL` | `cloakbrowser.dev` | Custom download URL for binary |\n| `CLOAKBROWSER_AUTO_UPDATE` | `true` | Set to `false` to disable background update checks |\n| `CLOAKBROWSER_SKIP_CHECKSUM` | `false` | Set to `true` to skip SHA-256 verification after download |\n\n## Fingerprint Management\n\nThe binary is **stealthy by default** — no flags needed. It auto-generates a random fingerprint seed at startup and spoofs all detectable values (GPU, hardware specs, screen dimensions, canvas, WebGL, audio, fonts). Every launch produces a fresh, coherent identity.\n\n**How fingerprinting works:**\n\n| Scenario | What happens |\n|----------|-------------|\n| **No flags** | Random seed auto-generated at startup. GPU, screen, hardware specs, and all noise patches are spoofed automatically. Fresh identity each launch. |\n| **`--fingerprint=seed`** | Deterministic identity from the seed. Same seed = same fingerprint across launches. Use this for session persistence (returning visitor). |\n| **`--fingerprint=seed` + explicit flags** | Explicit flags override individual auto-generated values. The seed fills in everything else. |\n\nThe binary detects its platform at compile time — a macOS binary reports as macOS with Apple GPU, a Linux binary reports as Linux with NVIDIA GPU. The **wrapper** overrides this on Linux by passing `--fingerprint-platform=windows`, so sessions appear as Windows desktops (more common fingerprint, harder to cluster). Use `--fingerprint-platform` for cross-platform spoofing when running the binary directly.\n\n> **Tip: Use a fixed seed when revisiting the same site.** A random seed makes every session look like a different device — which can be suspicious when hitting the same site repeatedly from the same IP. For reCAPTCHA v3 Enterprise and similar scoring systems, a fixed seed produces a consistent fingerprint across sessions, making you look like a returning visitor:\n> ```python\n> browser = launch(args=[\"--fingerprint=12345\"])\n> ```\n> ```javascript\n> const browser = await launch({ args: ['--fingerprint=12345'] });\n> ```\n\n### Default Fingerprint\n\nEvery `launch()` call sets these automatically. The **wrapper** applies platform-aware defaults — on Linux it spoofs as Windows for a more common fingerprint, on macOS it runs as a native Mac browser:\n\n| Flag | Linux\u002FWindows Default | macOS Default | Controls |\n|------|--------------|---------------|----------|\n| `--fingerprint` | Random (10000–99999) | Random (10000–99999) | Master seed for canvas, WebGL, audio, fonts, client rects |\n| `--fingerprint-platform` | `windows` | `macos` | `navigator.platform`, User-Agent OS, GPU pool selection |\n\nThe binary auto-generates everything else from the seed: GPU, hardware concurrency, device memory, and screen dimensions. Each seed produces a unique, consistent fingerprint. Override with explicit flags if needed.\n\n> **Using the binary directly?** It works out of the box with zero flags -- the binary auto-spoofs everything. Pass `--fingerprint=seed` for a persistent identity, or use explicit flags like `--fingerprint-gpu-renderer` to override any auto-generated value.\n\n### Additional Flags\n\nSupported by the binary but **not set by default** — pass via `args` to customize:\n\n| Flag | Controls |\n|------|----------|\n| `--fingerprint-gpu-vendor` | WebGL `UNMASKED_VENDOR_WEBGL` (auto-generated from seed + platform) |\n| `--fingerprint-gpu-renderer` | WebGL `UNMASKED_RENDERER_WEBGL` (auto-generated from seed + platform) |\n| `--fingerprint-hardware-concurrency` | `navigator.hardwareConcurrency` (auto-generated: `8`) |\n| `--fingerprint-device-memory` | `navigator.deviceMemory` in GB (auto-generated: `8`) |\n| `--fingerprint-screen-width` | Screen width (auto-generated: `1920` Win\u002FLinux, `1440` macOS) |\n| `--fingerprint-screen-height` | Screen height (auto-generated: `1080` Win\u002FLinux, `900` macOS) |\n| `--fingerprint-brand` | Browser brand: `Chrome`, `Edge`, `Opera`, `Vivaldi` |\n| `--fingerprint-brand-version` | Brand version (UA + Client Hints) |\n| `--fingerprint-platform-version` | Client Hints platform version |\n| `--fingerprint-location` | Geolocation coordinates |\n| `--fingerprint-timezone` | Timezone (e.g. `America\u002FNew_York`) |\n| `--fingerprint-locale` | Locale (e.g. `en-US`) |\n| `--fingerprint-storage-quota` | Override storage quota in MB — affects `storage.estimate()`, `storageBuckets`, and legacy webkit APIs. Auto-normalized when `--fingerprint` is set |\n| `--fingerprint-taskbar-height` | Override taskbar height (binary defaults: Win=48, Mac=95, Linux=0) |\n| `--fingerprint-fonts-dir` | Path to directory containing target-platform fonts (see [Font Setup on Linux](#font-setup-on-linux)) |\n| `--fingerprint-webrtc-ip` | WebRTC ICE candidate IP replacement. Use `auto` to resolve from proxy exit IP (makes an HTTP call through the proxy), or pass an explicit IP. Auto-injected when `geoip=True` |\n| `--fingerprint-noise=false` | Disable noise injection (canvas, WebGL, audio, client rects) while keeping the deterministic fingerprint seed active |\n| `--enable-blink-features=FakeShadowRoot` | Access closed shadow DOM elements |\n\n> **Note:** All stealth tests were verified with the default fingerprint config above. Changing these flags may affect detection results — test your configuration before using in production.\n\n### Font Setup on Linux\n\n**Required for aggressive anti-bot sites (Kasada, Akamai).** These systems render emoji on a hidden canvas and hash the pixel output. Minimal Linux environments (Docker, cloud VMs) often lack emoji and extended fonts, producing hashes that don't match any real browser. Install standard font packages to fix this:\n\n```bash\nsudo apt install -y fonts-noto-color-emoji fonts-freefont-ttf fonts-unifont \\\n    fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf\n```\n\nThe Docker image (`cloakhq\u002Fcloakbrowser`) ships with these pre-installed. If you run the binary directly on a Linux server or in a custom Docker image, install them manually.\n\n**Optional: Windows fonts for CreepJS font enumeration.** The packages above fix anti-bot canvas checks but won't improve your CreepJS font score. For that, you need actual Windows fonts (Segoe UI, Calibri, Bahnschrift, etc.) from a Windows machine's `C:\\Windows\\Fonts\\` directory — `ttf-mscorefonts-installer` only has old XP-era fonts and isn't enough.\n\n```bash\nmkdir -p ~\u002F.local\u002Fshare\u002Ffonts\u002Fwindows\ncp \u002Fpath\u002Fto\u002Fwindows\u002Ffonts\u002F*.ttf ~\u002F.local\u002Fshare\u002Ffonts\u002Fwindows\u002F\ncp \u002Fpath\u002Fto\u002Fwindows\u002Ffonts\u002F*.TTF ~\u002F.local\u002Fshare\u002Ffonts\u002Fwindows\u002F\nfc-cache -f  # mandatory for manually copied fonts\n```\n\n```python\nbrowser = launch(\n    args=[\"--fingerprint-fonts-dir=\u002Fhome\u002Fuser\u002F.local\u002Fshare\u002Ffonts\u002Fwindows\"],\n)\n```\n\n### Examples\n\n```python\n# Pin a seed for a persistent identity\nbrowser = launch(args=[\"--fingerprint=42069\"])\n\n# Full control — disable defaults, set everything yourself\nbrowser = launch(stealth_args=False, args=[\n    \"--fingerprint=42069\",\n    \"--fingerprint-platform=windows\",\n])\n\n# Override GPU to look like a specific machine\nbrowser = launch(args=[\n    \"--fingerprint-gpu-vendor=Intel Inc.\",\n    \"--fingerprint-gpu-renderer=Intel Iris OpenGL Engine\",\n])\n```\n\n## Examples\n\n**Python** — see [`examples\u002F`](examples\u002F):\n- [`basic.py`](examples\u002Fbasic.py) — Launch and load a page\n- [`persistent_context.py`](examples\u002Fpersistent_context.py) — Persistent profile with cookie\u002FlocalStorage persistence\n- [`recaptcha_score.py`](examples\u002Frecaptcha_score.py) — Check your reCAPTCHA v3 score\n- [`stealth_test.py`](examples\u002Fstealth_test.py) — Run against 6 detection sites\n- [`fingerprint_scan_test.py`](examples\u002Ffingerprint_scan_test.py) — Test against fingerprint-scan.com and CreepJS\n\n**JavaScript** — see [`js\u002Fexamples\u002F`](js\u002Fexamples\u002F):\n- [`basic-playwright.ts`](js\u002Fexamples\u002Fbasic-playwright.ts) — Playwright launch and load\n- [`basic-puppeteer.ts`](js\u002Fexamples\u002Fbasic-puppeteer.ts) — Puppeteer launch and load\n- [`stealth-test.ts`](js\u002Fexamples\u002Fstealth-test.ts) — Run against 6 detection sites\n\n### Framework Integrations\n\nCloakBrowser works with any framework that uses Playwright or Chromium:\n\n```python\n# Option 1: Framework launches our binary directly (Selenium, Stagehand, UC)\nfrom cloakbrowser.download import ensure_binary\nfrom cloakbrowser.config import get_default_stealth_args\nbinary_path = ensure_binary()          # auto-downloads if needed\nstealth_args = get_default_stealth_args()  # all fingerprint flags\n\n# Option 2: CloakBrowser launches first, framework connects via CDP (browser-use, Crawl4AI, Scrapling)\nfrom cloakbrowser import launch_async\nbrowser = await launch_async(args=[\"--remote-debugging-port=9242\"])\n# Connect your framework to http:\u002F\u002F127.0.0.1:9242 — all stealth flags are set\n# Note: humanize requires the wrapper (see below)\n```\n\n> **Humanize over CDP**: Stealth fingerprint patches work automatically over CDP, but `humanize=True` is a wrapper-level feature. If you connect to CloakBrowser via CDP from a separate script, import the patching functions to add humanization:\n>\n> ```js\n> import { patchBrowser, resolveConfig } from 'cloakbrowser\u002Fhuman';\n> patchBrowser(browser, resolveConfig('default'));\n> ```\n\n| Framework | Stars | Language | Example |\n|-----------|-------|----------|---------|\n| [browser-use](https:\u002F\u002Fgithub.com\u002Fbrowser-use\u002Fbrowser-use) | 70K | Python | [`browser_use_example.py`](examples\u002Fintegrations\u002Fbrowser_use_example.py) |\n| [Crawl4AI](https:\u002F\u002Fgithub.com\u002Funclecode\u002Fcrawl4ai) | 58K | Python | [`crawl4ai_example.py`](examples\u002Fintegrations\u002Fcrawl4ai_example.py) |\n| [Crawlee](https:\u002F\u002Fgithub.com\u002Fapify\u002Fcrawlee-python) | 8.6K | Python | [`crawlee_example.py`](examples\u002Fintegrations\u002Fcrawlee_example.py) |\n| [Scrapling](https:\u002F\u002Fgithub.com\u002FD4Vinci\u002FScrapling) | 21K | Python | [`scrapling_example.py`](examples\u002Fintegrations\u002Fscrapling_example.py) |\n| [Stagehand](https:\u002F\u002Fgithub.com\u002Fbrowserbase\u002Fstagehand) | 21K | TypeScript | [`stagehand.ts`](js\u002Fexamples\u002Fstagehand.ts) |\n| [LangChain](https:\u002F\u002Fgithub.com\u002Flangchain-ai\u002Flangchain) | 100K+ | Python | [`langchain_loader.py`](examples\u002Fintegrations\u002Flangchain_loader.py) |\n| [Selenium](https:\u002F\u002Fgithub.com\u002FSeleniumHQ\u002Fselenium) | — | Python | [`selenium_example.py`](examples\u002Fintegrations\u002Fselenium_example.py) |\n| [undetected-chromedriver](https:\u002F\u002Fgithub.com\u002Fultrafunkamsterdam\u002Fundetected-chromedriver) | 12K | Python | [`undetected_chromedriver.py`](examples\u002Fintegrations\u002Fundetected_chromedriver.py) |\n| [agent-browser](https:\u002F\u002Fgithub.com\u002Fnichochar\u002Fagent-browser) | — | Shell | [`agent_browser.sh`](examples\u002Fintegrations\u002Fagent_browser.sh) |\n\n### Deployment Integrations\n\n| Platform | Example |\n|----------|---------|\n| [AWS Lambda](https:\u002F\u002Faws.amazon.com\u002Flambda\u002F) | [`aws_lambda\u002F`](examples\u002Fintegrations\u002Faws_lambda\u002F) — One-shot scrapes in Lambda (container image) |\n\n## Platforms\n\n| Platform | Chromium | Patches | Status |\n|---|---|---|---|\n| Linux x86_64 | 146 | 57 | ✅ Latest |\n| Linux arm64 (RPi, Graviton) | 146 | 57 | ✅ Latest |\n| macOS arm64 (Apple Silicon) | 145 | 26 | ✅ |\n| macOS x86_64 (Intel) | 145 | 26 | ✅ |\n| Windows x86_64 | 146 | 57 | ✅ Latest |\n\nThe wrapper auto-downloads the correct binary for your platform.\n\n**macOS first launch:** The binary is ad-hoc signed. On first run, macOS Gatekeeper will block it. Right-click the app → **Open** → click **Open** in the dialog. This is only needed once.\n\n## Docker\n\nPre-built image on Docker Hub — no install, no setup.\n\n### Quick test\n\n```bash\ndocker run --rm cloakhq\u002Fcloakbrowser cloaktest\n```\n\n### Run a script\n\n```bash\n# Inline script\ndocker run --rm cloakhq\u002Fcloakbrowser python -c \"\nfrom cloakbrowser import launch\nbrowser = launch()\npage = browser.new_page()\npage.goto('https:\u002F\u002Fexample.com')\nprint(page.title())\nbrowser.close()\n\"\n\n# Mount your own script\ndocker run --rm -v .\u002Fmy_script.py:\u002Fapp\u002Fmy_script.py cloakhq\u002Fcloakbrowser python my_script.py\n\n# With a proxy\ndocker run --rm cloakhq\u002Fcloakbrowser python -c \"\nfrom cloakbrowser import launch\nbrowser = launch(proxy='http:\u002F\u002Fuser:pass@proxy:8080')\npage = browser.new_page()\npage.goto('https:\u002F\u002Fexample.com')\nprint(page.title())\nbrowser.close()\n\"\n```\n\n### CDP server mode\n\nStart a persistent stealth browser and connect to it remotely via Chrome DevTools Protocol:\n\n```bash\ndocker run -d --name cloak -p 127.0.0.1:9222:9222 cloakhq\u002Fcloakbrowser cloakserve\n```\n\nThen connect from your host machine:\n\n```python\nfrom playwright.sync_api import sync_playwright\n\npw = sync_playwright().start()\nbrowser = pw.chromium.connect_over_cdp(\"http:\u002F\u002Flocalhost:9222\")\npage = browser.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")\nprint(page.title())\nbrowser.close()\n```\n\nPass extra flags to the browser:\n\n```bash\n# With proxy\ndocker run -d --name cloak -p 127.0.0.1:9222:9222 cloakhq\u002Fcloakbrowser \\\n  cloakserve --proxy-server=http:\u002F\u002Fproxy:8080\n\n# Headed mode (renders to Xvfb inside container)\ndocker run -d --name cloak -p 127.0.0.1:9222:9222 cloakhq\u002Fcloakbrowser \\\n  cloakserve --headless=false\n```\n\nStop the server:\n\n```bash\ndocker stop cloak && docker rm cloak\n```\n\n> **Security:** CDP gives full control over the browser (execute JS, read pages, access files).\n> The examples bind to `127.0.0.1` so only your machine can connect. Never expose port 9222\n> to the public internet without additional authentication.\n\n### Docker Compose\n\n```yaml\nservices:\n  cloakbrowser:\n    image: cloakhq\u002Fcloakbrowser\n    command: cloakserve\n    restart: unless-stopped\n    ports:\n      - \"127.0.0.1:9222:9222\"\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http:\u002F\u002Flocalhost:9222\u002Fjson\u002Fversion\"]\n      interval: 30s\n      timeout: 5s\n      retries: 3\n      start_period: 10s\n```\n\n**Per-connection fingerprint seeds** — run multiple browser identities from a single container. Each unique seed spawns a separate Chrome process with its own fingerprint:\n\n```python\n# Each seed gets unique canvas noise, client rects, and other browser signals\nb1 = pw.chromium.connect_over_cdp(\"http:\u002F\u002Flocalhost:9222?fingerprint=11111\")\nb2 = pw.chromium.connect_over_cdp(\"http:\u002F\u002Flocalhost:9222?fingerprint=22222\")\n\n# Full identity control via query params\nb3 = pw.chromium.connect_over_cdp(\n    \"http:\u002F\u002Flocalhost:9222?fingerprint=33333\"\n    \"&timezone=Asia\u002FTokyo&locale=ja-JP&platform=macos\"\n    \"&hardware-concurrency=4&device-memory=8\"\n)\n\n# Auto-detect timezone\u002Flocale from proxy exit IP\nb4 = pw.chromium.connect_over_cdp(\n    \"http:\u002F\u002Flocalhost:9222?fingerprint=44444\"\n    \"&proxy=http:\u002F\u002Fproxy:8080&geoip=true\"\n)\n```\n\nSupported query params: `fingerprint`, `timezone`, `locale`, `platform`, `platform-version`, `brand`, `brand-version`, `gpu-vendor`, `gpu-renderer`, `hardware-concurrency`, `device-memory`, `screen-width`, `screen-height`, `proxy`, `geoip`. Same seed reuses the same process (first connection's params win). No seed = shared default process (backward compatible). Check active processes at `GET \u002F` (returns JSON with PIDs, ports, and connection counts).\n\n**Persistent profiles** — mount a volume to keep cookies and sessions across container restarts:\n\n```bash\ndocker run --rm -v .\u002Fmy-profile:\u002Fprofile cloakhq\u002Fcloakbrowser python -c \"\nfrom cloakbrowser import launch_persistent_context\nctx = launch_persistent_context('\u002Fprofile')\npage = ctx.new_page()\npage.goto('https:\u002F\u002Fexample.com')\nctx.close()\n\"\n```\n\nRun again with the same volume — cookies, localStorage, and cache are restored automatically.\n\n**Resource usage:** ~190MB RAM idle, ~280MB with 3 tabs. ~30MB per additional tab.\n\n### Extend with your own image\n\n```dockerfile\nFROM cloakhq\u002Fcloakbrowser\nCOPY your_script.py \u002Fapp\u002F\nCMD [\"python\", \"your_script.py\"]\n```\n\n**Building your own image from pip** — use `python -m cloakbrowser install` to download the binary during build with visible progress:\n\n```dockerfile\nFROM python:3.12-slim\nRUN pip install cloakbrowser && python -m cloakbrowser install\nCOPY your_script.py \u002Fapp\u002F\nCMD [\"python\", \"\u002Fapp\u002Fyour_script.py\"]\n```\n\n**Building from source** — a [`Dockerfile`](Dockerfile) is also included if you prefer to build your own image:\n\n```bash\ndocker build -t cloakbrowser .\n```\n\nCloakBrowser works identically local, in Docker, and on VPS. No environment-specific config needed.\n\n**Note:** If you run CloakBrowser inside a web server with uvloop (e.g., `uvicorn[standard]`), use `--loop asyncio` to avoid subprocess pipe hangs.\n\n## Troubleshooting\n\n---\n\n### Still getting blocked on aggressive sites (DataDome, Turnstile)?\n\nSome sites detect headless mode even with our C++ patches. Run in **headed mode** with a virtual display:\n\n```bash\n# Install Xvfb (virtual framebuffer)\nsudo apt install xvfb\n\n# Start virtual display\nXvfb :99 -screen 0 1920x1080x24 &\nexport DISPLAY=:99\n```\n\n```python\nfrom cloakbrowser import launch\n\n# Headed mode + residential proxy for maximum stealth\nbrowser = launch(headless=False, proxy=\"http:\u002F\u002Fyour-residential-proxy:port\")\npage = browser.new_page()\npage.goto(\"https:\u002F\u002Fheavily-protected-site.com\")  # passes DataDome, etc.\nbrowser.close()\n```\n\nThis runs a real headed browser rendered on a virtual display — no physical monitor needed. Combine with the recommended config below for maximum stealth.\n\n---\n\n### Recommended config for anti-bot sites\n\nMost blocks come from missing one of these three things, not from browser fingerprint detection:\n\n```python\nbrowser = launch(\n    proxy=\"http:\u002F\u002Fyour-residential-proxy:port\",  # residential IP — datacenter IPs get blocked by reputation alone\n    geoip=True,      # matches timezone + locale to proxy exit IP (without this: UTC + en-US = bot signal)\n    headless=False,   # headed mode — some sites detect headless even with C++ patches\n    humanize=True,    # human-like mouse, keyboard, scroll behavior\n)\n```\n\n```javascript\nconst browser = await launch({\n    proxy: 'http:\u002F\u002Fyour-residential-proxy:port',\n    geoip: true,\n    headless: false,\n    humanize: true,\n});\n```\n\nIf your proxy supports SOCKS5, use it for better compatibility — SOCKS5 tunnels raw TCP, avoiding HTTP CONNECT issues that some proxies have with HTTP\u002F2:\n\n```python\nbrowser = launch(proxy=\"socks5:\u002F\u002Fuser:pass@proxy:1080\", geoip=True, headless=False, humanize=True)\n```\n\nIf you're still blocked after this, check the font setup below.\n\n---\n\n### Blocked on Kasada \u002F Akamai sites despite correct config?\n\nOn minimal Linux environments, missing font packages cause canvas emoji rendering to produce hashes that anti-bot systems don't recognize. This is the most common cause of blocks on aggressive sites after proxy, geoip, and headed mode are already set up correctly.\n\nInstall the font packages listed in [Font Setup on Linux](#font-setup-on-linux) above.\n\n---\n\n### Sites challenge fresh sessions but work after first visit\n\nSome sites challenge first-time visitors with no cookies over HTTP\u002F2. This affects all Chromium browsers, not just CloakBrowser. Use a persistent profile to warm up cookies once, then reuse across sessions:\n\n```python\nfrom cloakbrowser import launch_persistent_context\n\n# First run: warm up with --disable-http2\nctx = launch_persistent_context(\".\u002Fprofile\", args=[\"--disable-http2\"])\npage = ctx.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")  # warms up cookies\nctx.close()\n\n# Future runs — no --disable-http2 needed\nctx = launch_persistent_context(\".\u002Fprofile\")\npage = ctx.new_page()\npage.goto(\"https:\u002F\u002Fexample.com\")  # passes with saved cookies\n```\n\n```javascript\nimport { launchPersistentContext } from 'cloakbrowser';\n\n\u002F\u002F First run: warm up with --disable-http2\nlet ctx = await launchPersistentContext({ userDataDir: '.\u002Fprofile', args: ['--disable-http2'] });\nlet page = await ctx.newPage();\nawait page.goto('https:\u002F\u002Fexample.com');\nawait ctx.close();\n\n\u002F\u002F Future runs — no --disable-http2 needed\nctx = await launchPersistentContext({ userDataDir: '.\u002Fprofile' });\n```\n\nFor stateless\u002Fephemeral use cases, `launch(args=[\"--disable-http2\"])` forces HTTP\u002F1.1 which bypasses the check. Only use this flag for sites that require it — most work fine with HTTP\u002F2. If your proxy supports SOCKS5, use `proxy=\"socks5:\u002F\u002Fuser:pass@host:port\"` instead — SOCKS5 bypasses HTTP CONNECT entirely.\n\n---\n\n### Something not working? Make sure you're on the latest version\n\nOlder versions may use outdated stealth args or download an older binary:\n```bash\npip install -U cloakbrowser    # Python\nnpm install cloakbrowser@latest # JavaScript\ndocker pull cloakhq\u002Fcloakbrowser:latest  # Docker\n```\n\n---\n\n### Binary download fails \u002F timeout\n\nSet a custom download URL or use a local binary:\n```bash\nexport CLOAKBROWSER_BINARY_PATH=\u002Fpath\u002Fto\u002Fyour\u002Fchrome\n```\n\n---\n\n### New update broke something? Roll back to the previous version\n\nInstall a specific wrapper version to downgrade both the wrapper and the binary it downloads:\n```bash\npip install cloakbrowser==0.3.21              # Python\nnpm install cloakbrowser@0.3.21               # JavaScript\ndocker pull cloakhq\u002Fcloakbrowser:0.3.21       # Docker\n```\nEach wrapper version pins its own binary version, so downgrading the wrapper automatically gets you the matching binary on next launch.\n\n---\n\n### macOS: \"App is damaged\" or Gatekeeper blocks launch\n\nThe binary is ad-hoc signed. macOS quarantines downloaded files. Run once to clear it:\n```bash\nxattr -cr ~\u002F.cloakbrowser\u002Fchromium-*\u002FChromium.app\n```\n\n---\n\n### \"playwright install\" vs CloakBrowser binary\n\nYou do NOT need `playwright install chromium`. CloakBrowser downloads its own binary. You only need Playwright's system deps:\n```bash\nplaywright install-deps chromium\n```\n\n---\n\n### macOS: Blocked on some sites that pass on Linux\n\nThe macOS fingerprint profile has known inconsistencies that aggressive bot detection catches. If a site blocks you on macOS but works on Linux, switch to a Windows fingerprint profile by passing `stealth_args=False` and manually setting `--fingerprint-platform=windows` with matching GPU flags (see [Fingerprint Management](#fingerprint-management) for the full flag list).\n\n---\n\n### Site detects incognito \u002F private browsing mode\n\nBy default, `launch()` opens an incognito context. Some sites penalize this. Use `launch_persistent_context()` to get a real profile with cookie persistence:\n\n```python\nfrom cloakbrowser import launch_persistent_context\n\nctx = launch_persistent_context(\".\u002Fmy-profile\", headless=False)\n```\n\nIf the site still flags incognito, raise the storage quota to appear as a regular browsing session. See the [storage quota tradeoff](#launch_persistent_context) for details on how this affects different detection services.\n\n---\n\n### reCAPTCHA v3 scores are low (0.1–0.3)\n\nAvoid `page.wait_for_timeout()` — it sends CDP protocol commands that reCAPTCHA detects. Use native sleep instead:\n\n```python\n# Bad — sends CDP commands, reCAPTCHA detects this\npage.wait_for_timeout(3000)\n\n# Good — invisible to the browser\nimport time\ntime.sleep(3)\n```\n\n```javascript\n\u002F\u002F Bad — sends CDP commands\nawait page.waitForTimeout(3000);\n\n\u002F\u002F Good — invisible to the browser\nawait new Promise(r => setTimeout(r, 3000));\n```\n\nOther tips for maximizing reCAPTCHA scores:\n- **Try the Patchright backend** — suppresses additional CDP automation signals at the Playwright protocol layer. Install with `pip install cloakbrowser[patchright]`, then use `launch(backend=\"patchright\")` or set `CLOAKBROWSER_BACKEND=patchright` globally. Note: Patchright breaks proxy auth and `add_init_script` — only use it if you're still seeing low scores after trying the steps above\n- **Use Playwright, not Puppeteer** — Puppeteer sends more CDP protocol traffic that reCAPTCHA detects ([details](#puppeteer))\n- **Use residential proxies** — datacenter IPs are flagged by IP reputation, not browser fingerprint\n- **Spend 15+ seconds on the page** before triggering reCAPTCHA — short visits score lower\n- **Space out requests** — back-to-back `grecaptcha.execute()` calls from the same session get penalized. Wait 30+ seconds between pages with reCAPTCHA\n- **Use a fixed fingerprint seed** for consistent device identity across sessions (see [Fingerprint Management](#fingerprint-management))\n- **Use `page.type()` instead of `page.fill()`** for form filling — `fill()` sets values directly without keyboard events, which reCAPTCHA's behavioral analysis flags. `type()` with a delay simulates real keystrokes:\n  ```python\n  page.type(\"#email\", \"user@example.com\", delay=50)\n  ```\n- **Minimize `page.evaluate()` calls** before the reCAPTCHA check fires — each one sends CDP traffic\n\n## FAQ\n\n**Q: Is this legal?**\nA: CloakBrowser is a browser built on open-source Chromium. We do not condone illegal use. Automating systems without authorization, credential stuffing, and account creation abuse are expressly prohibited. See [BINARY-LICENSE.md](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fblob\u002Fmain\u002FBINARY-LICENSE.md) for full terms.\n\n**Q: How is this different from Camoufox?**\nA: Camoufox patches Firefox. We patch Chromium. Chromium means native Playwright support, larger ecosystem, and TLS fingerprints that match real Chrome. Camoufox returned in early 2026 but is in unstable beta — CloakBrowser is production-ready.\n\n**Q: Will detection sites eventually catch this?**\nA: Possibly. Bot detection is an arms race. Source-level patches are harder to detect than config-level patches, but not impossible. We actively monitor and update when detection evolves.\n\n**Q: Can I use my own proxy?**\nA: Yes. Pass `proxy=\"http:\u002F\u002Fuser:pass@host:port\"` or `proxy=\"socks5:\u002F\u002Fuser:pass@host:port\"` to `launch()`. Both HTTP and SOCKS5 proxies are supported natively.\n\n## Roadmap\n\n| Feature | Status |\n|---------|--------|\n| Linux x64 — Chromium 146 (57 patches) | ✅ Released |\n| macOS arm64\u002Fx64 — Chromium 145 (26 patches) | ✅ Released |\n| Windows x64 — Chromium 146 (57 patches) | ✅ Released |\n| JavaScript\u002FPuppeteer + Playwright support | ✅ Released |\n| Fingerprint rotation per session | ✅ Released |\n| Built-in proxy rotation | 📋 Planned |\n\n## Links\n\n- 📋 **Changelog** — [CHANGELOG.md](CHANGELOG.md)\n- 🌐 **Website** — [cloakbrowser.dev](https:\u002F\u002Fcloakbrowser.dev)\n- 🐛 **Bug reports & feature requests** — [GitHub Issues](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fissues)\n- 📦 **PyPI** — [pypi.org\u002Fproject\u002Fcloakbrowser](https:\u002F\u002Fpypi.org\u002Fproject\u002Fcloakbrowser\u002F)\n- 📦 **npm** — [npmjs.com\u002Fpackage\u002Fcloakbrowser](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcloakbrowser)\n- ☕ **Support** — [ko-fi.com\u002Fcloakhq](https:\u002F\u002Fko-fi.com\u002Fcloakhq)\n- 📧 **Contact** — cloakhq@pm.me\n\n## Security\n\nAll releases are signed for supply chain verification.\n\n```bash\n# Verify GPG signature (binary release tag)\ngpg --keyserver keyserver.ubuntu.com --recv-keys C60C0DDC9D0DE2DD\ngit verify-tag chromium-v146.0.7680.177.3\n\n# Verify GitHub binary attestation (Sigstore)\ngh attestation verify cloakbrowser-linux-x64.tar.gz --repo CloakHQ\u002Fcloakbrowser\n\n# Verify Docker image signature (Cosign\u002FSigstore)\ncosign verify \\\n  --certificate-identity-regexp \"https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002F\" \\\n  --certificate-oidc-issuer \"https:\u002F\u002Ftoken.actions.githubusercontent.com\" \\\n  cloakhq\u002Fcloakbrowser:latest\n```\n\n## License\n\n- **Wrapper code** (this repository) — MIT. See [LICENSE](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fblob\u002Fmain\u002FLICENSE).\n- **CloakBrowser binary** (compiled Chromium) — free to use, no redistribution. See [BINARY-LICENSE.md](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fblob\u002Fmain\u002FBINARY-LICENSE.md).\n\n## Contributing\n\nIssues and PRs welcome. If something isn't working, [open an issue](https:\u002F\u002Fgithub.com\u002FCloakHQ\u002FCloakBrowser\u002Fissues) — we respond fast.\n\n## Contributors\n\n- [@evelaa123](https:\u002F\u002Fgithub.com\u002Fevelaa123) — humanize behavior, persistent contexts, Windows fix\n- [@yahooguntu](https:\u002F\u002Fgithub.com\u002Fyahooguntu) — persistent contexts\n- [@kitiho](https:\u002F\u002Fgithub.com\u002Fkitiho) — null viewport fix\n- [@eofreternal](https:\u002F\u002Fgithub.com\u002Feofreternal) — humanConfig type fix\n- [@AlexTech314](https:\u002F\u002Fgithub.com\u002FAlexTech314) — AWS Lambda integration\n","CloakBrowser 是一个经过深度修改的 Chromium 浏览器，能够通过所有机器人检测测试。该项目的核心功能包括在 C++ 源代码级别对浏览器指纹进行了49项修补，使其在自动化操作时表现得像普通用户一样，从而绕过如 reCAPTCHA、Cloudflare Turnstile 等多种反爬虫机制。此外，CloakBrowser 提供了与 Playwright 和 Puppeteer 兼容的 API，使得开发者可以轻松地将其集成到现有的 Python 或 JavaScript 项目中以进行网页抓取或自动化测试。此工具特别适合需要在高度监控环境下执行自动化任务的场景，例如数据采集、网站监测等。",2,"2026-06-11 02:30:53","trending"]