Expand description
playwright: High-level Rust bindings for Microsoft Playwright
This crate provides the public API for browser automation using Playwright.
§Quick tour
§Object model
Playwright start here — Playwright::launch().await?
└── BrowserType .chromium() / .firefox() / .webkit()
└── Browser .launch().await? → owns the browser process
└── BrowserContext isolated cookies / storage
└── Page one tab
└── Locator selector with auto-waitLocator is the workhorse. Build one with Page::locator or one
of the semantic helpers (get_by_role, get_by_text, get_by_label,
get_by_placeholder, get_by_test_id, get_by_alt_text,
get_by_title), then call action / assertion methods on it — they
wait for the element to be actionable automatically.
§API conventions
Result<T>everywhere. One error type,Error.- Builders for option-heavy methods.
goto,click,screenshot,tracing.start, etc. take anOptionsstruct (..Default::default()). - Auto-wait by default. Locator-based actions wait until the
element is actionable;
expectassertions auto-retry until the condition holds or times out. You almost never need a manualsleep. - Async/await on
tokio. Every method that does I/O isasync. - Selectors validated at compile time. Prefer the
locator!macro (re-exported when the defaultmacrosfeature is on) over raw&str: empty / malformed selectors fail atcargo build, not at runtime.
§Debugging failures
Fastest path to “what happened” is tracing:
- Wrap the test body with
BrowserContext::tracing—start({ snapshots, screenshots, sources })→ run →stop({ path }). - Open the resulting
.trace.zipwithplaywright show-trace path/to/trace.zip— the trace viewer is language-agnostic, the same UI JS / Python users see. - To inspect a trace programmatically (CI bots, agent feedback
loops), pull in
playwright-rs-traceas a[dev-dependencies].
See examples/trace_on_failure.rs
for the canonical Rust pattern (Rust has no async Drop, so cleanup
is explicit).
§Companion crates
playwright-rs-macros— compile-time-validatedlocator!macro. Default-on via themacrosfeature; surfaced here asplaywright_rs::locator!.playwright-rs-trace— pure-Rust parser for.trace.zipfiles. Standalone; add to[dev-dependencies]for post-mortem analysis.
§For AI coding agents
If you’re using this crate with a coding agent, install the
playwright-rs-usage skill
with npx skills add padamson/playwright-rust. It works with Claude
Code, Codex, Cursor and other skills-compatible agents, and gives the
agent this crate’s API model instead of generic Playwright knowledge.
§Examples
§Basic Navigation and Interaction
use playwright_rs::{Playwright, SelectOption};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let playwright = Playwright::launch().await?;
let browser = playwright.chromium().launch().await?;
let page = browser.new_page().await?;
// Navigate using data URL for self-contained test
let _ = page.goto(
"data:text/html,<html><body>\
<h1 id='title'>Welcome</h1>\
<button id='btn' onclick='this.textContent=\"Clicked\"'>Click me</button>\
</body></html>",
None
).await;
// Query elements with locators
let heading = page.locator("#title");
let text = heading.text_content().await?;
assert_eq!(text, Some("Welcome".to_string()));
// Click button and verify result
let button = page.locator("#btn");
button.click(None).await?;
let button_text = button.text_content().await?;
assert_eq!(button_text, Some("Clicked".to_string()));
browser.close().await?;
Ok(())
}§Form Interaction
use playwright_rs::{Playwright, SelectOption};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let playwright = Playwright::launch().await?;
let browser = playwright.chromium().launch().await?;
let page = browser.new_page().await?;
// Create form with data URL
let _ = page.goto(
"data:text/html,<html><body>\
<input type='text' id='name' />\
<input type='checkbox' id='agree' />\
<select id='country'>\
<option value='us'>USA</option>\
<option value='uk'>UK</option>\
<option value='ca'>Canada</option>\
</select>\
</body></html>",
None
).await;
// Fill text input
let name = page.locator("#name");
name.fill("John Doe", None).await?;
assert_eq!(name.input_value(None).await?, "John Doe");
// Check checkbox
let checkbox = page.locator("#agree");
checkbox.set_checked(true, None).await?;
assert!(checkbox.is_checked().await?);
// Select option
let select = page.locator("#country");
select.select_option("uk", None).await?;
assert_eq!(select.input_value(None).await?, "uk");
browser.close().await?;
Ok(())
}§Element Screenshots
use playwright_rs::Playwright;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let playwright = Playwright::launch().await?;
let browser = playwright.chromium().launch().await?;
let page = browser.new_page().await?;
// Create element to screenshot
let _ = page.goto(
"data:text/html,<html><body>\
<div id='box' style='width:100px;height:100px;background:blue'></div>\
</body></html>",
None
).await;
// Take screenshot of specific element
let element = page.locator("#box");
let screenshot = element.screenshot(None).await?;
assert!(!screenshot.is_empty());
browser.close().await?;
Ok(())
}§Assertions (expect API)
use playwright_rs::{expect, Playwright};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let playwright = Playwright::launch().await?;
let browser = playwright.chromium().launch().await?;
let page = browser.new_page().await?;
let _ = page.goto(
"data:text/html,<html><body>\
<button id='enabled'>Enabled</button>\
<button id='disabled' disabled>Disabled</button>\
<input type='checkbox' id='checked' checked />\
</body></html>",
None
).await;
// Assert button states with auto-retry
let enabled_btn = page.locator("#enabled");
expect(enabled_btn.clone()).to_be_enabled().await?;
let disabled_btn = page.locator("#disabled");
expect(disabled_btn).to_be_disabled().await?;
// Assert checkbox state
let checkbox = page.locator("#checked");
expect(checkbox).to_be_checked().await?;
browser.close().await?;
Ok(())
}§Observability
Every public async method on the user-facing types
(Browser, BrowserContext, BrowserType, Page, Frame, Locator,
ElementHandle, Tracing, CDPSession, Debugger, Screencast, plus
Request, Response, Dialog, Download, Worker, FileChooser)
is instrumented with the tracing crate. Wire up any
tracing_subscriber and you get spans for free, with cardinality-bounded
identifiers (guid, selector, url, name) and selected
completion-time fields (status, bytes_len, count, version).
Event handlers never run inside the span of the call that registered
them or of the operation that caused the event. Events arrive on the
connection’s read loop, which dispatches each message inside a
trace-level dispatch span. Handler tasks, page-level and
context-level alike, are spawned with Instrument::in_current_span()
and inherit that span and nothing else, so under an info or debug
filter a handler has no parent span. The read loop itself starts with no
span, for a launched browser and one from BrowserType::connect alike,
so it never holds the caller’s span open, and neither do the driver’s
stderr reader and the SIGINT listener. Correlate a handler with the
operation that triggered it by guid or url, not by span parentage.
Levels: top-level user operations (goto, click, fill, screenshot,
pdf, evaluate, tracing.start/stop, browser_type.launch) are at
info; everything else is at debug. Span fields never carry input
values, eval expressions or request/response bodies. trace-level
events do: the connection logs every outbound request’s full JSON and
every inbound message, so a trace filter writes fill text, evaluated
expressions and base64 bodies to the log.
use tracing_subscriber::EnvFilter;
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new("playwright_rs=info"))
.init();Re-exports§
pub use protocol::Browser;pub use protocol::BrowserContext;pub use protocol::BrowserType;pub use protocol::ContentOptions;pub use protocol::FrameLocator;pub use protocol::HeaderEntry;pub use protocol::Page;pub use protocol::Playwright;pub use protocol::Response;pub use protocol::Selectors;pub use protocol::Keyboard;pub use protocol::Mouse;pub use protocol::Touchscreen;pub use protocol::Request;pub use protocol::ResourceTiming;pub use protocol::AriaRole;pub use protocol::AriaSnapshotMode;pub use protocol::AriaSnapshotOptions;pub use protocol::BoundingBox;pub use protocol::ElementHandle;pub use protocol::FilterOptions;pub use protocol::GetByRoleOptions;pub use protocol::HighlightOptions;pub use protocol::JSHandle;pub use protocol::Locator;pub use protocol::GotoOptions;pub use protocol::WaitUntil;pub use protocol::CheckOptions;pub use protocol::ClickOptions;pub use protocol::DragToOptions;pub use protocol::DropOptions;pub use protocol::DropOptionsBuilder;pub use protocol::FillOptions;pub use protocol::HoverOptions;pub use protocol::PressOptions;pub use protocol::PressSequentiallyOptions;pub use protocol::Scroll;pub use protocol::SelectOptions;pub use protocol::TapOptions;pub use protocol::WaitForOptions;pub use protocol::WaitForState;pub use protocol::Position;pub use protocol::FilePayload;pub use protocol::SelectOption;pub use protocol::Animations;pub use protocol::Caret;pub use protocol::Scale;pub use protocol::ScreenshotClip;pub use protocol::ScreenshotOptions;pub use protocol::ScreenshotType;pub use protocol::ActionCursor;pub use protocol::ActionPosition;pub use protocol::ChapterOptions;pub use protocol::OverlayId;pub use protocol::Screencast;pub use protocol::ScreencastFrame;pub use protocol::ScreencastSize;pub use protocol::ScreencastStartOptions;pub use protocol::ShowActionsOptions;pub use protocol::ShowActionsStyle;pub use protocol::ShowOverlayOptions;pub use protocol::WebStorage;pub use protocol::WebStorageKind;pub use protocol::WebMCP;pub use protocol::WebMCPOptions;pub use protocol::WebMCPTool;pub use protocol::WebMCPToolAnnotations;pub use protocol::Credentials;pub use protocol::CredentialsCreateOptions;pub use protocol::CredentialsGetOptions;pub use protocol::VirtualCredential;pub use protocol::AddScriptTagOptions;pub use protocol::ColorScheme;pub use protocol::EmulateMediaOptions;pub use protocol::ForcedColors;pub use protocol::Media;pub use protocol::PdfMargin;pub use protocol::PdfOptions;pub use protocol::ReducedMotion;pub use protocol::BrowserContextOptions;pub use protocol::Cookie;pub use protocol::Geolocation;pub use protocol::HttpCredentials;pub use protocol::HttpCredentialsSend;pub use protocol::LocalStorageItem;pub use protocol::Origin;pub use protocol::RecordHar;pub use protocol::RecordVideo;pub use protocol::StorageState;pub use protocol::StorageStateOptions;pub use protocol::Viewport;pub use protocol::HarContent;pub use protocol::HarMode;pub use protocol::StartHarOptions;pub use protocol::TraceSnapshots;pub use protocol::Tracing;pub use protocol::TracingStartOptions;pub use protocol::TracingStopOptions;pub use protocol::EventWaiter;pub use protocol::EventValue;pub use protocol::ConsoleMessage;pub use protocol::ConsoleMessageLocation;pub use protocol::DeviceDescriptor;pub use protocol::DeviceViewport;pub use protocol::WebError;pub use protocol::WebErrorLocation;pub use protocol::WebSocketRoute;pub use protocol::WebSocketRouteCloseOptions;pub use protocol::FileChooser;pub use protocol::Accessibility;pub use protocol::AccessibilitySnapshotOptions;pub use protocol::CSSCoverageEntry;pub use protocol::Coverage;pub use protocol::CoverageRange;pub use protocol::JSCoverageEntry;pub use protocol::JSCoverageRange;pub use protocol::JSFunctionCoverage;pub use protocol::StartCSSCoverageOptions;pub use protocol::StartJSCoverageOptions;pub use protocol::Clock;pub use protocol::ClockInstallOptions;pub use protocol::Video;pub use protocol::FetchOptions;pub use protocol::FetchResponse;pub use protocol::FulfillOptions;pub use protocol::Route;pub use protocol::UnrouteBehavior;pub use protocol::APIRequest;pub use protocol::APIRequestContext;pub use protocol::APIRequestContextOptions;pub use protocol::APIResponse;pub use api::ConnectOverCdpOptions;pub use api::LaunchOptions;
Modules§
Macros§
- locator
- Compile-time-validated Playwright selector. Expands to a
&'static strcontaining the same selector verbatim, with the validation a one-time compile-time check.
Structs§
- Page
Expectation - Page-level expectation for screenshot assertions.
Enums§
- Error
- Errors that can occur when using playwright-core
Constants§
- DEFAULT_
LAUNCH_ TIMEOUT_ MS - Default timeout in milliseconds for starting a browser:
launch,launch_persistent_context, andconnect_over_cdp. - DEFAULT_
TIMEOUT_ MS - Default timeout in milliseconds for Playwright operations.
- PLAYWRIGHT_
VERSION - Playwright server version bundled with this crate.
Functions§
- expect
- Creates an expectation for a locator with auto-retry behavior.
- expect_
page - Creates a page-level expectation for screenshot assertions.
- install_
browsers - Install Playwright browsers programmatically.
- install_
browsers_ with_ deps - Install Playwright browsers and their system dependencies.
Type Aliases§
- Result
- Result type alias for playwright-core operations