Shirabe

Shirabe

Headless browser automation

License: SySL-1.0 GitHub Checks Docs docs.rs

English · 简体中文 · 繁體中文 · 日本語 · 한국어 · Français · Español · Русский · العربية

Introduction

shirabe is a lightweight, Rust-native browser automation library and debug server. It drives any browser that speaks the Chrome DevTools Protocol — Google Chrome, Chromium, Microsoft Edge — through one hand-rolled CDP engine, and exposes the whole thing over a small HTTP API. It is the browser backbone extracted from the tairitsu packager, hardened to stand on its own.

The guiding idea is the same as ort for ONNX Runtime: you should never have to install a browser by hand. A pinned Chrome for Testing build is fetched into a shared cache at build time (or on first use), located transparently, and driven through CDP. Pin a different backend, ship native libs with your product, route the download through a mirror or proxy — all from environment variables.

Quick Start

CLI

# Zero-config: auto-discovers Chrome/Chromium/Edge, or fetches Chrome for Testing.
shirabe debug --port 3001

# Pin a backend, route the browser through a proxy.
SHIRABE_BACKEND=chromium shirabe debug --port 3001 --proxy http://localhost:7890

# Then drive it over HTTP.
curl -X POST http://localhost:3001/navigate \
  -H "Content-Type: application/json" -d '{"url":"https://example.com"}'
curl -X POST http://localhost:3001/screenshot -d '{}'

npx (no Rust toolchain required)

Prebuilt binaries are published to npm, so you can run shirabe with a single command — no cargo build, no Chrome install:

npx @celestia-island/shirabe debug --port 3001

The @celestia-island/shirabe root package pulls the right platform subpackage (-linux-x64 / -darwin-arm64 / -win32-x64) automatically via optionalDependencies + a postinstall selector. To pin a version:

npx @celestia-island/shirabe@0.1.0 debug --port 3001

Library

use shirabe::{start_debug_server, DebugServerConfig};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let cfg = DebugServerConfig {
        base_url: "about:blank".to_string(),
        dev_port: 0,
        dist_dir: String::new(),
        package_name: String::new(),
        proxy: Some("http://localhost:7890".to_string()),
    };
    start_debug_server(cfg, 3001).await
}

Backends & zero-config resolution

Pick a backend with SHIRABE_BACKEND=chrome|chromium|edge|firefox|servo|auto (default auto). The Chromium family (Chrome / Chromium / Edge) is driven in-process through our own CDP engine; Firefox and Servo take a different path — their cores are built by the browser vendors and shipped as dynamic libraries, which shirabe drives through a thin C-binding FFI contract (the foreign-engine feature, see Foreign Engines). Whichever is chosen, shirabe resolves it in this order:

  1. Backend-specific overrideCHROME_PATH / CHROMIUM_PATH / EDGE_PATH.
  2. Build-time baked pathSHIRABE_BROWSER_PATH, emitted by build.rs when the `auto-fetch` feature downloads Chrome for Testing during the build.
  3. System binary on $PATH and well-known install locations.
  4. Runtime fetch (the runtime-fetch feature) — download the pinned build into the shared cache.

Download knobs (build time and runtime alike):

EnvPurpose
SHIRABE_CHROME_VERSIONOverride the pinned Chrome for Testing version.
SHIRABE_CHROME_MIRRORDownload from a mirror instead of storage.googleapis.com.
SHIRABE_CHROME_SHA256Optional hex checksum to verify the download.
SHIRABE_DOWNLOAD_PROXYRoute the download through http:// / https:// / socks5:// proxy.
SHIRABE_DOWNLOAD_TIMEOUT_SECSPer-request timeout (default 600).
SHIRABE_SKIP_BROWSER_FETCHSkip both build-time and runtime downloads.
SHIRABE_BACKENDWhich Chromium-family backend to drive.

Shipping native libraries with your product

A fetched Chrome build (and your own crate) depend on native libraries that a clean container may lack. shirabe gives packagers two tools:

  [[lib]]
  path = "third_party/libfoo.so"
  optional = true
  target_os = "linux"

  [[lib]]
  path = "third_party/foo.dll"
use shirabe::{BundleReport, render_bundle_report};
let report = BundleReport::build(&backend_exe);
print!("{}", render_bundle_report(&report));

HTTP API

MethodPathDescription
GET/healthServer health
GET/infoBrowser status + selected backend
POST/navigateNavigate to a URL
POST/clickClick an element
POST/typeType text
POST/evaluateExecute JavaScript
POST/screenshotCapture a screenshot
POST/wait-for-selectorWait for an element
GET/domQuery the DOM
GET/a11yAccessibility tree
POST/batchBatch operations

…plus console, network and websocket capture endpoints for full control.

MCP server

Build shirabe with the mcp feature and run the stdio server — it hosts the headless-browser debug API in-process (no separate shirabe debug daemon to launch) and exposes its operations to AI coding assistants over the Model Context Protocol:

shirabe mcp

The server advertises twelve tools — browser_navigate, browser_navigate_back, browser_navigate_forward, browser_snapshot, browser_dom, browser_screenshot, browser_click, browser_type, browser_press_key, browser_evaluate, browser_console_messages, browser_resize — each proxying over loopback to the in-process CDP engine. One process is both the browser and the MCP server; when it exits, Chrome is killed. Wire it into an MCP client:

{
  "mcpServers": {
    "shirabe": { "command": "shirabe", "args": ["mcp"] }
  }
}

Set SHIRABE_URL to change the page the browser opens on startup (default about:blank) and SHIRABE_DOWNLOAD_PROXY to route Chrome's traffic through a proxy. The browser backend, mirror, and fetch knobs from the library all still apply.

Development

SHIRABE_SKIP_BROWSER_FETCH=1 cargo clippy --all-targets --all-features -- -D warnings
SHIRABE_SKIP_BROWSER_FETCH=1 cargo test --all-features
Screenshots

shirabe snapshot

License

SySL-1.0 (Synthetic Source License). See LICENSE.