Dev Tools

Obscura: The Rust Headless Browser Built for AI Agents (2026 Guide)

Obscura is an open-source (Apache-2.0) headless browser engine written in Rust that runs real JavaScript via V8, speaks the Chrome DevTools Protocol, and drops in for headless Chrome with existing Puppeteer and Playwright code — with stealth mode and an MCP server built in. ~15,500 GitHub stars as of September 7, 2026 (volatile, date-stamped), latest release v0.2.1 (August 23, 2026). The vendor's performance table is unverified — this guide separates claims from verified behavior, and covers the honest limits: single-threaded JS, raster-only PDFs, and no CAPTCHA solving.

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:

DimensionObscura (claimed)Chrome (claimed)Status
Memory (idle page)~30 MB (claimed)200+ MBVendor claim — verify with obscura-benchmark
Binary size~70 MB (claimed)300+ MBDocker image ~57 MB compressed
StartupInstant (claimed)~2 s—
Page load~85 ms (claimed)~500 ms—
Anti-detectBuilt-in stealth modeNoneDoes 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

RequirementPickReason
Fleet of agents, cost-sensitiveObscura~30 MB/page (claimed) vs 200+ MB Chrome; single 57 MB Docker image.
Scraping with anti-bot pressureObscura + proxiesStealth TLS + fingerprint consistency built in; CAPTCHAs still need proxies/humans.
Pages using service workers / mediaChromeBoth are explicitly incomplete in Obscura today.
Selectable/tagged PDFsChromeObscura PDFs are raster-backed only.
MCP-driven browser toolsObscuraNative MCP server with cookies, tabs, forms; video still via CDP screencast.
Managed-challenge sites (CF Turnstile etc.)Neither, aloneStealth 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

Get the latest on AI, LLMs & developer tools

New MCP servers, model updates, and guides like this one — delivered weekly.