Open-source project
h4ckf0r0day/obscura avatar
h4ckf0r0day/obscura

Obscura: a Rust headless browser that replaces headless Chrome for scraping and agents

The headless browser for AI agents and web scraping

28,040 stars2,077 forksRustApache-2.0

At a glance

What is it?
Obscura is an Apache-2.0 headless browser engine written in Rust, with V8, the Chrome DevTools Protocol and Puppeteer/Playwright compatibility. The pitch is a drop-in Chrome replacement with a much smaller footprint, and the README's comparison table is where the real questions start.
Who is it for?
Adopt Obscura if you scrape at volume, run agents in containers, or want CDP without shipping a Chromium runtime, and you can live with a young engine whose release line started at v0.2.0 in August 2026. Do not adopt it if you need a browser that renders every page exactly as Chrome does, or if your pipeline depends on behaviour the README does not document.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Obscura is for, and who actually needs it

Obscura targets two jobs that usually pull in the same heavy dependency: web scraping and AI agent automation. In both cases the browser is infrastructure, not the product. You need JavaScript to execute, the DOM to be queryable, and a control channel your existing code already speaks. The README states the engine "acts as a drop-in replacement for headless Chrome with Puppeteer and Playwright", which is the claim that matters. If that holds for your scripts, you keep your automation code and swap the runtime underneath it.

The audience is narrower than the tagline suggests. Obscura is for engineers who already run headless Chrome at scale and feel the cost: a 300 MB binary, a container image that takes minutes to build, and a process that needs a second or two before it answers the first command. The README's comparison table puts Obscura at 30 MB of memory, a 70 MB binary, 85 ms page load and instant startup against 200+ MB, 300+ MB, roughly 500 ms and about 2 s for headless Chrome. Those are the project's own numbers and the README does not describe the hardware or the pages measured, so treat them as a direction of travel rather than a benchmark you can plan capacity against.

The second audience is anti-detection work. The table lists "Anti-detect" as built in for Obscura and "None" for headless Chrome, and the repository topics include antidetect and antidetect-browser. That is a design decision with consequences: a browser that deliberately presents a less machine-like fingerprint is useful for scraping sites that block automation, and awkward for anything where you must prove the client is exactly Chrome.

The engine: V8, CDP, and a workspace of nine crates

The README says Obscura "runs real JavaScript via V8, supports the Chrome DevTools Protocol", and the workspace layout confirms the split. Cargo.toml lists nine members: obscura-dom, obscura-net, obscura-browser, obscura-cdp, obscura-js, obscura-mcp, obscura-render, obscura-cli and obscura. Each name maps to a stage in the pipeline, which makes the architecture readable from the file tree alone.

obscura-net handles fetching and cookies. The workspace dependency comment is unusually candid: reqwest is pulled in without the cookies feature because "obscura manages cookies through its own CookieJar (obscura-net/src/cookies.rs) and never uses reqwest's cookie store", and the comment names a compile failure in cookie 0.18.1 as the reason. obscura-dom parses with html5ever and markup5ever and matches with the selectors crate, the same lineage Servo uses. obscura-js is the V8 binding layer. obscura-cdp is the protocol surface that Puppeteer and Playwright connect to, and obscura-mcp suggests a Model Context Protocol server for agent frameworks. obscura-render is the optional layer.

That last crate is the interesting one. The README's headline is "Native rendering is here. No Chromium required", and the workspace comments describe how: taffy 0.12 for layout, tiny-skia 0.12 as a "CPU-only pure-Rust 2D rasterizer for the render layer's paint step", and ab_glyph 0.2 for glyph rasterization. Nothing in that stack is a browser engine in the Blink sense. It is a layout and paint pipeline assembled from general-purpose Rust crates, which is why the README can promise screenshots, screencasts and PDF export without shipping Chromium, and also why pixel-identical output with Chrome is not something to assume.

Installing Obscura and taking a first screenshot

Obscura is distributed as a Rust workspace, so the documented route is to build from source. The repository root holds Cargo.toml and Cargo.lock, and the Dockerfile builds with the render feature enabled, which tells you the render layer is behind a feature flag rather than on by default. Start by cloning and building the CLI binary with that feature on.

bash
git clone https://github.com/h4ckf0r0day/obscura
cd obscura
cargo build --release --features render --bin obscura

The build produces the obscura binary in target/release. The same Dockerfile also builds a second binary, obscura-worker, which suggests a worker mode for parallel jobs, though the README does not explain how the two relate. Expect a long first compile: the workspace vendors its dependencies in a vendor/ directory and the Dockerfile exists specifically to cache dependency compilation, which is a hint about how long a cold build takes.

If you would rather not install a Rust toolchain, the repository ships a Dockerfile that builds both binaries with the render feature. The build stage is rust:1-slim-bookworm and installs curl, ca-certificates, perl and make before compiling.

bash
docker build -t obscura .
docker run --rm obscura --help

Once the binary is on your PATH, the README's stated capabilities are screenshots, live page screencasts and PDF export, all handled by the engine itself. The README does not print a command line for any of them, so check the docs site at docs.obscura.sh for the exact flags before scripting against them. For automation, the more useful path is the CDP endpoint: point an existing Puppeteer or Playwright script at the Obscura instance instead of Chrome. The README claims compatibility but does not show a connection snippet, so the first thing to confirm is that your client's connect call succeeds and that a page evaluates JavaScript.

Where the drop-in claim gets thin

The README's own framing is the limitation. "Drop-in replacement" covers the control protocol, not the rendering engine. Puppeteer and Playwright talk to Obscura over CDP, so the commands arrive; what answers them is html5ever, taffy, tiny-skia and ab_glyph rather than Blink. Pages that depend on Chrome-specific layout quirks, unusual font shaping, or CSS features the Rust stack has not implemented will diverge, and the README does not publish a compatibility list. There is no statement about which CSS properties the render layer supports.

The comparison table has the same shape of problem. It lists seven metrics and gives Obscura the better number in every row, but it does not say how memory was measured, whether the 85 ms page load is a cold or warm fetch, or what page was loaded. A table where one column wins every row is a marketing artefact as much as a technical one, and the README does not link a methodology. That does not make the numbers false; it means you cannot size a fleet from them.

The anti-detection feature is also a two-sided choice. Built-in fingerprint management helps against bot detection and hurts when you need the client to be verifiably Chrome, for example in compatibility testing or in workflows where a third party checks the user agent string against a known browser build. And for plain HTML pages, Obscura is the wrong tool entirely: if the target returns static markup, an HTTP client with an HTML parser costs a fraction of a browser, Rust or otherwise. The README does not claim otherwise, but the framing invites over-application.

Finally, the release line is short. The oldest release listed is v0.2.0 from 2026-08-08, followed by v0.2.1 and v0.2.2, with the last push to the repository on 2026-09-10. The workspace package version in Cargo.toml still reads 0.1.0 while the tags have moved to 0.2.x, a small inconsistency that tells you the manifests and the releases are not kept in lockstep. For a project at this stage, pin a tag rather than tracking main.

Obscura against headless Chrome, and against the hosted route

The obvious alternative is the thing Obscura is replacing: headless Chrome, driven by Puppeteer or Playwright. The difference is not the API, since both speak CDP, but what sits behind it. Chrome ships a complete Blink and V8 rendering stack and behaves the way every site's developer tested it; Obscura ships a Rust pipeline that implements enough layout and paint to produce screenshots and PDFs. If your scraping depends on JavaScript execution and DOM queries, the two are close. If it depends on what the page looks like, Chrome is the reference implementation and Obscura is an approximation of it. Chrome also has a decade of documented behaviour and a large body of answers when something breaks; Obscura's documentation is a GitBook site and a README.

The second alternative is Obscura's own hosted product. The README describes Obscura Cloud as a work in progress with "managed infrastructure, residential proxies, and dedicated support" for people who want the engine without operating it, reachable through a waitlist link. The README states the open-source engine "stays Apache-2.0, fully featured. No feature gating, ever." That is a commitment worth noting, because it means the hosted tier competes on operations and proxies rather than on withheld features. If your bottleneck is proxy rotation and uptime, the hosted route addresses a problem the open-source engine does not; if your bottleneck is runtime weight, the engine alone is enough.

The README also notes that "Obscura inspired Cloudflare Kitesurf's first prototype", linking a Cloudflare engineering blog post about porting Obscura to Workers. That is a claim about influence, not about shared code, and it does not tell you anything about Obscura's own stability. It does suggest the architecture is legible enough that another team could port it, which is consistent with the crate-per-stage layout.

Licence, maintenance and what an upgrade costs

Obscura is Apache-2.0, and the licence identifier appears in both the repository's LICENSE file and the workspace package metadata in Cargo.toml. Apache-2.0 permits commercial use, modification and redistribution, and includes an explicit patent grant, which matters if you embed the engine in a product. It also requires that you preserve notices and state changes. The README's promise that the open-source engine stays fully featured with no gating is a project statement, not a licence term, and nothing in the licence prevents a future hosted tier from existing alongside it. That is a general observation about how open-core projects work, not legal advice; talk to your own counsel about your distribution model.

On maintenance, the repository is not archived and the last push was on 2026-09-10, with v0.2.2 released on 2026-09-05 and v0.2.1 on 2026-08-23. The cadence across August and September 2026 is steady. The upgrade cost is where the workspace layout helps: because the engine is split into nine crates with a shared workspace dependency block, version bumps for html5ever, taffy, tiny-skia and the rest are centralised in one Cargo.toml, and the Cargo.lock pins them. The Dockerfile's vendored dependency copy means image builds are reproducible but also that a dependency bump touches the vendor directory.

The practical cost is compile time. The Dockerfile goes to some length to cache dependency compilation by copying manifests and creating stub source files before the real build, which only makes sense if a cold build is slow enough to hurt. If you build Obscura in CI, budget for that layer cache and pin the tag you build.

Editorial conclusion

Adopt Obscura if you scrape at volume, run agents in containers, or want CDP without shipping a Chromium runtime, and you can live with a young engine whose release line started at v0.2.0 in August 2026. Do not adopt it if you need a browser that renders every page exactly as Chrome does, or if your pipeline depends on behaviour the README does not document. Verify first that your Puppeteer or Playwright scripts connect over CDP against a real target page, and check the docs site for the flags your workflow needs before you remove Chrome from your image.

Frequently asked questions

What is Obscura?

Obscura is an open-source headless browser engine written in Rust, built for web scraping and AI agent automation. The README states it runs JavaScript via V8, supports the Chrome DevTools Protocol and acts as a drop-in replacement for headless Chrome with Puppeteer and Playwright.

How do I install the Obscura browser?

The repository is a Rust workspace, so the documented route is to clone it and build the CLI with cargo build --release --features render --bin obscura. A Dockerfile is also included that builds both the obscura and obscura-worker binaries with the render feature enabled.

How do I use Obscura?

The README lists screenshots, live page screencasts and PDF export as native capabilities, and states that Puppeteer and Playwright can drive it over CDP as they would headless Chrome. The README does not print the command line for those features, so check docs.obscura.sh for the exact flags.

Official sources

  1. h4ckf0r0day/obscura on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/h4ckf0r0day-obscura.svg)](https://hysenlabs.com/projects/h4ckf0r0day-obscura)