Rust language bindings for Microsoft Playwright — the industry standard for cross-browser end-to-end testing.
Status: Pre-1.0, API stabilizing. See coverage for the path to v1.0.
This README describes the latest published release on crates.io. For changes on
mainthat haven't been released yet (new features, breaking changes, bug fixes), seecrates/playwright/CHANGELOG.mdunder[Unreleased].
Read our WHY.md to understand the vision, timing, and philosophy behind this project.
TL;DR: Rust is emerging as a serious web development language, with frameworks like Axum and Actix gaining traction. AI coding assistants are making Rust accessible to more developers. Test-Driven Development is experiencing a renaissance as the optimal way to work with AI agents. These trends are converging now, and they need production-quality E2E testing. playwright-rust fills that gap by bringing Playwright's industry-leading browser automation to the Rust ecosystem.
See Development Roadmap for plans and status of the development approach for playwright-rust.
Goal: Build this library to a production-quality state for broad adoption as @playwright/rust or playwright-rs. Provide official-quality Rust bindings for Microsoft Playwright, following the same architecture as playwright-python, playwright-java, and playwright-dotnet.
The API matches Playwright's cross-language conventions — if you know playwright-python, you know playwright-rust:
| Python | Rust |
|---|---|
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
# Locator with auto-waiting
heading = page.locator("h1")
assert heading.text_content() == "Example Domain"
# Response body access
resp = page.goto("https://api.example.com/data")
data = resp.json()
browser.close() |
use playwright_rs::Playwright;
let pw = Playwright::launch().await?;
let browser = pw.chromium().launch().await?;
let page = browser.new_page().await?;
page.goto("https://example.com", None).await?;
// Locator with auto-waiting
let heading = page.locator("h1").await;
assert_eq!(heading.text_content().await?, Some("Example Domain".into()));
// Response body access
let resp = page.goto("https://api.example.com/data", None).await?.unwrap();
let data: serde_json::Value = resp.json().await?;
browser.close().await?; |
Full Python API parity + agent integration. All Playwright Python
classes and methods are implemented, plus Browser::bind() /
Browser::unbind() (Playwright 1.59) for exposing a Rust-launched browser
to external clients like @playwright/mcp, the Playwright CLI, or
third-party agent tooling.
The remaining path to v1.0 is multi-month dogfooding, API polish, and performance tuning rather than new surface area. See the v1.0 gap analysis for the detailed state of each class.
playwright-rust follows Microsoft's proven architecture for language bindings:
┌──────────────────────────────────────────────┐
│ playwright-rs (Rust API) │
│ - High-level, idiomatic Rust API │
│ - Async/await with tokio │
│ - Type-safe bindings │
└─────────────────────┬────────────────────────┘
│ JSON-RPC over stdio
┌─────────────────────▼────────────────────────┐
│ Playwright Server (Node.js/TypeScript) │
│ - Browser automation logic │
│ - Cross-browser protocol abstraction │
│ - Maintained by Microsoft Playwright team │
└─────────────────────┬────────────────────────┘
│ Native protocols
┌─────────────┼─────────────┐
▼ ▼ ▼
Chromium Firefox WebKit
This means:
- ✅ Full feature parity with Playwright (JS/Python/Java/.NET)
- ✅ Cross-browser support (Chromium, Firefox, WebKit)
- ✅ Automatic updates when Playwright server updates
- ✅ Minimal maintenance - protocols handled by Microsoft's server
- ✅ Production-tested architecture used by millions
Following Playwright's cross-language consistency:
- Match Playwright API exactly - Same method names, same semantics
- Idiomatic Rust - Use Result, async/await, builder patterns where appropriate
- Type safety - Leverage Rust's type system for compile-time safety
- Auto-waiting - Built-in smart waits like other Playwright implementations
- Testing-first - Designed for reliable end-to-end testing
Add to your Cargo.toml:
[dependencies]
playwright-rs = "0.12" # Auto-updates to latest 0.12.x
tokio = { version = "1", features = ["full"] }See the CHANGELOG for version history and features.
Browsers must be installed before use. Install once, then run tests as many times as needed.
# Install all browsers
npx playwright@1.59.1 install
# Or install specific browsers
npx playwright@1.59.1 install chromium firefox webkitIn CI/CD: Add this to your GitHub Actions workflow:
- name: Install Playwright Browsers
run: npx playwright@1.59.1 install chromium firefox webkit --with-depsProgrammatic installation: For setup scripts, Docker images, or tools built on playwright-rs, you can install browsers from Rust code:
use playwright_rs::install_browsers;
install_browsers(None).await?; // all browsers
install_browsers(Some(&["chromium"])).await?; // specific browsersWhy version matters: The library bundles Playwright driver 1.59.1. Each release expects specific browser builds. Using the matching version ensures compatible browsers.
What happens if I don't install browsers? You'll get a helpful error message with the correct install command when trying to launch a browser.
- Rust 1.88+
- Node.js 18+ (for Playwright server and browser installation)
- tokio async runtime
# Clone repository
git clone https://github.com/YOUR_USERNAME/playwright-rust.git
cd playwright-rust
# Install pre-commit hooks
pip install pre-commit
pre-commit install
# Build
cargo buildAfter building, install browsers as described in Browser Installation above:
cargo build
npx playwright@1.59.1 install chromium firefox webkitThe build script automatically downloads the Playwright driver to drivers/ (gitignored). CI handles browser installation automatically - see .github/workflows/test.yml.
Platform Support: ✅ Windows, macOS, Linux
Known limitation: WebKit launch_persistent_context() fails on native
Windows with "Initial load failed" — this is an upstream Playwright issue
(microsoft/playwright#36936,
also tracked as playwright-rust #39).
Microsoft is building a channel: "webkit-wsl" replacement
(microsoft/playwright#37036).
Chromium and Firefox persistent contexts work on all platforms. Non-persistent
WebKit (browser.new_context()) works on Windows. Use WSL or macOS/Linux for
WebKit persistent contexts.
This project uses cargo-nextest. Install once: cargo install cargo-nextest
cargo nextest run # All tests
cargo nextest run -p playwright-rs --lib # Unit tests only (~2s, no browsers)
cargo nextest run -p playwright-rs -E 'test(locator)' # Pattern match
cargo test --doc --workspace -- --ignored # Doc-tests (requires browsers)See examples/ for usage examples.
cargo run --package playwright-rs --example basicSee the source line that failed. When ? propagates an Error out of
your test, you see the message but no Rust source location. Use
anyhow for tests and run with RUST_BACKTRACE=1:
use anyhow::{Context, Result};
#[tokio::test]
async fn my_test() -> Result<()> {
// ...
let content = heading.text_content().await.context("read heading")?;
// ...
Ok(())
}Run as RUST_BACKTRACE=1 cargo nextest run (or cargo test). The backtrace
points at the failing ?, and .context("...") adds breadcrumbs to the
error chain. This matches how playwright-java/dotnet rely on the test
runner's stack trace rather than baking source locations into the library.
Save a Playwright trace when a test fails. Rust has no async Drop,
so trace cleanup is explicit. Capture the test result, then run cleanup
unconditionally and pass the trace path only on failure:
let result = run_test_body(&context).await;
let trace_path = result.is_err().then(|| "trace.zip".to_string());
let _ = tracing.stop(Some(TracingStopOptions { path: trace_path })).await;
let _ = browser.close().await;
result?;See examples/trace_on_failure.rs
for a runnable end-to-end example. Open the resulting trace.zip at
https://trace.playwright.dev.
This project aims for production-quality Rust bindings matching Playwright's standards. Contributions should:
- Follow Playwright API conventions
- Include comprehensive tests
- Maintain type safety
- Document public APIs with examples
- Pass CI checks (fmt, clippy, tests)
Apache-2.0 (same as Microsoft Playwright)
- Microsoft Playwright Team - For the amazing browser automation framework
- playwright-python - API design reference