oxibrowser 0.21.1

Headless browser engine with CDP support
Documentation

๐ŸŒ OxiBrowser

The headless browser built in pure Rust for AI agents.

Not a Chromium fork. Not a C++ wrapper. A browser engine written from scratch in Rust, designed from day one for automation, web scraping, and AI-driven workflows.

CI Crates.io docs.rs GitHub release License: MIT GitHub stars Rust

Report Bug ยท Request Feature ยท Read the Docs ยท Discord



โœจ Why OxiBrowser?

You're building AI agents that need to browse the web. You don't need a full browser with GPU rendering, audio output, and extension support. You need something fast, small, and programmable.

OxiBrowser is built for exactly that use case:

  • ๐Ÿค– AI-Agent First โ€” CLI designed for agents: --json output, describe for schema, skill for prompts, session for multi-step
  • โšก Blazing Fast โ€” Cold starts in ~50ms, no Chromium overhead, no Node.js required
  • ๐Ÿฆ€ Rust-First โ€” boa_engine (JS, no V8), html5ever (HTML) are pure Rust. TLS uses btls (BoringSSL C binding) for stealth fingerprint emulation. Single static binary.
  • ๐Ÿ”Œ CDP Compatible โ€” Puppeteer, Playwright, and any Chrome DevTools Protocol client works out of the box
  • ๐Ÿ›ก๏ธ Secure by Default โ€” SSRF protection with CIDR blocking, robots.txt respect, no sandbox escape surface
  • ๐Ÿ“ฆ Tiny Footprint โ€” ~44 MB binary, ~8 MB base memory. Run 100 instances without breaking a sweat

๐Ÿ“‹ Changelog

See CHANGELOG.md for the full version history and GitHub Releases for release notes.

Recent milestones (v0.17โ€“v0.20): per-frame JS execution contexts (iframe isolation), Shadow DOM (open/closed/declarative/slots), async fetch/XMLHttpRequest/WebSocket, CORS + preflight, cookie PSL/prefixes, multi-tab, PDF export, @font-face webfonts, Blitz/Stylo/Taffy/Parley rendering pipeline, stealth bot-detection, Canvas 2D, custom-element lifecycle, and a 12-domain CDP server.

๐Ÿš€ Quick Start

Install

cargo install oxibrowser

Fetch a page (human-readable)

$ oxibrowser fetch https://example.com

Example Domain

# Example Domain

This domain is for use in documentation examples...
[Learn more](https://iana.org/domains/example)

Fetch a page (agent mode)

$ oxibrowser fetch https://example.com --json
{"ok":true,"data":{"url":"https://example.com/","title":"Example Domain","status":200,"markdown":"..."},"meta":{"elapsed_ms":152}}

Extract structured data

$ oxibrowser extract https://example.com --links --json
{"ok":true,"data":{"links":["https://iana.org/domains/example"],"title":"Example Domain"}}

Multi-step session (stdin/stdout JSON REPL)

$ oxibrowser session
new
{"ok":true,"data":{"tab_id":"t1"}}
goto t1 https://example.com
{"ok":true,"data":{"status":200,"title":"Example Domain"}}
eval t1 document.title
{"ok":true,"data":{"value":"Example Domain"}}
close t1
{"ok":true,"data":{"closed":"t1"}}
exit
{"ok":true,"data":{"exit":true}}

Start CDP server (Puppeteer/Playwright)

oxibrowser serve --port 9222
import puppeteer from 'puppeteer-core';

const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://127.0.0.1:9222',
});

const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');
console.log(await page.title());
await browser.close();

๐Ÿ“‹ CLI Reference

oxibrowser <COMMAND>

COMMANDS:
  fetch      Fetch a URL and return content (markdown default)
  extract    Extract structured data (links, text, elements)
  run        Run a YAML automation script
  session    Interactive stdin/stdout JSON REPL (22 commands)
  serve      Start CDP WebSocket server
  search     Web / GitHub / GitHub-issues search (no browser needed)
  describe   Print CLI schema as JSON (for agents)
  skill      Print agent skill guide
  version    Print version information

fetch โ€” One-shot page fetch

# Human-readable (markdown, default)
oxibrowser fetch https://example.com

# Agent mode
oxibrowser fetch https://example.com --json

# Click then read
oxibrowser fetch https://example.com --click button --wait .result --json

# Quick page summary
oxibrowser fetch https://example.com --summary --json

# Run JS
oxibrowser fetch https://example.com --eval "document.title" --json

# Limit response size
oxibrowser fetch https://example.com --max-bytes 8000 --json

# Select specific fields
oxibrowser fetch https://example.com --fields url,title,status --json

extract โ€” Structured data extraction

# Get all links
oxibrowser extract https://example.com --links --json

# Extract elements by CSS selector
oxibrowser extract https://example.com --selector "a" --all --attrs text,href --json

# Title + full text
oxibrowser extract https://example.com --title --text --json

session โ€” Multi-step automation

oxibrowser session  # Start REPL

# 22 commands:
new, goto, back, forward, reload, click, fill, press, type,
select, check, uncheck, scroll, eval, extract, content,
screenshot, wait, close, close --all, list, help, exit

describe โ€” Agent introspection

# Compact (~200 tokens)
oxibrowser describe --compact

# Full command details
oxibrowser describe fetch
oxibrowser describe session

search โ€” Web / GitHub search (no browser needed)

# Web search (DuckDuckGo)
oxibrowser search "rust async" --engine ddg --max-results 5 --json

# GitHub search
oxibrowser search "memory pool" --source github --json

# GitHub issues for a specific repo
oxibrowser search "panic on shutdown" --source github-issues --repo project-oxi/oxibrowser --json

run โ€” YAML automation

name: example
steps:
  - step_type: goto
    data:
      goto: https://example.com
  - step_type: content
    data:
      format: markdown
oxibrowser run script.yaml

JSON Output Format

All --json responses follow the same schema:

{
  "ok": true,
  "data": { ... },
  "meta": { "elapsed_ms": 152 }
}

On error:

{
  "ok": false,
  "error": "URL scheme must be http or https",
  "error_code": "INVALID_URL"
}

Exit codes: 0=success, 1=runtime, 2=input validation, 3=timeout, 4=network


๐Ÿ— Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚            Puppeteer / Playwright / Rust CDP          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚ CDP WebSocket
                         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                 CDP Server (12 domains)               โ”‚
โ”‚  Browser ยท DOM ยท Emulation ยท Fetch ยท Input            โ”‚
โ”‚  Log ยท Network ยท OXI ยท Page ยท Runtime                 โ”‚
โ”‚  Target ยท Tracing                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚          Browser โ†’ Session โ†’ Page โ†’ Frame            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  WebAPI  โ”‚  Network โ”‚  JS Runtime  โ”‚  Rendering      โ”‚
โ”‚  DOM     โ”‚  HTTP    โ”‚  boa_engine  โ”‚  Blitz+Stylo    โ”‚
โ”‚  Tree    โ”‚  Cookies โ”‚  ES2024+     โ”‚  Taffy+Parley   โ”‚
โ”‚  Storage โ”‚  SSRF    โ”‚  per-frame   โ”‚  PNG/PDF/font   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  html5ever ยท encoding_rs ยท reqwest ยท boa ยท blitz-dom  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Crate Structure

Crate Lines Purpose
oxibrowser 6,103 Binary + CLI (8 subcommands, session REPL, agent features)
oxibrowser-core 35,287 Browser engine: Session, Page, Frame, JS Runtime, Network
oxibrowser-cdp 5,643 CDP WebSocket server with 12 domain handlers
oxibrowser-render 513 Blitz/Stylo/Taffy/Parley rendering pipeline (PNG/PDF/fonts)
Total ~47,500

๐ŸŒŸ Features

Agent-First CLI

Designed for AI agent workflows โ€” no daemon, no socket, single binary:

Feature Description
--json Machine-readable output (opt-in, human by default)
--max-bytes N Truncate response to N bytes
--fields a,b,c Select specific output fields
--summary Quick page metadata (title, links, headings)
describe CLI schema as JSON for agent introspection
skill Agent skill guide for prompt injection
session Stdin/stdout JSON REPL with 22 commands
Exit codes 0=success, 1=runtime, 2=input, 3=timeout, 4=network

JavaScript Runtime (ES2024+)

Powered by boa_engine โ€” pure Rust, no V8 dependency:

Web API Status
document.querySelector / querySelectorAll โœ… Full
document.createElement / createTextNode โœ… Full
element.appendChild / removeChild / insertBefore โœ… Full
element.getAttribute / setAttribute / removeAttribute โœ… Full
element.cloneNode / remove() โœ… Full
element.style (CSSStyleDeclaration) โœ… Property accessor
element.classList (DOMTokenList) โœ… Property accessor
element.textContent / innerHTML โœ… Read/Write
element.addEventListener / dispatchEvent โœ… Full
element.click() โœ… With event handlers
fetch() โœ… Full (channel bridge)
XMLHttpRequest โœ… Full with callbacks
localStorage โœ… Persistent
MutationObserver โœ… observe/disconnect/takeRecords
setTimeout / setInterval โœ… TokioJobQueue
console.log/warn/error โœ… With formatting
URL / URLSearchParams โœ… Full
crypto.getRandomValues โœ… Pseudo-random
TextEncoder / TextDecoder โœ… UTF-8
atob / btoa โœ… Base64
requestAnimationFrame โœ… Polyfill

CDP Protocol (Chrome DevTools Protocol)

12 domain handlers โ€” Puppeteer and Playwright compatible:

Domain Key Methods
Browser getVersion, close
DOM getDocument, describeNode, querySelector, querySelectorAll, getBoxModel, getContentQuads
Emulation setDeviceMetricsOverride, clearDeviceMetricsOverride, setUserAgentOverride
Fetch enable/disable, continueRequest, failRequest, fulfillRequest, getResponseBody
Input dispatchKeyEvent, dispatchMouseEvent, dispatchDragEvent, insertText
Log enable, entryAdded
Network enable/disable, setExtraHTTPHeaders, getResponseBody, JS-fetch/XHR/WS lifecycle events
OXI ๐Ÿค– getMarkdown, getPageInfo โ€” AI-native extensions
Page navigate, captureScreenshot, printToPDF, getFrameTree, getTitle
Runtime evaluate, callFunctionOn, enable, consoleAPICalled, exceptionThrown
Target getTargets, createTarget, attachToTarget, setAutoAttach (multi-tab)
Tracing start, end, getCategories (Playwright tracing compatible)

OXI Domain โ€” Built for AI Agents

import websockets, json, asyncio

async def ai_scrape():
    ws = await websockets.connect('ws://localhost:9222/ws')
    
    await ws.send(json.dumps({
        "id": 1, "method": "Page.navigate",
        "params": {"url": "https://news.ycombinator.com"}
    }))
    await asyncio.sleep(2)
    
    # Clean markdown โ€” perfect for LLM ingestion
    await ws.send(json.dumps({"id": 2, "method": "OXI.getMarkdown"}))
    resp = json.loads(await ws.recv())
    print(resp['result']['markdown'])

Network Layer

| HTTP Client | reqwest with cookie persistence, redirect following | | Cookie Jar | Domain-scoped cookies: PSL, __Host-/__Secure- prefixes, expiry, CHIPS partitioning | | CORS | Preflight (OPTIONS), Access-Control-* validation (Fetch ยง3.2โ€“3.3) | | Auth | Basic + Digest (401-challenge retry) | | Proxy | HTTP / HTTPS / SOCKS proxy via BrowserConfig.proxy | | SSRF Protection | CIDR blocking for private network ranges, scheme-aware | | robots.txt | RFC 9309 compliant parser, --obey-robots flag | | Network Interception | Pause, modify, or block any request via Fetch domain | | WebSocket | Full browser WebSocket API (ws + wss) | | Stealth | Chrome JA4+ fingerprint emulation, bot-detection challenge retry |

Rendering Pipeline

Powered by the Blitz rendering stack โ€” isolated in oxibrowser-render so Stylo/html5ever dependency trees stay out of the core workspace:

  • Blitz-dom โ€” DOM tree representation for layout and paint
  • Stylo (Firefox CSS engine) โ€” CSS cascade, computed styles
  • Taffy โ€” block/inline/flex layout
  • Parley โ€” text shaping with @font-face webfont support
  • PNG screenshots โ€” shadow-DOM-aware rasterization (flattened tree compose)
  • PDF export โ€” Page.printToPDF / Tab::print_to_pdf via printpdf
  • HTML โ†’ Markdown โ€” full conversion with heading, link, and list support

๐Ÿงช Testing

# Run all tests
cargo test --workspace

# CLI integration tests (fast, no network)
cargo test -p oxibrowser --test cli

# E2E CDP tests
cargo test -p oxibrowser-cdp

# Integration tests (real websites, requires internet)
cargo test --workspace -- --ignored

๐Ÿ”ง Advanced Usage

Rust API

use oxibrowser_core::Browser;
use oxibrowser_core::config::BrowserConfig;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let browser = Browser::new(BrowserConfig::default()).await?;
    let session = browser.new_session().await?;
    
    session.navigate("https://example.com").await?;
    
    let title = session.evaluate("document.title").await?;
    println!("Title: {:?}", title);
    
    Ok(())
)
}

Use as a library

[dependencies]
oxibrowser-core = "0.11"
# Or the CDP server:
oxibrowser-cdp = "0.11"

Request Interception

const client = await page.target().createCDPSession();

await client.send('Fetch.enable', {
    patterns: [{ urlPattern: '*ads*' }]
});

client.on('Fetch.requestPaused', async ({ requestId }) => {
    await client.send('Fetch.failRequest', {
        requestId,
        reason: 'BlockedByClient'
    });
});

๐Ÿค Contributing

See CONTRIBUTING.md for full guidelines.

git clone https://github.com/project-oxi/oxibrowser.git
cd oxibrowser
cargo build
cargo test --workspace
cargo clippy --workspace -- -D warnings

๐Ÿ“„ License

OxiBrowser is licensed under the MIT License.

๐Ÿ™ Acknowledgments

  • boa_engine โ€” Pure Rust JavaScript engine (ES2024+)
  • html5ever โ€” HTML parser from the Servo project
  • reqwest โ€” Ergonomic HTTP client for Rust
  • tokio โ€” Async runtime powering the entire networking stack

โฌ† Back to Top

Made with ๐Ÿฆ€ in Rust