Someone built in Rust what Chrome engineers couldn't optimize in years — Obscura is an open-source headless browser engine for web scraping and AI agents.
— @itsharmanjot September 4, 2026
What Obscura Is
Created April 2026, Obscura targets two workloads: web scraping and AI-agent browser automation. It runs real JavaScript through V8 (via deno_core), implements the Chrome DevTools Protocol including Fetch-domain request interception, and renders natively (CSS cascade, flex/grid layout via Taffy, CPU paint via tiny-skia). The managed cloud (obscura.sh) is waitlist-only with no published pricing; the engine self-hosts in a single ~57 MB Docker container with “no feature gating, ever.” Performance claims below are the vendor's, pending the separate benchmark suite:
| Dimension | Obscura (claimed) | Chrome (claimed) | Status |
|---|---|---|---|
| Memory (idle page) | ~30 MB (claimed) | 200+ MB | Vendor claim — verify with obscura-benchmark |
| Binary size | ~70 MB (claimed) | 300+ MB | Docker image ~57 MB compressed |
| Startup | Instant (claimed) | ~2 s | — |
| Page load | ~85 ms (claimed) | ~500 ms | — |
| Anti-detect | Built-in stealth mode | None | Does NOT solve CAPTCHAs or managed challenges |
Architecture
Nine Rust crates, one per layer: obscura-cli (fetch/serve/scrape/mcp), obscura-cdp (WebSocket server and method dispatch), obscura-browser (page/navigation/lifecycle), obscura-js (the V8 bridge), obscura-dom, obscura-net (HTTP/stealth client, cookies, robots cache, tracker blocklist), obscura-mcp, obscura-render, and an embeddable obscura library. One design decision explains most behavior: one V8 isolate per process, single-threaded — a global lock serializes JavaScript, so CPU-bound scripts queue; concurrent page navigations still work because navigation runs in spawned tasks. Watchdogs bound everything (script deadline 30 s, module budget 3 s, CDP command 60 s), and the DOM bridge funnels every operation through a single Rust op wrapped in catch_unwind.
Install and Build
Prebuilt binaries cover x86_64/aarch64 Linux and macOS plus Windows (AUR and NixOS packages exist). The Docker image (~57 MB, distroless, no shell) is the quickest server: docker run -d --name obscura -p 127.0.0.1:9222:9222 h4ckf0r0day/obscura. From source: Rust 1.75+, a C compiler, ~5 GB disk, ~5-minute first build (V8 compiles from source); the stealth feature additionally needs CMake, Clang, and libclang. Build form per docs: cargo build --release -p obscura-cli --bins --features render (add ,stealth for the stealth client). Archive suffixes choose features: plain = render, no stealth; -stealth = both; -no-render = neither; -no-render-stealth = stealth only. Smoke test: ./obscura fetch https://example.com --eval "document.title" → "Example Domain".
Using It with Puppeteer and Playwright
Start with obscura serve --port 9222, then connect over CDP. Puppeteer: use puppeteer-core (not puppeteer) with puppeteer.connect({browserWSEndpoint: 'ws://127.0.0.1:9222'}). Playwright: chromium.connectOverCDP('ws://127.0.0.1:9222') — not connect — then browser.contexts()[0] || browser.newContext(). Supported operations cover the automation core: goto/reload/back/forward, evaluate, click/type/fill, waitForSelector/Function, cookies, request interception, screenshots (viewport/clipped/fullPage), PDF, screencast, plus DOMSnapshot and markdown extraction. Lifecycle events (domcontentloaded → load → networkidle2 → networkidle0) drive waitUntil — note the default differs: CLI defaults to load, Puppeteer/Playwright clients to domcontentloaded.
Stealth Mode: What It Does and Does Not
Stealth is a build/flag, and it works at the network layer first: a BoringSSL-based client with a consistent Chrome-matching TLS fingerprint (deliberately consistent, not randomized — docs-corrected from early README wording), bundled webpki roots, and a 3,520-domain tracker blocklist applied before requests leave the process. Anti-fingerprinting covers per-session randomization (GPU, screen, canvas, audio, battery), realistic userAgentData, native-function masking, and webdriver=undefined, with an identity pool of Windows/macOS profiles kept internally consistent (canvas/webgl return null rather than a renderer string). Opt-in rotation exists (OBSCURA_PROFILE, OBSCURA_ROTATE_PROFILE) but mismatches TLS/timezone unless aligned — docs recommend leaving rotation off when pinned. What stealth does not do: Cloudflare interactive challenges, Datadome/Akamai managed challenges, CAPTCHAs, or IP rate limiting — use residential proxies for those.
MCP for Agent Tooling
obscura mcp runs stdio MCP for Claude Desktop and Claude Code (claude mcp add obscura /path/to/obscura mcp); obscura mcp --http --port 3000 exposes an HTTP endpoint at /mcp (HTTP-only host, loopback default). Tools span navigation, snapshots, interaction, markdown/links extraction, form detection and filling, screenshots and PDFs (render builds only), cookies with storage-state, and tab management — session-persistent, with element refs that go stale after navigation or re-render. Video is the one gap: MCP serves still images and PDFs; motion requires CDP screencast.
Honest Limits
The single shared V8 isolate serializes CPU-bound JS — heavy per-page scripting will queue. Service workers, native media playback, some Web APIs, long-tail CSS, and compositor features are incomplete. PDFs are raster-backed (not selectable, no tagged structure). Playwright's page.video() and tracing are not implemented; BrowserContext storage-state is limited (use --storage-dir). file:// access is refused by default (CVE-hardened; needs --allow-file-access). And performance claims remain vendor numbers until reproduced — the dedicated obscura-benchmark repo (WPT, obstacle course, real-world corpus) is the place to watch.
The Security Model
Two non-negotiables. First, no auth on either CDP or MCP servers — bind loopback, put a reverse proxy with auth in front, or isolate via Docker; the HTTP MCP adds Origin checking (403 on unlisted origins) and a 16 MiB body cap, but that is not authentication. Second, an SSRF guard: private, loopback, and link-local targets are blocked by default with a DNS-resolution-time check (rebinding-safe); opt out with --allow-private-network only on trusted networks. Obscura also ignores ambient HTTP_PROXY environment variables — configure proxies explicitly. No external security audit is cited as of v0.2.1; release notes credit researchers for the file:// fix.
Use It If
Use Obscura if you run agent fleets where per-browser Chrome overhead is the bottleneck, need scriptable stealth for scraping, or want MCP-based browser tools without a Chrome fleet. Stay on Chrome if your pages depend on service workers, advanced media, or long-tail CSS; need selectable/tagged PDFs; or require battle-tested TLS behavior against managed-challenge vendors. The pragmatic path: run the Docker image behind Playwright connectOverCDP for a week and measure your own pages — the benchmark repo is too young to outsource that judgment.
Chrome vs Obscura: The Decision Matrix
| Requirement | Pick | Reason |
|---|---|---|
| Fleet of agents, cost-sensitive | Obscura | ~30 MB/page (claimed) vs 200+ MB Chrome; single 57 MB Docker image. |
| Scraping with anti-bot pressure | Obscura + proxies | Stealth TLS + fingerprint consistency built in; CAPTCHAs still need proxies/humans. |
| Pages using service workers / media | Chrome | Both are explicitly incomplete in Obscura today. |
| Selectable/tagged PDFs | Chrome | Obscura PDFs are raster-backed only. |
| MCP-driven browser tools | Obscura | Native MCP server with cookies, tabs, forms; video still via CDP screencast. |
| Managed-challenge sites (CF Turnstile etc.) | Neither, alone | Stealth does not solve interactive challenges — budget for human-in-the-loop. |
FAQ
Does Obscura work with existing Playwright code?
Yes, via connectOverCDP against ws://127.0.0.1:9222 — same API surface for navigation, evaluation, clicks, waits, and screenshots. Launch methods (browser.newContext vs CDP contexts) and some storage-state features differ.
Does stealth mode beat Cloudflare?
Not managed challenges. Stealth targets TLS/fingerprint consistency and tracker blocking; Cloudflare interactive challenges, Datadome, and CAPTCHAs are explicitly out of scope — pair with residential proxies and human-in-the-loop where required.
Why is my heavy JavaScript slow?
One V8 isolate per process, single-threaded: CPU-bound scripts queue behind each other. Split work across Obscura processes, or offload computation out of the page.
Is it production-ready?
For scraping/automation pipelines that fit the limits, teams are running it (v0.2.1, active release cadence). It has no external audit and no auth by design — treat network exposure accordingly.
Sources
- GitHub — h4ckf0r0day/obscura (README, releases, LICENSE)
- docs.obscura.sh — installation, CDP usage, stealth, MCP
- obscura.sh — project site and managed cloud
- GitHub — obscura-benchmark (independent benchmark suite)
Get the latest on AI, LLMs & developer tools
New MCP servers, model updates, and guides like this one — delivered weekly.