Backends
ferridriver has four browser backends behind one API. They all speak the
same Browser / Page / Locator surface — switch with a single flag
and every test keeps working.
At a glance
cdp-pipe — the default
Chromium via CDP over Unix pipes (file descriptors 3 and 4). ferridriver launches Chrome itself and wires stdin/stdout-like pipes for the protocol.
Strengths
- Lowest-latency transport — no WebSocket framing, no TCP loopback.
- Deterministic process lifecycle: when the test ends the pipe closes and Chrome exits.
- Fully parallel across tests on the same worker (each worker has its own Chrome).
Limits
- You must let ferridriver launch Chrome. It cannot attach to a running instance.
- The remote-debugging-port flag is ignored; the pipe is the only channel.
Pick this unless you have a specific reason not to.
cdp-raw — attach to a running Chrome
Same CDP protocol over a WebSocket. ferridriver can launch Chrome and
dial its ws://... endpoint, or you can point it at an existing browser.
Use when
- You want to automate a persistent Chrome profile started outside the test runner.
- Your environment does not allow inherited file descriptors (some container setups, some CI runners).
- You want to share one browser across several runners or languages.
Slightly slower than cdp-pipe — WebSocket framing plus a loopback hop
— but the difference is in the low single-digit ms per CDP call and is
usually irrelevant.
webkit — Playwright WebKit (Linux + macOS)
Speaks Playwright's WebKit Inspector protocol over a NUL-byte-delimited
JSON pipe to a pw_run.sh child process. Same code on Linux and macOS.
Strengths
- Real WebKit / JavaScriptCore rendering and JS engine.
- Cross-platform — Linux and macOS (the
--inspector-pipetransport relies on a Unix fork/dup model, so there is no Windows support). - Closes most Playwright feature gaps that a public-API WKWebView build cannot (PDF, video, network interception, per-frame execution context, main-document response, etc.).
Limits
- Requires the Playwright WebKit binary. Download it with
ferridriver install webkit, or provide it viaFERRIDRIVER_WEBKITornpx playwright install webkit. - A few hundred MB on disk per platform.
bidi — Firefox via WebDriver BiDi
Native Firefox driver. ferridriver launches firefox with a fresh
profile and speaks WebDriver BiDi (not Marionette, not CDP) over a
WebSocket.
Strengths
- Real Firefox coverage — rendering, JS engine, HTTP stack are Gecko's.
- Standards-based: the same BiDi protocol Playwright, Selenium 4, and Puppeteer can drive.
Limits
- Firefox must be installed — ferridriver does not bundle it. Set
executable_pathif it is not onPATH. - HAR recording and download interception return
FerriError::Unsupported(BiDi protocol gap).
How browsers relate to backends
Each browser has a sensible default backend, chosen by the Rust factory
you call (chromium() / firefox() / webkit()) or by [[test.projects]]
config:
Chromium also supports cdp-raw (chromium({ transport: 'ws' }) in JS,
BrowserType::chromium_with in Rust). Pairings like Firefox-on-webkit or
WebKit-on-bidi are not valid.
Cross-backend matrix
Then --project firefox runs only that slice. CI typically runs all
three in parallel shards.
Performance notes
Rough CDP round-trip budget per action on a warm machine:
These are transport costs, not test costs. An assertion polling at 100/250/500/1000 ms intervals is dominated by the interval, not the transport.
Picking in practice
- Writing a new suite today: start on
cdp-pipe. Addwebkitandbidiprojects when you need cross-browser coverage. - Debugging a single test:
--backend cdp-pipewith--workers 1— one browser, linear output. (MCP /runlaunch headed by default.) - Attaching to a logged-in profile:
cdp-rawwithchromium().connect(...). - Safari-family regression:
webkit. - Firefox regression:
bidi.