Back to feed

h4ckf0r0day/obscura

h4ckf0r0day/obscura
7.5k
+477/day
442
Rust

The headless browser for AI agents and web scraping

From the README

Obscura

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.

Why Obscura over headless Chrome?

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 |

Install

Download

Grab the latest binary from Releases:

# Linux x86_64
curl -LO 
tar xzf obscura-x86_64-linux.tar.gz
./obscura fetch  --eval "document.title"

# macOS Apple Silicon
curl -LO 
tar xzf obscura-aarch64-macos.tar.gz

# macOS Intel
curl -LO 
tar xzf obscura-x86_64-macos.tar.gz

# Windows
Download the `.zip` from the releases page and extract it manually.

Single binary. No Chrome, no Node.js, no dependencies.

Build from source

git clone 
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).

Quick Start

Fetch a page

# Get the page title
obscura fetch  --eval "document.title"

# Extract all links
obscura fetch  --dump links

# Render JavaScript and dump HTML
obscura fetch  --dump html

# Wait for dynamic content
obscura fetch  --wait-until networkidle0

Start the CDP server

obscura serve --port 9222

# With stealth mode (anti-detection + tracker blocking)
obscura serve --port 9222 --stealth

Scrape in parallel

obscura scrape url1 url2 url3 ... \
  --concurrency 25 \
  --eval "document.querySelector('h1').textContent" \
  --format json

Puppeteer / Playwright

Puppeteer

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(');

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();

Playwright

npm install playwright-core
import { chromium } from 'playwright-core';

const browser = await chromium.connectOverCDP({
  endpointURL: 'ws://127.0.0.1:9222',
});

co