Cloaked headless browser for AI agents β stealth TLS, smart extraction, SPA fallback
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Cloaked headless browser for AI agents.
Lightweight, stealthy, built in Rust. Based on Obscura.
Kloakt is a headless browser built for AI agents. It runs JavaScript via V8, extracts clean markdown from any page (including SPAs), and exposes tools via MCP for Claude Code and other AI systems.
Beyond one-shot extraction it can drive persistent, stateful sessions (click, type, navigate β cookies and page/JS state persist across calls), emit an accessibility/structure snapshot as an agent-vision substitute, and capture real screenshots via system Chrome β 12 MCP tools in all.
| Metric | Kloakt | Headless Chrome |
|---|---|---|
| Memory | 30 MB | 200+ MB |
| Binary size | 70 MB | 300+ MB |
| Anti-detect | Built-in | None |
| Page load | 85 ms | ~500 ms |
| Startup | Instant | ~2s |
| SPA extract | Yes | Manual |
One-line install (Linux & macOS). Downloads the right binary for your OS/arch from the latest GitHub Release and installs it to ~/.local/bin (or /usr/local/bin when run as root):
You can pin a version or override the install dir:
Windows: download kloakt-x86_64-windows.zip from the Releases page and extract kloakt.exe onto your PATH.
(Until a dedicated tap exists, brew tap KultMember6Banger/kloakt https://github.com/KultMember6Banger/kloakt then brew install kloakt.)
Builds the CLI from crates.io (requires Rust toolchain; first build compiles V8, ~5 min):
This installs the kloakt binary. To build with stealth mode, add --features stealth.
Requires Rust 1.75+ (rustup.rs). First build takes ~5 min (V8 compiles from source, cached after).
kloakt has no rasterizer, so this is the lightweight "what's on the page and what can I act on" view for agents that work from structure rather than pixels.
Drive a named session whose cookies and page/JS state survive across separate
invocations, backed by a running kloakt serve daemon:
The extract command uses a multi-phase pipeline optimized for AI agents:
Works on static HTML, server-rendered pages, and pure client-side SPAs (React, Vue, etc.).
Kloakt includes an MCP server for use as a Claude Code tool:
Exposes 12 native tools:
| Tool | What it does |
|---|---|
kloakt_extract | Clean markdown, or structured fields via schema |
kloakt_fetch | Low-level fetch (html/text/links/markdown, or JS eval) |
kloakt_scrape | Many URLs in parallel |
kloakt_search | Discover outbound links on a page |
kloakt_crawl | Budget/depth-limited breadth-first crawl |
kloakt_snapshot | Accessibility/structure tree (agent vision) |
kloakt_screenshot | Real PNG via system Chrome |
kloakt_session_open | Open a persistent named session |
kloakt_session_act | navigate / click / type / eval within a session |
kloakt_session_read | Read a session's page as text or snapshot |
kloakt_session_list | List open sessions |
kloakt_session_close | Close a session (drops its cookies + page) |
The CDP server embeds a per-session token in the WebSocket path (like Chrome). Connect via
browserURL so the client discovers the token from /json/version automatically β don't
hardcode the ws://.../devtools/browser path.
Enable with --features stealth.
navigator.userAgentData (Chrome 145, high-entropy values)event.isTrusted = true for dispatched eventsFunction.prototype.toString() β [native code])navigator.webdriver = undefinedAccept-Language + Client Hints (Sec-CH-UA) request headersnavigator.languageskloakt extract <URL>| Flag | Default | Description |
|---|---|---|
--format | markdown | Output: markdown, text, or links |
--main | off | Strip nav, header, footer, sidebar |
--json | off | Structured JSON: title, URL, content, meta |
--max-chars | unlimited | Truncate content to N characters |
--delay | 0 | Extra ms to wait after load |
--stealth | off | Anti-detection mode |
--selector | β | Wait for CSS selector |
--wait-until | load | load, domcontentloaded, networkidle0 (bounded by --wait) |
--schema | β | Extract structured fields as JSON (see below) |
--har | β | Write captured network activity to a HAR file |
--cache-ttl | 0 | Cache the result on disk and reuse it for N seconds |
--schemaPass a JSON object mapping field names to CSS selectors. Suffix a selector with [] to
return all matches as a list, and with @attr to return an attribute instead of text:
This is also exposed through the MCP kloakt_extract tool via an optional schema argument.
kloakt fetch <URL>| Flag | Default | Description |
|---|---|---|
--dump | html | Output: html, text, links, markdown |
--eval | β | JavaScript expression to evaluate |
--wait-until | load | Wait condition |
--selector | β | Wait for CSS selector |
--stealth | off | Anti-detection mode |
--quiet | off | Suppress banner |
kloakt serve| Flag | Default | Description |
|---|---|---|
--port | 9222 | WebSocket port |
--proxy | β | HTTP/SOCKS5 proxy URL |
--stealth | off | Anti-detection + tracker blocking |
--workers | 1 | Parallel workers |
kloakt scrape <URL...>| Flag | Default | Description |
|---|---|---|
--concurrency | 10 | Parallel workers |
--eval | β | JS expression per page |
--format | json | Output: json or text |
kloakt snapshot <URL>Emit an indexed accessibility/structure tree (always JSON) β an agent-vision substitute.
Each node is compact: i (index), tag, depth, vis (visible), and when present click,
role, text, type/value, href, id, name, label.
| Flag | Default | Description |
|---|---|---|
--interactive | off | Only actionable elements (links, buttons, inputs) |
--max-nodes | 1500 | Cap on nodes emitted |
--stealth | off | Anti-detection mode |
--delay | 0 | Extra ms to wait after load |
--wait-until | load | Wait condition |
kloakt screenshot <URL>Capture a real PNG by delegating to a locally-installed Chrome/Chromium/Edge (kloakt has no
rasterizer). Errors clearly if none is found; override detection with --chrome <path> or the
KLOAKT_CHROME env var.
| Flag | Default | Description |
|---|---|---|
--output | screenshot.png | Output PNG path |
--width | 1280 | Viewport width |
--height | 800 | Viewport height |
--chrome | auto-detect | Path to a Chrome/Chromium/Edge binary |
kloakt session <COMMAND>Drive a persistent, named session against a running kloakt serve daemon. Cookies and
page/JS state survive across separate invocations (client state in ~/.kloakt/sessions/<name>.json).
| Command | Description |
|---|---|
open <name> [--url URL] [--port] | Open (or reattach to) a session and create a page |
nav <name> <url> | Navigate the session's page |
eval <name> <expr> | Evaluate a JS expression, print the JSON value |
text <name> | Print document.body.innerText |
snapshot <name> [--interactive] | Structure snapshot of the session's page |
click <name> <selector> | Click the first matching element |
type <name> <selector> <text> | Focus an element, set its value, fire input/change |
list [--port] | List open sessions on the daemon |
close <name> | Close the session (drops its pages + cookies) |
Multi-statement JS passed to
evalreturnsnull(the daemon evaluates a single expression); wrap it in an IIFE β(function(){ ...; return v })()β to get a value back.
kloakt benchmark <URL...>Measure load performance per URL β average/min/max load time, request count, bytes, and DOM
node count β as a table or --json.
| Flag | Default | Description |
|---|---|---|
--runs | 1 | Runs per URL (reports the average) |
--json | off | Emit JSON instead of a table |
--wait-until | load | load, domcontentloaded, or networkidle0 |
kloakt extract --json includes a "challenge" field reporting a detected captcha or bot
wall (recaptcha, hcaptcha, turnstile, cloudflare, datadome, perimeterx) or
null. This is detection only β kloakt tells you a page is gated so an agent can stop
and back off; it does not attempt to solve or evade challenges. (Also surfaced via the MCP
kloakt_extract output and the Python Page.challenge field.)
| Flag | Default | Description |
|---|---|---|
--obey-robots | off | Respect robots.txt β refuse to fetch disallowed paths |
--allow-private | off | Allow private/internal/loopback hosts (disables the SSRF guard) |
Security note: by default kloakt refuses to fetch private, loopback, link-local, and cloud-metadata addresses (SSRF protection), and rejects
file://URLs. Use--allow-privateonly when you intentionally need to reach internal services. The CDP server binds to127.0.0.1and validates theHostheader to block DNS-rebinding.
Full Chrome DevTools Protocol support for Puppeteer/Playwright compatibility.
| Domain | Methods |
|---|---|
| Session | open, close, list β named, persistent browser contexts that keep cookies alive |
| Target | createTarget (browserContextName binds a page to a session), closeTarget, attachToTarget, createBrowserContext, disposeBrowserContext |
| Page | navigate, getFrameTree, addScriptToEvaluateOnNewDocument, lifecycleEvents |
| Runtime | evaluate, callFunctionOn, getProperties, addBinding |
| DOM | getDocument, querySelector, querySelectorAll, getOuterHTML, resolveNode |
| Network | enable, setCookies, getCookies, setExtraHTTPHeaders, setUserAgentOverride |
| Fetch | enable, continueRequest, fulfillRequest, failRequest |
| Storage | getCookies, setCookies, deleteCookies |
| Input | dispatchMouseEvent, dispatchKeyEvent |
Apache 2.0 β Based on Obscura by h4ckf0r0day.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/kloakt)<a href="https://allmcps.com/mcp/kloakt"><img src="https://allmcps.com/api/badge/kloakt?style=directory" alt="Kloakt on AllMCPs" /></a>