Lightweight, stealthy, and built in Rust. Obscura is a headless browser engine written in Rust, built for web scraping and AI agent automation. It runs real JavaScript via V8, supports the Chrome DevTools Protocol, and acts as a drop-in replacement for headless Chrome with Puppeteer and Playwright. Designed for automation at scale, not desktop browsing.
The open-source headless browser for AI agents and web scraping.
Lightweight, stealthy, and built in Rust.
Obscura is a headless browser engine written in Rust, built for web scraping and AI agent automation. It runs real JavaScript via V8, supports the Chrome DevTools Protocol, and acts as a drop-in replacement for headless Chrome with Puppeteer and Playwright.
Designed for automation at scale, not desktop browsing.
| Metric | Obscura | 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 |
| Puppeteer | Yes | Yes |
| Playwright | Yes | Yes |
I'm working on Obscura Cloud the hosted version, with managed infrastructure, residential proxies, and dedicated support. For people who want the engine without operating it themselves.
The open-source engine stays Apache-2.0, fully featured. No feature gating, ever.
Grab the latest binary from Releases:
# Linux x86_64
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-x86_64-linux.tar.gz
tar xzf obscura-x86_64-linux.tar.gz
./obscura fetch https://example.com --eval "document.title"
# Linux ARM64 (aarch64)
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-aarch64-linux.tar.gz
tar xzf obscura-aarch64-linux.tar.gz
# Arch Linux (AUR)
yay -S obscura-browser
# macOS Apple Silicon
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-aarch64-macos.tar.gz
tar xzf obscura-aarch64-macos.tar.gz
# macOS Intel
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-x86_64-macos.tar.gz
tar xzf obscura-x86_64-macos.tar.gz
# Windows
Download the `.zip` from the releases page and extract it manually.
No Chrome, no Node.js, no dependencies. Release archives include both
obscura and obscura-worker; keep them in the same directory for the
parallel scrape command.
Linux release builds target Ubuntu 22.04 so the downloaded binary remains usable on common LTS servers with glibc 2.35+.
docker run -d --name obscura -p 127.0.0.1:9222:9222 h4ckf0r0day/obscura
Image on Docker Hub. Multi-stage build on distroless/cc, no shell, no package manager, ~57 MB compressed.
git clone https://github.com/h4ckf0r0day/obscura.git
cd obscura
cargo build --release
# With stealth mode (anti-detection + tracker blocking)
cargo build --release --features stealth
Requires Rust 1.75+ (rustup.rs). First build takes ~5 min (V8 compiles from source, cached after).
# Get the page title
obscura fetch https://example.com --eval "document.title"
# Extract all links
obscura fetch https://example.com --dump links
# Render JavaScript and dump HTML
obscura fetch https://news.ycombinator.com --dump html
# Write dump or eval output to a file
obscura fetch https://example.com --dump text --output page.txt
# Stream the raw response body verbatim (binary-safe; bypasses the JS/DOM layer).
# Use this for images, JSON, JS, CSS, or any non-HTML resource.
obscura fetch https://picsum.photos/200/300 --dump original > photo.jpg
# List every sub-resource URL the page would fetch (NDJSON; one record per asset)
obscura fetch https://example.com --dump assets
# Fetch through an HTTP or SOCKS proxy
obscura --proxy socks5://127.0.0.1:1080 fetch https://example.com --dump text
# Wait for dynamic content
obscura fetch https://example.com --wait-until networkidle0
# Bound navigation time for slow or broken pages
obscura fetch https://example.com --timeout 10
obscura serve --port 9222
# With stealth mode (anti-detection + tracker blocking)
obscura serve --port 9222 --stealth
obscura scrape url1 url2 url3 ... \
--concurrency 25 \
--eval "document.querySelector('h1').textContent" \
--format json
# Suppress scrape progress on stderr for script-friendly output
obscura scrape https://example.com --quiet --format json
# Scrape workers inherit the global proxy
obscura --proxy http://127.0.0.1:8080 scrape https://example.com https://news.ycombinator.com
npm install puppeteer-core
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint: 'ws://127.0.0.1:9222/devtools/browser',
});
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');
const stories = await page.evaluate(() =>
Array.from(document.querySelectorAll('.titleline > a'))
.map(a => ({ title: a.textContent, url: a.href }))
);
console.log(stories);
await browser.disconnect();
npm install playwright-core
import { chromium } from 'playwright-core';
const browser = await chromium.connectOverCDP({
endpointURL: 'ws://127.0.0.1:9222',
});
const page = await browser.newContext().then(ctx => ctx.newPage());
await page.goto('https://en.wikipedia.org/wiki/Web_scraping');
console.log(await page.title());
await browser.close();
await page.goto('https://quotes.toscrape.com/login');
await page.evaluate(() => {
document.querySelector('#username').value = 'admin';
document.querySelector('#password').value = 'admin';
document.querySelector('form').submit();
});
// Obscura handles the POST, follows the 302 redirect, maintains cookies
Page load:
| Page | Obscura | Chrome |
|---|---|---|
| Static HTML | 51 ms | ~500 ms |
| JS + XHR + fetch | 84 ms | ~800 ms |
| Dynamic scripts | 78 ms | ~700 ms |
Enable with --features stealth.
navigator.userAgentData (Chrome 145, high-entropy values)event.isTrusted = true for dispatched eventsObject.keys(window) safe)Function.prototype.toString() → [native code])navigator.webdriver = undefined (matches real Chrome)--stealthObscura implements the Chrome DevTools Protocol for Puppeteer/Playwright compatibility.
| Domain | Methods |
|---|---|
| Target | createTarget, 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 (live interception) |
| Storage | getCookies, setCookies, deleteCookies |
| Input | dispatchMouseEvent, dispatchKeyEvent |
| LP | getMarkdown (DOM-to-Markdown conversion) |
Obscura embeds V8 directly. Use --v8-flags to pass raw flags through to V8, same syntax as Chromium's --js-flags and Node's command-line flags. Most common use is raising the heap cap to fix JavaScript heap out of memory on JS-heavy pages:
obscura --v8-flags "--max-old-space-size=4096" fetch <url>
obscura serveStart a CDP WebSocket server.
| Flag | Default | Description |
|---|---|---|
--port | 9222 | WebSocket port |
--proxy | — | HTTP/SOCKS5 proxy URL |
--stealth | off | Enable anti-detection + tracker blocking |
--workers | 1 | Number of parallel worker processes |
--obey-robots | off | Respect robots.txt |
obscura fetch <URL>Fetch and render a single page.
| Flag | Default | Description |
|---|---|---|
--dump | html | Output: html, text, links, markdown, assets (NDJSON of every sub-resource URL the page references), or original (raw response body) |
--eval | — | JavaScript expression to evaluate |
--wait-until | load | Wait: load, domcontentloaded, networkidle0 |
--timeout | 30 | Maximum navigation time in seconds |
--selector | — | Wait for CSS selector |
--stealth | off | Anti-detection mode |
--output | — | Write dump or eval output to a file |
--quiet | off | Suppress banner |
--proxy | — | Inherited global HTTP/SOCKS5 proxy URL |
obscura scrape <URL...>Scrape multiple URLs in parallel with worker processes.
| Flag | Default | Description |
|---|---|---|
--concurrency | 10 | Parallel workers |
--eval | — | JS expression per page |
--format | json | Output: json or text |
--quiet | off | Suppress scrape progress on stderr |
--proxy | — | Inherited global HTTP/SOCKS5 proxy URL for all workers |
Obscura ships an MCP server that exposes browser automation tools to AI agents (Claude Desktop, Cursor, etc.).
stdio (default) — for Claude Desktop and MCP clients that launch a subprocess:
obscura mcp
HTTP — for clients that connect over the network:
obscura mcp --http --port 8080
# endpoint: http://127.0.0.1:8080/mcp
Optional flags (both transports):
| Flag | Description |
|---|---|
--proxy <URL> | HTTP/SOCKS5 proxy |
--user-agent <UA> | Custom User-Agent string |
--stealth | Enable anti-detection mode |
{
"mcpServers": {
"obscura": {
"command": "obscura",
"args": ["mcp"]
}
}
}
| Tool | Description |
|---|---|
browser_navigate | Navigate to a URL (url, optional waitUntil: load / domcontentloaded / networkidle0) |
browser_snapshot | Return the current page URL, title, and body text |
browser_click | Click an element by CSS selector |
browser_fill | Set an input value (triggers input + change events) |
browser_type | Append text to an input |
browser_press_key | Dispatch a keyboard event (key, optional selector) |
browser_select_option | Select an <option> by value or text |
browser_evaluate | Evaluate a JavaScript expression and return the result |
browser_wait_for | Wait for a CSS selector to appear (selector, optional timeout in seconds) |
browser_network_requests | List network requests made by the current page |
browser_console_messages | Return console messages logged by the page |
browser_close | Close the page and reset browser state |
Apache 2.0
How To Play: Candela Obscura (Critical Role's New RPG)
Critical Role · 469K views
“Obscura Cloud waitlist is open — Thanks for getting Obscura to 10k stars. I'm working on **Obscura Cloud**, the hosted version with managed infrastructure, residential proxies, and dedicated support. For people who want…”
“Vision and Screenshots — Will Obscura eventually implement browser_vision, browser_type and other functionalities? I really like how small and efficient Obscura is compared to bloated Chromium.”
“AWS Lambda runtime build + node wrapper — Hey - Love the project! Today I tried running Obscura in a node AWS Lambda. However, the default AWS Lambda runtime image is not fully compatible with the Obscura build (specif…”
“Is this browser safe to use? — Coming from a security standpoint. I'm a little skeptic and really can't tell if it's secure to add my accounts on it. Can someone confirm that they won't steal info?”
“Camera Obscura’s 'Let’s Get Out of This Country' is still twee music at its finest - Paste Magazine — Paste Magazine”
“Sinclair Dinosaur Gas Station - Atlas Obscura — Atlas Obscura”
“Camera Obscura, Swervedriver, Ivy, and more played the Schellraiser Humboldt Hideaway (pics) - BrooklynVegan — BrooklynVegan”
Web
Recordly is your open-source screen recorder and editor for walkthroughs, demos, product videos, and more. Accepting PRs. Recordly is a desktop app for recording and editing screen captures with motion-driven presentation tools built in. Instead of sending raw footage to a motion designer just to add zooms, cursor polish, or a styled background, Recordly handles that workflow in one place for free. Recordly can automatically emphasize activity with zoom suggestions, smooth cursor movement, add motion effects, and place the final composition inside a styled frame with wallpapers, colors, gradients, blur, padding, and shadows.
Web
MiMoCode is a terminal-native AI coding assistant. It can read and write code, run commands, manage Git, and use a persistent memory system to keep a deep understanding of your project across sessions while continuously improving itself. MiMo Auto is built in as a free-for-limited-time channel, so you can start with zero configuration. MiMoCode also supports connecting to any mainstream LLM provider API. The first launch guides you through configuration automatically. Supported options:
Web
Kami (紙, かみ) means paper in Japanese: the surface where a finished idea lands. AI can produce documents better than most humans do manually. The missing piece is not capability but constraint: without a design system, every session drifts into generic gray and inconsistent layouts. Kami fills that gap: one constraint language, nine templates, simple enough for agents to run reliably, strict enough that every output is something you actually want to ship. English and Chinese are first-class; Japanese and Korean work via best-effort CJK paths with visual QA before delivery. Part of a trilogy: Kaku (書く) writes code, Waza (技) drills habits, Kami (紙) delivers documents.
Web
All telemetry stripped. All guardrails removed. All experimental features unlocked. One binary, zero callbacks home. Checks your system, installs Bun if needed, clones the repo, builds with all experimental features enabled, and symlinks free-code on your PATH. Then run free-code and use the /login command to authenticate with your preferred model provider.