Coming from Playwright
ferridriver is a Rust-first browser automation stack with a
Playwright-shaped API. If you know Playwright, the Browser / Page /
Locator / Frame / BrowserContext surface is familiar — but
ferridriver is built for Rust projects, and the whole Playwright
toolchain (test runner, BDD, MCP server, codegen, traces) has a native
ferridriver equivalent that runs from one Rust binary with no Node in
the run path.
This page is for two audiences:
- Rust developers who want Playwright's automation and testing model in a Rust codebase.
- Teams replacing a specific Playwright tool —
@playwright/test,playwright-bdd, or@playwright/mcp.
It is not a "port my TypeScript test suite in place" guide:
ferridriver does not run a JS/TS test runner. Tests are written in Rust
(or as Gherkin features). JavaScript / TypeScript shows up in exactly two
places — BDD step bodies, and the @ferridriver/node browser API for
scripts (see the last section).
What replaces what
The browser-call layer is the same idea everywhere; only the host language and the surrounding runner change.
Browser automation in Rust
The core move is from a TypeScript script to an async Rust function.
Selectors, getBy* accessors, Locator chaining, BrowserContext, and
tracing all port over.
What changes: methods are snake_case, calls are awaited and return
Result (use ?), and option bags are structs (LaunchOptions,
RoleOptions, …) defaulted with Default::default() or passed as None.
The selector strings and locator semantics are identical.
Tests: @playwright/test → ferridriver-test
test() / expect() become #[ferritest] plus the Rust expect
matchers — auto-retrying on Playwright's polling schedule.
Fixtures, hooks, projects, retries, sharding, and reporters live in
ferridriver-test. See Test runner and the
expect reference.
BDD: playwright-bdd → ferridriver-bdd
Your .feature files are plain Gherkin — they carry over unchanged.
What changes is the step layer and the runner: ferridriver-bdd parses
Gherkin natively and runs it through the core test runner, so there is no
playwright-bdd codegen step and no Playwright test process.
Write step bodies in Rust:
…or keep them in JavaScript / TypeScript and let ferridriver run them:
JS/TS steps are bundled with rolldown, compiled to QuickJS bytecode, and
executed on the embedded ferridriver-script engine — no Node or Bun
in the run path. See BDD overview.
MCP: @playwright/mcp → ferridriver mcp
Swap the server command in your agent config. ferridriver ships the MCP
server in the same binary — no npx, and you can pick the backend and
transport.
See MCP setup.
Using the browser API from JavaScript / Bun
@ferridriver/node is the browser API only — Browser,
BrowserContext, Page, Frame, Locator, ElementHandle, Route,
and friends, driving the same Rust engine. Reach for it when you want
Playwright's automation API in a Node or Bun script without writing
Rust.
It is not a test runner: there is no test(), expect(), fixtures,
or BDD in this package. For tests, BDD, or the MCP server, use the Rust
crates and the ferridriver CLI described above.
API differences to know
Locator method renames
or and and are Rust keywords, so two locator combinators are renamed
(the NAPI binding uses the same names, so the TS surface matches):
Events return a numeric listener id
Playwright's page.on(...) returns the Page; you remove a listener with
page.off(event, handler). ferridriver returns a numeric id:
Auto-waiting
ferridriver's pre-action actionability matches Playwright: before a click
it waits for the element to be attached, visible, enabled, position-
stable (bounding box unchanged across animation frames), and to
actually receive the event at the click point (no other element
occludes it). force: true skips the checks, same as Playwright.
Backends and browser choice
ferridriver runs four backends behind one API; pick per launch or per test project.
Default is cdp-pipe (Chromium over fd 3/4 pipes). On a protocol-level
issue, try --backend cdp-raw (CDP over WebSocket). The WebKit backend
uses Playwright's WebKit binary (ferridriver install webkit, or an
existing npx playwright install webkit, or FERRIDRIVER_WEBKIT) and
runs on Linux and macOS. Firefox uses WebDriver BiDi and must already be
installed (no bundled binary).
Porting checklist
- Decide what you're replacing — library, test runner, BDD, or MCP — and pick the ferridriver piece from the table above.
- For automation in Rust: translate scripts to
async fnwith?;snake_casemethods; option structs. Selectors are unchanged. - For automation from JS/Bun: install
@ferridriver/nodeand swap theplaywrightimport (browser code is unchanged). Remember it has no test runner. - For tests: move bodies to Rust
#[ferritest]+expect, or to Gherkin features run byferridriver bdd. - Rename
.or()→.orLocator()and.and()→.andLocator(). - Add a
backendto project configs only if you want something other than Chromium-over-pipes.