Agent-friendly CLI for CloakBrowser — stealth Chromium that passes every bot detection test. Covers all CloakBrowser features so other AI agents can drive a real browser from any shell.
npm install -g @dreamor/cloakbrowser-cli cloakbrowser playwright-core
cloak doctor # confirm everything is installed
cloak binary install # one-time ~200MB Chromium download
cloak fetch https://example.com --markdown --prettyCloakBrowser ships a Python/JS SDK plus a Python python -m cloakbrowser CLI for binary management and a cloakserve CDP gateway — but no CLI for the browser itself. Agents calling shell commands need a structured surface that covers all of CloakBrowser: launch options, fingerprint flags, humanize behaviors, page operations, content extraction, cookies, storage, network, multi-page sessions, and the CDP server.
@dreamor/cloakbrowser-cli is that surface.
Best for "fetch this URL and give me the markdown / a screenshot".
cloak fetch https://news.ycombinator.com --markdown --pretty
cloak fetch https://target.com --humanize --proxy=http://u:p@host:port --text
cloak scrape https://example.com --selector="h1" --multiBest for "log in, click around, scrape over several pages, take screenshots".
cloak daemon start
SID=$(cloak session new --humanize | jq -r .session_id)
cloak goto $SID https://demo.fingerprint.com
cloak wait $SID --selector="#visitor-id"
cloak text $SID --selector="#visitor-id"
cloak screenshot $SID --path=./fp.png --full-page
cloak session close $SIDThe daemon keeps Browser, Context, and Page instances alive between CLI invocations. Each cloak <verb> is a tiny RPC over a Unix socket at ~/.cloak/daemon.sock.
npm install -g @dreamor/cloakbrowser-cli cloakbrowser playwright-coreRequires Node 18.17+. Peer deps cloakbrowser and playwright-core are installed alongside.
First real browser launch downloads the stealth Chromium binary (~200MB, cached at ~/.cloakbrowser/). Pre-download with cloak binary install.
Default output is single-line JSON on stdout, exit code 0/1. Errors go to stderr as JSON with a stable code. Designed so an agent can:
# 1. Start once per project; survives across many agent turns.
cloak daemon start >/dev/null
# 2. Create a session, save the id.
SID=$(cloak session new --humanize | jq -r .data.session_id)
# 3. Drive it.
cloak goto "$SID" https://target.com
SNAP=$(cloak snapshot "$SID") # element uids, roles, names, bboxes
# agent reasons over $SNAP, picks an element with uid "u7"
cloak click "$SID" '[data-cloak-uid="u7"]'
cloak text "$SID" --selector="#result"
# 4. Or keep state across turns by saving cookies + localStorage.
cloak session save-state "$SID" ./state.json
# later, in a fresh process:
SID=$(cloak session new --storage-state=./state.json | jq -r .data.session_id)The envelope is stable:
Add --pretty for human-readable colored output (auto when stdout is a TTY). Add --quiet to emit only data (without the envelope) on success.
Error code values: BOOT_ERROR, INVALID_ARG, INVALID_JSON, MISSING_DEPENDENCY, DAEMON_NOT_RUNNING, DAEMON_ALREADY_RUNNING, DAEMON_TIMEOUT, SESSION_NOT_FOUND, PAGE_NOT_FOUND, BROWSER_LAUNCH_FAILED, NAVIGATION_FAILED, TIMEOUT, SELECTOR_NOT_FOUND, EVAL_FAILED, NETWORK_ERROR, IO_ERROR, NOT_IMPLEMENTED, UNSUPPORTED_OPERATION, INTERNAL_ERROR.
| Command | What it does |
|---|---|
cloak daemon start [--log <path>] |
Spawn the daemon detached. |
cloak daemon stop |
Stop and free all sessions. |
cloak daemon status |
pid, uptime, session count. |
cloak daemon ping |
Round-trip health check. |
cloak daemon methods |
List all 60+ RPC methods. |
cloak daemon foreground |
Run daemon attached for debugging. |
| Command | What it does |
|---|---|
cloak session new [opts] |
Returns {session_id, page_id}. See Launch options below. |
cloak session list |
All active sessions with metadata. |
cloak session info <id> |
Pages, ttl, launch opts. |
cloak session close <id> |
Close + free resources. |
cloak session save-state <id> <path> |
Dump storageState JSON. |
| Command | What it does |
|---|---|
cloak page new <sid> |
New tab in the session. |
cloak page list <sid> |
List tabs. |
cloak page close <sid> <pid> |
Close one tab. |
cloak page activate <sid> <pid> |
Make tab default for subsequent ops. |
cloak goto <sid> <url> · back · forward · reload · url · title
All accept --page <pid> and --timeout <ms>. goto also takes --wait-until=load|domcontentloaded|networkidle|commit and --referer.
content (HTML) · text (innerText, --selector to scope) · html --selector · attr <sel> <name> · markdown (Readability + Turndown) · screenshot [--path] [--full-page] [--selector] [--format png|jpeg] [--quality] · pdf [--path] [--format A4] [--landscape]
Binary outputs are returned as base64 by default; pass --path=FILE to write to disk (response includes {path, size, sha256}). The global --out <path> flag also works as a fallback for --path.
click · dblclick · fill · type · press · hover · focus · blur · scroll [--to top|bottom|<sel>] [-x] [-y] · select <sid> <sel> <value...> · check · uncheck · upload <sid> <sel> <file...> · drag <sid> <from> <to> · dispatch <sid> <sel> <event_type> [--init <json>]
cloak wait <sid> [--selector] [--text] [--url] [--state visible|hidden|attached|detached] [--load-state load|networkidle] [--timeout] · cloak sleep <sid> <ms> · cloak snapshot <sid> (a11y-style tree with uids) · cloak frames <sid> · cloak a11y <sid> (raw Playwright accessibility tree; returns UNSUPPORTED_OPERATION if unavailable — use snapshot instead)
snapshot is the recommended entry point for agent reasoning: it tags every visible interactive element with data-cloak-uid and returns role, name, attrs, bounding box, and a usable selector for each.
cloak eval <sid> <expression> [--arg <json>] · cloak eval-file <sid> <path> [--arg <json>]
cloak cookies get <sid> [--url] · cloak cookies set <sid> --json <json>|--file <path>|stdin · cloak cookies clear <sid>
cloak storage save <sid> <path> (storageState dump) · cloak storage load (only at session launch — recreate the session with --storage-state)
cloak local-storage get|set|clear · cloak session-storage get|set|clear
cloak request <sid> <url> [--method] [--header "Name: Value"] [--body|--json|--form key=value] [--timeout] — fires through the session's context.request, so cookies/proxy/fingerprint match the browser.
cloak dialog <sid> --action=accept|dismiss [--text] — install a one-shot handler for the next alert/confirm/prompt.
cloak fetch <url> [launch opts] [--wait-until] [--nav-timeout] [--referer] [--text] [--html] [--markdown] [--selector] [--screenshot [path]] [--full-page] [--pdf [path]]
cloak scrape <url> --selector <sel> [--multi] [--attr <name>] [launch opts]
cloak binary install|info|update|clear-cache — uses cloakbrowser's JS surface (ensureBinary, binaryInfo, clearCache).
cloak serve [--port] [--host] [--headless true|false] [--proxy-server] — wraps python -m cloakbrowser.cloakserve. Requires the Python install of cloakbrowser.
cloak connect <ws_url> — create a session attached to an existing CDP endpoint.
cloak doctor · cloak test [--detector fingerprintjs|browserscan|botd|sannysoft] [--humanize] [--proxy] [--screenshot <path>] [--wait-until load|domcontentloaded|networkidle|commit] [--timeout <ms>] · cloak version
cloak fingerprint — lists all fingerprint options and usage examples. Fingerprint flags are set at session creation (session new) or in one-shot commands (fetch, scrape); this command shows what's available.
Every CloakBrowser launch flag is exposed:
- Mode:
--headless/--no-headless,--persistent <dir>(cookies/state survive),--channel <name> - Network:
--proxy <url>(HTTP/SOCKS5),--geoip(auto timezone/locale from proxy exit IP) - Identity / fingerprint:
--fingerprint <seed>(deterministic),--platform windows|macos|linux,--platform-version,--brand,--brand-version,--gpu-vendor,--gpu-renderer,--hardware-concurrency,--device-memory,--screen WxH,--webrtc-ip auto|<ip> - Locale / display:
--timezone,--locale,--user-agent,--viewport WxH,--color-scheme light|dark - Humanize:
--humanize,--humanize-preset careful|default|fast,--humanize-config <json> - Context-level:
--storage-state <path>,--extra-headers <json>,--permissions <json>,--extension <path>(repeatable) - Misc:
--extra-args <json>(extra Chromium args),--slow-mo <ms>,--timeout <ms>
Context-level options or --persistent cause cloak to use launchContext / launchPersistentContext automatically.
cloak daemon start
SID=$(cloak session new --humanize --proxy=http://u:p@residential:port --geoip | jq -r .data.session_id)
cloak goto "$SID" https://app.example.com/login
cloak fill "$SID" 'input[name=email]' 'me@example.com'
cloak fill "$SID" 'input[name=password]' "$PASSWORD"
cloak click "$SID" 'button[type=submit]'
cloak wait "$SID" --url='**/dashboard**'
cloak session save-state "$SID" ./auth.json
cloak session close "$SID"SID=$(cloak session new --storage-state=./auth.json --humanize | jq -r .data.session_id)
cloak goto "$SID" https://app.example.com/dashboard
cloak screenshot "$SID" --path=./dashboard.png --full-pageSID=$(cloak session new | jq -r .data.session_id)
cloak goto "$SID" https://example.com
cloak snapshot "$SID" --pretty
# Agent picks { uid: "u3", role: "link", name: "More information..." }
cloak click "$SID" '[data-cloak-uid="u3"]'# Reproducible identity (returning visitor)
cloak fetch https://demo.fingerprint.com --fingerprint=42 --humanize --markdown
# Pretend to be a Windows desktop
cloak fetch https://botscan.test --platform=windows --gpu-vendor='NVIDIA' --screen=1920x1080cloak scrape https://news.ycombinator.com --selector='.titleline > a' --multi --attr=href# Start cloakserve (requires Python install of cloakbrowser)
cloak serve --port=9222 --headless=false &
SID=$(cloak connect 'http://localhost:9222?fingerprint=42' | jq -r .data.session_id)
cloak goto "$SID" https://example.com~/.cloak/ Local state
├── daemon.sock Unix socket for CLI ↔ daemon RPC
├── daemon.pid Daemon process id
└── sessions/ Reserved for future per-session caches
Set CLOAK_CLI_HOME=/custom/path to relocate. Set CLOAK_CLI_SOCK=/abs/path/to/sock to override the socket only.
┌─────────────┐ spawn ┌──────────────────────┐
│ CLI client │ ─────────────► │ cloak-daemon (node) │
│ (commander) │ │ ─────────────────── │
│ │ JSON-RPC │ sessions registry │
│ │ ◄───over──────►│ cloakbrowser API │
└─────────────┘ unix sock │ playwright pages │
└──────────────────────┘
(one-shot fetch/scrape: in-process, no daemon)
- 62 RPC methods on the daemon, all listed by
cloak daemon methods. - One-shot mode (
fetch,scrape) skips the daemon entirely for stateless requests. - Session idle timeout: 1 hour by default; override with
--ttl-msonsession new.
git clone <repo>
cd CloakBrowser-Cli
npm install
npm run build # tsc → dist/
npm run typecheck
npm run test # unit
npm run test:e2e # daemon RPC plumbing (no browser)
CLOAK_BINARY_READY=1 npm run test:all # full set, requires binary
npm link # use `cloak` globally during devcloak serverequires the Python install of cloakbrowser (pip install cloakbrowser) becausecloakserveis a Python entry point. Node-only installs usesession newfor everything else.- Widevine sideloading is Linux-only (cloakbrowser upstream constraint). Use
--persistentwith a pre-seeded profile on Linux. storage.loadpost-launch is not supported by Playwright; recreate the session with--storage-state.network.recent(live network event log) is reserved for a future version; usecloak evalwithperformance.getEntriesByType("resource")for a snapshot.
MIT — see LICENSE.