Obscura is a headless browser engine written in Rust for web scraping and AI-agent automation. It executes JavaScript with an embedded V8, implements the Chrome DevTools Protocol (CDP), and connects to Puppeteer and Playwright in place of headless Chrome. Release builds include a native rendering engine that produces viewport and full-page screenshots, activity-driven CDP screencasts, and raster PDF export without starting Chromium.
The CLI has three entry points. fetch loads a single page and dumps HTML, text, links, Markdown, sub-resource URLs, or the raw response body, or evaluates a JavaScript expression. scrape runs many URLs across parallel worker processes. serve starts a CDP WebSocket server on port 9222. Fetches to private and internal IP addresses are blocked by default as SSRF protection, a script-execution budget (30 s by default) stops a hung page from stalling a worker, and --v8-flags passes raw flags such as a larger heap cap through to V8.
A stealth build adds per-session fingerprint randomisation (GPU, screen, canvas, audio, battery), a navigator.userAgentData profile matching Chrome 145, native-function masking, navigator.webdriver = undefined, and a block list of 3,520 tracker, analytics, and ad domains. Cloudflare's Kitesurf agent browser began as a port of Obscura to Workers.
Reported resource figures against headless Chrome:
| Metric | Obscura | Headless Chrome |
|---|---|---|
| Memory | 30 MB | 200+ MB |
| Binary size | 70 MB | 300+ MB |
| Page load | 85 ms | ~500 ms |
| Startup | Instant | ~2 s |
An MCP server (obscura mcp, over stdio or HTTP) exposes navigation, snapshot, screenshot, PDF, click, fill, type, key-press, option-select, evaluate, wait, network-request, and console-message tools to agents such as Claude Desktop and Cursor. A Hermes plugin runs Hermes browser tasks on Obscura by spawning obscura serve per session and driving it over CDP. A hosted version, Obscura Cloud, with managed infrastructure and residential proxies is in preparation.
Features
- CDP compatibility: Target, Page, Runtime, DOM, Network, Fetch, IO, Storage, and Input domains, plus a getMarkdown DOM-to-Markdown method
- Puppeteer and Playwright: connect with puppeteer.connect or chromium.connectOverCDP against the WebSocket endpoint
- Native rendering: block, inline, flex, grid, table, float, positioning, transform, SVG, canvas, and animation paths for screenshots, screencasts, and PDFs
- Page fetching: --dump html|text|links|markdown|assets|original, --eval, --wait-until networkidle0, --selector, and --screenshot
- Parallel scraping: obscura scrape with configurable concurrency and JSON or text output
- Stealth mode: fingerprint randomisation, trusted dispatched events, hidden internals, and tracker blocking via --stealth
- Proxy support: HTTP and SOCKS5 proxies inherited by scrape workers
- Request interception: Fetch.enable, continueRequest, fulfillRequest, failRequest, and chunked body streaming via IO.read
- SSRF protection: private and internal addresses blocked unless --allow-private-network is set
- Timeout model: OBSCURASCRIPTDEADLINEMS, OBSCURAMODULEBUDGETMS, and OBSCURAFETCHTIMEOUT_MS bound script, module, and network time
- MCP server: fourteen browser tools over stdio or HTTP with optional proxy, user agent, and stealth flags
- Docker image: distroless build with no shell or package manager, about 57 MB compressed