Skip to content

Repository files navigation

Lightwright

A small, Chromium-first automation library for Rust workloads that need a real browser and explicit control over its resources.

Lightwright is built for scrapers, agents, CI jobs, internal automation, and long-lived workers. It speaks Chrome DevTools Protocol directly, keeps the core Rust-native, and makes browser memory, resource loading, and lifecycle decisions visible in your code.

Playwright-style, not Playwright-compatible. Lightwright is an alpha with a deliberately smaller API surface - not a drop-in replacement for Playwright.

Why Lightwright

  • Lean Rust controller. Drive a real Chromium browser without a Node runtime in your automation path; the measured controller footprint is 28 MiB.
  • Smaller controller footprint. In the current local runs, Lightwright used 3.5x to 4.1x less controller memory than Playwright.
  • Fast simple navigation average. On the aligned cold-page run, Lightwright averaged 170 ms versus Playwright's 197 ms. Read the p95 before treating that as a general win.
  • Measured multi-context progress. Lazy CDP initialization cut Lightwright's own two-context/four-page average from 934 ms to 672 ms in repeated local runs.
  • Isolated contexts. Cookies and web storage stay scoped to their BrowserContext.
  • Explicit resource control. Choose memory modes, block resource classes, and enforce browser-tree memory budgets.
  • Small operational surface. Launch, pages, contexts, locators, screenshots, storage, and a practical CLI.
  • Measured, reproducible benchmarks. Timing and memory runs are separate, use the same browser executable, and report variability.

Best current KPIs

KPI Lightwright Reference What it shows
Controller memory, simple page 28 MiB Playwright: 116 MiB 4.1x smaller controller footprint in this local pass
Controller memory, 2 contexts / 4 pages 28 MiB Playwright: 98 MiB 3.5x smaller controller footprint in this local pass
Simple cold navigation average 170 ms Playwright: 197 ms 14% lower average; p95 remains less stable
Multi-context navigation, before/after 934 -> 672 ms Lightwright baseline 28% lower after lazy CDP initialization

These are controlled local measurements with Chrome for Testing 149.0.7827.55, not universal performance guarantees. Lightwright does not currently win on Chromium-tree memory, multi-context absolute latency, or reused-browser latency.

Quick start

cargo fmt --all -- --check
cargo test

cargo run -p lightwright-cli -- open `
  "data:text/html,<title>Lightwright</title><h1>Hello</h1>" `
  --memory ultra-low
use lightwright_core::{Browser, LaunchOptions, MemoryMode};

#[tokio::main]
async fn main() -> lightwright_core::Result<()> {
    let browser = Browser::launch(
        LaunchOptions::new()
            .memory_mode(MemoryMode::UltraLow)
            .max_memory_mb(350),
    )
    .await?;

    let page = browser.new_page().await?;
    page.goto("data:text/html,<title>LW</title><h1>Hello</h1>")
        .await?;
    println!("{}", page.title().await?);

    browser.close().await
}

What you can use today

Area Included in v0.1.0-alpha.1
Browser lifecycle Chrome, Edge, and Chromium detection on Windows; executable override; headless launch; temporary profiles
Automation Browser, isolated BrowserContext, Page, locators, navigation, evaluation, actions, screenshots, cookies, and storage
CDP Sessions, request IDs, events, response correlation, timeouts, and safe concurrent commands
Resource control Memory modes, resource profiles, explicit URL/resource blocking, headers, viewport, and user-agent overrides
Operations Browser-process-tree memory measurement, budget actions, local fixtures, benchmark harness, and CLI

Still out of scope: Firefox, WebKit, Playwright compatibility, a test runner, video/tracing, and native Node bindings. The Node package is a private type-shape preview only.

Performance snapshot

The following local measurements use Chrome for Testing 149.0.7827.55 (Playwright Chromium 1228), headless mode, a 1280x720 viewport, and the same data: page. Timing runs have no memory sampler. Lower is better.

xychart-beta
    title "Average navigation time (ms) - lower is better"
    x-axis ["Simple cold", "2 contexts / 4 pages", "Simple reuse"]
    y-axis "Milliseconds" 0 --> 1000
    bar "Lightwright" [170, 672, 151]
    bar "Playwright" [197, 380, 108]
Loading
Scenario Lightwright Playwright Notes
Simple page, cold browser 170 ms navigation 197 ms navigation 20 measured runs each; Lightwright had a wider p95 in this pass
Two contexts, four pages, cold browser 672 ms navigation 380 ms navigation 20 measured runs each; isolated-context creation remains the main gap
Simple page, reused browser 151 ms navigation 108 ms navigation 100 measured runs each

Lightwright now initializes Network only when a page needs headers, user-agent overrides, cookies, cache actions, or resource blocking. In the multi-context workload this reduced average navigation from 934 ms to 672 ms in a repeated 20-run local comparison. Results are machine-specific measurements, not performance guarantees.

Browser-tree memory

Memory is measured in a separate five-run pass after navigation. It includes the launched Chromium root process and all of its descendants; controller memory is deliberately reported separately.

xychart-beta
    title "Chromium browser-tree memory after navigation (MiB)"
    x-axis ["Simple page", "2 contexts / 4 pages"]
    y-axis "MiB" 0 --> 750
    bar "Lightwright" [455, 675]
    bar "Playwright" [349, 525]
Loading
Scenario Lightwright controller Lightwright Chromium tree Playwright controller Playwright Chromium tree
Simple page 28 MiB 455 MiB 116 MiB 349 MiB
Two contexts, four pages 28 MiB 675 MiB 98 MiB 525 MiB

The controller is materially smaller, while Chromium itself is still larger than Playwright's in these workloads. See the viability report for protocol details, history, and limitations.

Control browser resources

Choose a memory mode for the browser process:

Mode Intended use
default Safe Chromium defaults
low Reduce background work while retaining normal browser behavior
ultra-low Prefer minimal browser footprint; disables GPU and image loading
agent Agent-oriented defaults that preserve screenshots and accessibility work
scraper Extraction-oriented defaults
test Closer to ordinary Chromium behavior

Add a resource profile when the workload does not need every asset:

cargo run -p lightwright-cli -- inspect "data:text/html,<title>LW</title><h1>Hello</h1>" `
  --memory ultra-low `
  --profile text-only `
  --max-memory-mb 350 `
  --on-memory-pressure close-idle-pages

Available profiles: default, low, ultra-low, scraper, agent, form, visual, and text-only.

Useful CLI options:

--memory default|low|ultra-low|agent|scraper|test
--profile default|low|ultra-low|scraper|agent|form|visual|text-only
--headless true|false
--browser-path <path>
--viewport 1280x720
--user-agent "..."
--header "Name: Value"
--block image,font,media,stylesheet
--max-memory-mb <mb>
--on-memory-pressure warn|clear-cache|close-idle-pages|fail-fast

Context isolation and budgets

Browser::new_context(...).await maps to Chromium's isolated browser contexts. Cookies and web storage do not cross context boundaries; closing a context closes its pages and disposes its Chromium context.

Browser::memory_usage() reports resident memory for the Chromium root process and its descendants. For a remote browser, it returns None because Lightwright does not own that process tree. When a configured budget is exceeded, enforce_memory_budget() can warn, clear the browser cache, close idle pages, or fail fast.

Benchmark it fairly

Use the same local fixture, browser executable, headless mode, viewport, workload, warmups, and run count for both tools. Run timing and memory separately.

# Terminal 1: local fixture server
cargo run -p lightwright-cli -- fixture-server --port 0

# Terminal 2: Lightwright timing pass
cargo run -p lightwright-bench -- `
  --url "http://127.0.0.1:PORT/simple" `
  --browser-path "C:\\path\\to\\chrome.exe" `
  --runs 20 --warmup-runs 3 `
  --pages 2 --contexts 2 --concurrency 4 `
  --viewport 1280x720 `
  --measure-memory false --json

# Separate memory pass
cargo run -p lightwright-bench -- `
  --url "http://127.0.0.1:PORT/simple" `
  --browser-path "C:\\path\\to\\chrome.exe" `
  --runs 5 --warmup-runs 1 `
  --pages 2 --contexts 2 --concurrency 4 `
  --viewport 1280x720 `
  --measure-memory true --json

For the matching Playwright harness and the full comparison rules, see Benchmark comparison and Benchmarks.

Documentation

License

MIT

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages