Playwright vs. Selenium
Compare Playwright and Selenium on protocol, waiting behaviour, browser coverage, isolation and speed, and see which one fits new work versus an existing suite.
Both drive real browsers, and both can do essentially the same jobs. The difference is how much the library does for you and what it costs to run at scale. Almost every practical decision between them comes down to one question β who is responsible for waiting.
1. The Protocol Difference
Selenium speaks W3C WebDriver: your script sends an HTTP request to a driver process, the driver translates it for its browser, and the response comes back. Every command is a round trip through a separate process.
Playwright speaks the browser's own debugging protocol over a persistent WebSocket β CDP for Chromium, and native protocols for Firefox and WebKit. One connection stays open, and commands stream over it.
That is the origin of the speed gap. It is not that WebDriver is badly implemented; it is that a per-command HTTP round trip through a driver binary costs more than a message on an open socket. In a suite with thousands of commands, the difference compounds.
The trade-off runs the other way too: WebDriver is a standard, so any browser vendor can implement it. Playwright's coverage is whatever Microsoft ships bindings for.
2. Waiting β The Difference That Actually Matters
Selenium does not wait unless you tell it to:
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#submit"))
).click()
Playwright waits automatically:
page.click("#submit")
Before that click fires, Playwright checks the element is attached, visible, stable, enabled, and actually receiving pointer events β then acts, retrying until a timeout.
This is the single largest practical difference. Most flaky Selenium suites are flaky for one reason: someone reached for time.sleep(2) instead of an explicit wait, and two seconds is enough on a laptop and not enough in CI. Auto-waiting removes the failure class structurally rather than asking every engineer to remember the discipline.
If your suite is full of fixed sleeps, that is the symptom, and it is a bigger win than any benchmark.
3. Side by Side
| Selenium | Playwright | |
|---|---|---|
| First released | 2004 | 2020 |
| Protocol | W3C WebDriver over HTTP | CDP / native over WebSocket |
| Standardised | Yes | No |
| Browsers | Chrome, Firefox, Edge, real Safari, others | Chromium, Firefox, WebKit |
| Languages | Java, Python, C#, Ruby, JS, more | JS/TS, Python, Java, .NET |
| Auto-waiting | No | Yes |
| Network interception | Limited (CDP in v4, Chromium only) | First-class, all browsers |
| Isolation | New browser session per test | Browser contexts, milliseconds to create |
| Test runner | Bring your own | Included |
| Debug tooling | Third-party | Trace viewer, codegen, inspector |
| Distributed execution | Selenium Grid, mature | Sharding, or your own infrastructure |
| Ecosystem age | Two decades | Newer, growing fast |
4. Isolation and Cost per Test
Selenium isolates tests by starting a new browser session, which means a new browser process β hundreds of milliseconds to seconds each time.
Playwright reuses one browser and creates a browser context per test: a separate cookie jar, storage and cache inside the same process, created in milliseconds. Contexts are cheap enough that per-test isolation stops being a cost decision.
At ten tests this is invisible. At two thousand, it is the difference between a suite you run on every commit and one you run nightly.
5. Where Selenium Still Wins
- Real Safari. Playwright's WebKit shares Safari's rendering engine but is not Safari β it lacks Safari's own application layer, and Safari-specific bugs hide in that gap. If you must certify Safari, Selenium is the answer and the discussion ends there.
- Language coverage. Ruby, PHP, Perl and others have mature Selenium bindings and no Playwright equivalent.
- An existing Grid. Migrating a large working suite rarely pays for itself.
- Standards alignment. Some organisations prefer a specified protocol over a vendor library, and that is a legitimate architectural position rather than nostalgia.
- Unusual browsers. Anything shipping a conforming WebDriver implementation is reachable.
6. Where Playwright Wins
- New projects without a Safari requirement β lower friction from the first day.
- Flaky suites, for the auto-waiting reason above.
- Network-dependent testing β mocking responses, blocking analytics, asserting on requests, all built in and consistent across browsers.
- Debugging, where the trace viewer gives a recorded timeline with DOM snapshots per step rather than a stack trace and a screenshot.
- Scraping workloads, where cheap contexts and request interception matter more than standards conformance.
7. Real-World Examples
- A suite with 40
sleep()calls migrating to Playwright typically deletes all of them, and the CI failure rate drops without any test logic changing. - A team certifying Safari keeps Selenium for that matrix and runs Playwright day to day β a sensible split, not a compromise.
- A scraper needing to block images and fonts does it in one line of Playwright routing; the Selenium equivalent means CDP calls that only work on Chromium.
- A 3,000-test suite moving from sessions to contexts often halves wall-clock time before any parallelism is tuned.
8. Summary
Playwright is faster, waits for you, intercepts network traffic across all three engines, isolates tests cheaply, and ships a runner and a trace viewer. For new work, it is the lower-friction choice.
Selenium is the W3C standard with the broadest browser and language coverage, real Safari, and two decades of tooling and expertise around it. It is not obsolete β it is less batteries-included, which is a different claim.
Choose Selenium when you need real Safari, an unusual language, or you already have a working Grid. Choose Playwright otherwise. Running both, with Selenium confined to the Safari matrix, is a perfectly ordinary setup.