RepoDepot
Agent SDK App

CloakBrowser

by CloakHQ
Stealth Chromium browser for AI agents — bypasses bot detection with source-level fingerprint patches

CloakBrowser is a stealth Chromium browser for AI agents and web scrapers, designed to bypass advanced bot detection systems like Cloudflare and reCAPTCHA. It achieves this by modifying Chromium's C++ source code, patching 49+ fingerprint vectors at the binary level, unlike common JavaScript injection methods. The tool offers a drop-in replacement for Playwright and Puppeteer, maintaining the same API for seamless integration into existing automation workflows.

View on GitHub ↗
Key features
  • 49+ source-level C++ patches for deep fingerprint modification
  • Human-like mouse, keyboard, and scroll patterns with `humanize=True`
  • Achieves 0.9 reCAPTCHA v3 score and passes Cloudflare Turnstile
  • Drop-in API compatibility with Playwright and Puppeteer
  • Auto-updating Chromium binary for the latest stealth builds
Languages
Python53%TypeScript43%JavaScript3%Nix1%Dockerfile0%
Top contributors
+10k stars since added
Started at 13k ★ when added to RepoDepot.
Topics
ai-agentsanti-detectantidetect-browserbot-detectionbrowser-automationcaptcha-bypasschromiumcloudflarecloudflare-bypassfingerprintheadless-browserplaywrightpuppeteerpythonrecaptchaseleniumstealth-browserundetectedweb-scrapingwebscraping

CloakBrowser

PyPI npm License Last Commit
Stars PyPI Downloads npm Downloads Docker Pulls

Support on Ko-fi


Stealth Chromium that passes every bot detection test.

Not 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 is a normal browser.

Cloudflare Turnstile — 3 Tests Passing
Cloudflare Turnstile — 3 live tests passing (headed mode, macOS)


Drop-in Playwright/Puppeteer replacement for Python and JavaScript.
Same API, same code — just swap the import. 3 lines of code, 30 seconds to unblock.

  • 49 source-level C++ patches — canvas, WebGL, audio, fonts, GPU, screen, WebRTC, network timing, automation signals, CDP input behavior
  • humanize=True — human-like mouse curves, keyboard timing, and scroll patterns. One flag, behavioral detection passes
  • 0.9 reCAPTCHA v3 score — human-level, server-verified
  • Passes Cloudflare Turnstile, FingerprintJS, BrowserScan — tested against 30+ detection sites
  • Auto-updating binary — background update checks, always on the latest stealth build
  • pip install cloakbrowser or npm install cloakbrowser — binary auto-downloads, zero config
  • Free and open source — no subscriptions, no usage limits

Try it now — no install needed:

docker run --rm cloakhq/cloakbrowser cloaktest

Python:

from cloakbrowser import launch

browser = launch()
page = browser.new_page()
page.goto("https://protected-site.com")  # no more blocks
browser.close()

JavaScript (Playwright):

import { launch } from 'cloakbrowser';

const browser = await launch();
const page = await browser.newPage();
await page.goto('https://protected-site.com');
await browser.close();

Also works with Puppeteer: import { launch } from 'cloakbrowser/puppeteer' (details)

Install

Python:

pip install cloakbrowser

JavaScript / Node.js:

# With Playwright
npm install cloakbrowser playwright-core

# With Puppeteer
npm install cloakbrowser puppeteer-core

On first run, the stealth Chromium binary is automatically downloaded (~200MB, cached locally).

Optional: Auto-detect timezone/locale from proxy IP:

pip install cloakbrowser[geoip]

Migrating from Playwright? One-line change:

- from playwright.sync_api import sync_playwright
- pw = sync_playwright().start()
- browser = pw.chromium.launch()
+ from cloakbrowser import launch
+ browser = launch()

page = browser.new_page()
page.goto("https://example.com")
# ... rest of your code works unchanged

Star to show support — Watch releases to get notified when new builds drop.

Browser Profile Manager

Self-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.

docker run -p 8080:8080 -v cloakprofiles:/data cloakhq/cloakbrowser-manager

Open http://localhost:8080. Create a profile. Click Launch. Done.

CloakBrowser Manager — free, open source (MIT)


Latest: v0.3.28 (Chromium 146.0.7680.177.4)

  • 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.
  • JS contextOptions escape hatch — forward arbitrary options (including storageState) to Playwright's newContext() from launchContext() / launchPersistentContext().
  • Native SOCKS5 proxyproxy="socks5://user:pass@host:port" works directly in all launch functions, Python + JS. QUIC/HTTP3 tunnels through SOCKS5 via UDP ASSOCIATE.
  • Chromium 146 upgrade — rebased all patches from 145.0.7632.x to 146.0.7680.177
  • 57 fingerprint patches — additional detection-vector coverage (WebAuthn, AAC audio, window position) and WebGL/canvas consistency fixes
  • 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)
  • Proxy signal removal — DNS/connect/SSL timing zeroed, proxy cache headers stripped, Proxy-Connection header leak removed
  • cloakserve CDP multiplexer — rewritten as a multi-connection CDP proxy with per-connection fingerprint seeds
  • Humanize CDP isolation — keyboard events now use isolated worlds and trusted dispatch for better behavioral stealth
  • 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
  • Stealthy with zero flags — binary auto-generates a random fingerprint seed at startup. No configuration required
  • Timezone & locale from proxy IPlaunch(proxy="...", geoip=True) auto-detects timezone and locale
  • Persistent profileslaunch_persistent_context() keeps cookies and localStorage across sessions, bypasses incognito detection

See the full CHANGELOG.md for details.

Why CloakBrowser?

  • Config-level patches breakplaywright-stealth, undetected-chromedriver, and puppeteer-extra inject JavaScript or tweak flags. Every Chrome update breaks them. Antibot systems detect the patches themselves.
  • 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.
  • 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.
  • Same behavior everywhere — works identically local, in Docker, and on VPS. No environment-specific patches or config needed.
  • Works with AI agents and automation frameworks — drop-in stealth for browser-use, Crawl4AI, Scrapling, Stagehand, LangChain, Selenium, and more. See integrations.

CloakBrowser 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.

Test Results

All tests verified against live detection services. Last tested: Apr 2026 (Chromium 146).

Detection Service Stock Playwright CloakBrowser Notes
reCAPTCHA v3 0.1 (bot) 0.9 (human) Server-side verified
Cloudflare Turnstile (non-interactive) FAIL PASS Auto-resolve
Cloudflare Turnstile (managed) FAIL PASS Single click
ShieldSquare BLOCKED PASS Production site
FingerprintJS bot detection DETECTED PASS demo.fingerprint.com
BrowserScan bot detection DETECTED NORMAL (4/4) browserscan.net
bot.incolumitas.com 13 fails 1 fail WEBDRIVER spec only
deviceandbrowserinfo.com 6 true flags 0 true flags isBot: false
navigator.webdriver true false Source-level patch
navigator.plugins.length 0 5 Real plugin list
window.chrome undefined object Present like real Chrome
UA string HeadlessChrome Chrome/146.0.0.0 No headless leak
CDP detection Detected Not detected isAutomatedWithCDP: false
TLS fingerprint Mismatch Identical to Chrome ja3n/ja4/akamai match
Tested against 30+ detection sites

Proof

reCAPTCHA v3 — Score 0.9
reCAPTCHA v3 score 0.9 — server-side verified (human-level)

Cloudflare Turnstile — Success
Cloudflare Turnstile non-interactive challenge — auto-resolved

BrowserScan — Normal
BrowserScan bot detection — NORMAL (4/4 checks passed)

FingerprintJS — Passed
FingerprintJS web-scraping demo — data served, not blocked

deviceandbrowserinfo.com — You are human!
deviceandbrowserinfo.com behavioral bot detection — "You are human!" with humanize=True (24/24 signals passed)

Comparison

Feature Playwright playwright-stealth undetected-chromedriver Camoufox CloakBrowser
reCAPTCHA v3 score 0.1 0.3-0.5 0.3-0.7 0.7-0.9 0.9
Cloudflare Turnstile Fail Sometimes Sometimes Pass Pass
Patch level None JS injection Config patches C++ (Firefox) C++ (Chromium)
Survives Chrome updates N/A Breaks often Breaks often Yes Yes
Maintained Yes Stale Stale Unstable Active
Browser engine Chromium Chromium Chrome Firefox Chromium
Playwright API Native Native No (Selenium) No Native

How It Works

CloakBrowser is a thin wrapper (Python + JavaScript) around a custom-built Chromium binary:

  1. You installpip install cloakbrowser or npm install cloakbrowser
  2. First launch → binary auto-downloads for your platform (Chromium 146)
  3. Every launch → Playwright or Puppeteer starts with our binary + stealth args
  4. You write code → standard Playwright/Puppeteer API, nothing new to learn

The 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.

These are compiled into the Chromium binary — not injected via JavaScript, not set via flags.

Binary downloads are verified with SHA-256 checksums to ensure integrity.

API

launch()

from cloakbrowser import launch

# Basic — headless, default stealth config
browser = launch()

# Headed mode (see the browser window)
browser = launch(headless=False)

# With proxy (HTTP or SOCKS5)
browser = launch(proxy="http://user:pass@proxy:8080")
browser = launch(proxy="socks5://user:pass@proxy:1080")

# With proxy dict (bypass, separate auth fields)
browser = launch(proxy={"server": "http://proxy:8080", "bypass": ".google.com", "username": "user", "password": "pass"})

# With extra Chrome args
browser = launch(args=["--disable-gpu"])

# With timezone and locale (sets binary flags — no detectable CDP emulation)
browser = launch(timezone="America/New_York", locale="en-US")

# Auto-detect timezone/locale from proxy IP (requires: pip install cloakbrowser[geoip])
# Also auto-injects --fingerprint-webrtc-ip to prevent WebRTC IP leaks (no extra cost)
# Note: makes HTTP calls through your proxy to resolve exit IP (ipify.org, checkip.amazonaws.com)
browser = launch(proxy="http://proxy:8080", geoip=True)

# Explicit timezone/locale always win over auto-detection
browser = launch(proxy="http://proxy:8080", geoip=True, timezone="Europe/London")

# WebRTC IP spoofing only (no geoip dep needed — resolves exit IP via HTTP call through proxy)
browser = launch(proxy="http://proxy:8080", args=["--fingerprint-webrtc-ip=auto"])

# Explicit WebRTC IP (no network call)
browser = launch(proxy="http://proxy:8080", args=["--fingerprint-webrtc-ip=1.2.3.4"])

# Human-like mouse, keyboard, and scroll behavior
browser = launch(humanize=True)

# With slower, more deliberate movements
browser = launch(humanize=True, human_preset="careful")

# Without default stealth args (bring your own fingerprint flags)
browser = launch(stealth_args=False, args=["--fingerprint=12345"])

Returns a standard Playwright Browser object. All Playwright methods work: new_page(), new_context(), close(), etc.

launch_async()

import asyncio
from cloakbrowser import launch_async

async def main():
    browser = await launch_async()
    page = await browser.new_page()
    await page.goto("https://example.com")
    print(await page.title())
    await browser.close()

asyncio.run(main())

launch_context()

Convenience function that creates browser + context in one call with user agent, viewport, locale, and timezone:

from cloakbrowser import launch_context

context = launch_context(
    user_agent="Custom UA",
    viewport={"width": 1920, "height": 1080},
    locale="en-US",
    timezone="America/New_York",
)
page = context.new_page()
page.goto("https://protected-site.com")
context.close()

Extra 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:

from cloakbrowser import launch_context

# Restore a saved session (cookies, localStorage) from a JSON file
context = launch_context(storage_state="state.json")
page = context.new_page()
page.goto("https://example.com")
# Save state back for next run
context.storage_state(path="state.json")
context.close()

launch_context_async()

Async counterpart to launch_context(). Same signature and kwargs forwarding:

import asyncio
from cloakbrowser import launch_context_async

async def main():
    ctx = await launch_context_async(storage_state="state.json")
    page = await ctx.new_page()
    await page.goto("https://example.com")
    await ctx.storage_state(path="state.json")
    await ctx.close()

asyncio.run(main())

launch_persistent_context()

Same as launch_context(), but with a persistent user profile. Cookies, localStorage, and cache persist across sessions.

Use this when you need to:

  • Stay logged in across runs (cookies/sessions survive restarts)
  • Bypass incognito detection (some sites flag empty, ephemeral profiles)
  • Load Chrome extensions (extensions only work from a real user data dir)
  • Build natural browsing history (cached fonts, service workers, IndexedDB accumulate over time, making the profile look more realistic)
from cloakbrowser import launch_persistent_context

# First run — creates the profile
ctx = launch_persistent_context("./my-profile", headless=False)
page = ctx.new_page()
page.goto("https://protected-site.com")
ctx.close()  # profile saved

# Next run — cookies, localStorage restored automatically
ctx = launch_persistent_context("./my-profile", headless=False)

# Load Chrome extensions
ctx = launch_persistent_context(
    "./my-profile",
    headless=False,
    extension_paths=["./my-extension"],
)

Supports all the same options as launch_context(): proxy, user_agent, viewport, locale, timezone, color_scheme, geoip, extension_paths.

Async version: launch_persistent_context_async().

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:

ctx = launch_persistent_context("./my-profile", args=["--fingerprint-storage-quota=5000"])
Quota setting FingerprintJS BrowserScan notPrivate
Default (auto, ~500MB) PASS -10 (flagged as incognito)
--fingerprint-storage-quota=5000 May trigger detection PASS (appears non-incognito)

CLI

Pre-download the binary or check installation status from the command line:

python -m cloakbrowser install      # Download binary with progress output
python -m cloakbrowser info         # Show version, path, platform
python -m cloakbrowser update       # Check for and download newer binary
python -m cloakbrowser clear-cache  # Remove cached binaries

Utility Functions

from cloakbrowser import binary_info, clear_cache, ensure_binary

# Check binary installation status
print(binary_info())
# {'version': '146.0.7680.177.3', 'platform': 'linux-x64', 'installed': True, ...}

# Force re-download
clear_cache()

# Pre-download binary (e.g., during Docker build)
ensure_binary()

JavaScript / Node.js API

CloakBrowser ships a TypeScript package with full type definitions. Choose Playwright or Puppeteer — same stealth binary underneath.

Playwright (default)

import { launch, launchContext, launchPersistentContext } from 'cloakbrowser';

// Basic
const browser = await launch();

// With options
const browser = await launch({
  headless: false,
  proxy: 'http://user:pass@proxy:8080',
  args: ['--fingerprint=12345'],
  timezone: 'America/New_York',
  locale: 'en-US',
  humanize: true,
});

// Convenience: browser + context in one call
const context = await launchContext({
  userAgent: 'Custom UA',
  viewport: { width: 1920, height: 1080 },
  locale: 'en-US',
  timezone: 'America/New_York',
});
const page = await context.newPage();

// Persistent profile — cookies/localStorage survive restarts, avoids incognito detection
const ctx = await launchPersistentContext({
  userDataDir: './chrome-profile',
  headless: false,
  proxy: 'http://user:pass@proxy:8080',
});

Note: Each example above is standalone — not meant to run as one block.

All Python options work in JS: stealthArgs: false to disable defaults, geoip: true to auto-detect timezone/locale from proxy IP.

Puppeteer

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.

import { launch } from 'cloakbrowser/puppeteer';

const browser = await launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();

Utility Functions (JS)

import { ensureBinary, clearCache, binaryInfo } from 'cloakbrowser';

// Pre-download binary (e.g., during Docker build)
await ensureBinary();

// Check installation status
console.log(binaryInfo());

// Force re-download
clearCache();

Human Behavior

Pass 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.

browser = launch(humanize=True)
page = browser.new_page()
page.goto("https://example.com")
page.locator("#email").fill("user@example.com")  # per-character timing, thinking pauses
page.locator("button[type=submit]").click()       # Bézier curve, realistic aim point
// Playwright
import { launch } from 'cloakbrowser';
const browser = await launch({ humanize: true });
// Puppeteer
import { launch } from 'cloakbrowser/puppeteer';
const browser = await launch({ humanize: true });

What changes:

Interaction Default With humanize=True
Mouse movement Instant teleport Bézier curve with easing and slight overshoot
Clicks Instant Realistic aim point + hold duration
Keyboard Instant fill Per-character timing, thinking pauses, occasional typos with self-correction
Scroll Jump Accelerate → cruise → decelerate micro-steps
fill() Instant value set Clears existing content, types character by character

Presetsdefault (normal speed) or careful (slower, more deliberate, idle micro-movements between actions):

browser = launch(humanize=True, human_preset="careful")
const browser = await launch({ humanize: true, humanPreset: 'careful' });

Custom config — override any parameter:

browser = launch(humanize=True, human_config={
    "mistype_chance": 0.05,              # 5% typo rate with self-correction
    "typing_delay": 100,                 # slower typing (ms per character)
    "idle_between_actions": True,        # micro-movements between clicks
    "idle_between_duration": [0.3, 0.8], # idle duration range (seconds)
})
const browser = await launch({
    humanize: true,
    humanConfig: {
        mistype_chance: 0.05,
        typing_delay: 100,
        idle_between_actions: true,
        idle_between_duration: [0.3, 0.8],
    }
});

Access the original un-patched Playwright page at page._original if you need raw speed for a specific call.

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.

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.

Contributed by @evelaa123 — full Playwright and Puppeteer API coverage.

Configuration

Env Variable Default Description
CLOAKBROWSER_BINARY_PATH Skip download, use a local Chromium binary
CLOAKBROWSER_CACHE_DIR ~/.cloakbrowser Binary cache directory
CLOAKBROWSER_DOWNLOAD_URL cloakbrowser.dev Custom download URL for binary
CLOAKBROWSER_AUTO_UPDATE true Set to false to disable background update checks
CLOAKBROWSER_SKIP_CHECKSUM false Set to true to skip SHA-256 verification after download
CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS 5 Max seconds for GeoIP resolution before continuing without it

Fingerprint Management

The 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.

How fingerprinting works:

Scenario What happens
No flags Random seed auto-generated at startup. GPU, screen, hardware specs, and all noise patches are spoofed automatically. Fresh identity each launch.
--fingerprint=seed Deterministic identity from the seed. Same seed = same fingerprint across launches. Use this for session persistence (returning visitor).
--fingerprint=seed + explicit flags Explicit flags override individual auto-generated values. The seed fills in everything else.

The 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.

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:

browser = launch(args=["--fingerprint=12345"])
const browser = await launch({ args: ['--fingerprint=12345'] });

Default Fingerprint

Every 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:

Flag Linux/Windows Default macOS Default Controls
--fingerprint Random (10000–99999) Random (10000–99999) Master seed for canvas, WebGL, audio, fonts, client rects
--fingerprint-platform windows macos navigator.platform, User-Agent OS, GPU pool selection

The 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.

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.

Additional Flags

Supported by the binary but not set by default — pass via args to customize:

Flag Controls
--fingerprint-gpu-vendor WebGL UNMASKED_VENDOR_WEBGL (auto-generated from seed + platform)
--fingerprint-gpu-renderer WebGL UNMASKED_RENDERER_WEBGL (auto-generated from seed + platform)
--fingerprint-hardware-concurrency navigator.hardwareConcurrency (auto-generated: 8)
--fingerprint-device-memory navigator.deviceMemory in GB (auto-generated: 8)
--fingerprint-screen-width Screen width (auto-generated: 1920 Win/Linux, 1440 macOS)
--fingerprint-screen-height Screen height (auto-generated: 1080 Win/Linux, 900 macOS)
--fingerprint-brand Browser brand: Chrome, Edge, Opera, Vivaldi
--fingerprint-brand-version Brand version (UA + Client Hints)
--fingerprint-platform-version Client Hints platform version
--fingerprint-location Geolocation coordinates
--fingerprint-timezone Timezone (e.g. America/New_York)
--fingerprint-locale Locale (e.g. en-US)
--fingerprint-storage-quota Override storage quota in MB — affects storage.estimate(), storageBuckets, and legacy webkit APIs. Auto-normalized when --fingerprint is set
--fingerprint-taskbar-height Override taskbar height (binary defaults: Win=48, Mac=95, Linux=0)
--fingerprint-fonts-dir Path to directory containing target-platform fonts (see Font Setup on Linux)
--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
--fingerprint-noise=false Disable noise injection (canvas, WebGL, audio, client rects) while keeping the deterministic fingerprint seed active
--enable-blink-features=FakeShadowRoot Access closed shadow DOM elements

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.

Font Setup on Linux

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:

sudo apt install -y fonts-noto-color-emoji fonts-freefont-ttf fonts-unifont \
    fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf

The Docker image (cloakhq/cloakbrowser) ships with these pre-installed. If you run the binary directly on a Linux server or in a custom Docker image, install them manually.

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

Similar agent sdks

Added to RepoDepot ·