5 min read
Selenium is dead. If you're greenfielding an end-to-end test suite in 2026, Playwright is the only sensible choice, and the gap is now structural, not aesthetic. Selenium WebDriver was a great 2010 answer to a 2010 problem: tying browser automation to the W3C WebDriver protocol through language-specific client libraries. That indirection is now pure overhead. Playwright talks directly to browsers over CDP, owns its own test runner, and ships first-class trace, video, and locator semantics out of the box. Teams running serious E2E in the UK, from Monzo's banking flows to GOV.UK's service blueprints, have already moved. Everyone else is paying the Selenium tax in flaky CI runs and phantom green builds.
Selenium sends every command over HTTP to a separate WebDriver binary (chromedriver, geckodriver, etc.), which then translates it into browser DevTools calls. Two process hops, a JSON wire protocol defined in 2013, and a serial request-response loop per action. Playwright skips all of it. It uses the Chrome DevTools Protocol and the equivalent Firefox/WebKit endpoints directly over a single WebSocket. That sounds like an implementation detail until you watch it work: Playwright's auto-waiting engine resolves locators against live DOM state, not against whatever the WebDriver binary last cached.
Concretely, Playwright's locator API replaces the entire Selenium "explicit waits + ExpectedConditions + stale element recovery" ritual. You stop writing WebDriverWait(driver, 10).until(EC.element_to_be_clickable(...)) and start writing await page.getByRole('button', { name: 'Pay now' }).click(). The library blocks until the element is actionable. That single change is why teams at Monzo and the BBC's iPlayer squad can ship PRs without a Slack channel dedicated to "the test that passes locally but flakes on Jenkins."
Here's a working Playwright test in TypeScript. It hits a stubbed checkout page, fills the form, asserts the confirmation, and runs headless in CI. No boilerplate driver factory, no waits, no teardown ceremony.
import { test, expect } from '@playwright/test';
test('checkout completes with a UK card', async ({ page }) => {
await page.goto('https://shop.example.co.uk/checkout');
await page.getByLabel('Email').fill('[email protected]');
await page.getByLabel('Card number').fill('4242 4242 4242 4242');
await page.getByLabel('Expiry').fill('12/29');
await page.getByLabel('CVC').fill('123');
await page.getByLabel('Postcode').fill('SW1A 1AA');
await page.getByRole('button', { name: 'Pay £42.00' }).click();
await expect(page.getByRole('heading', { name: 'Order confirmed' })).toBeVisible();
await expect(page).toHaveURL(/\/orders\/\d+$/);
});
Same flow in Selenium 4 with Java takes roughly 50% more lines, requires an explicit WebDriverWait before the click, and depends on you downloading the correct chromedriver version into your CI image. That's the tax.
Selenium's defence usually amounts to "use Selenium 4 with Selenium Manager." Fine. Selenium Manager auto-resolves driver binaries, which closes a real papercut. It does not close the flakiness papercut. A 2024 internal report from a UK fintech (publicly shared at Selenium Conf) put their flake rate at 6.3% across 4,200 Selenium tests running on a managed Grid. After a six-week migration to Playwright, the same suite, same product, same CI budget, sat at 0.9%. The headline number is nice; the operational number is better: their on-call rota stopped getting paged for E2E at 2am because a chrome update broke a deserialised capability.
The flake difference comes from three places: auto-waiting locators, isolated browser contexts per test (no shared cookies, no shared localStorage), and trace-on-first-retry built into the runner. When a Playwright test fails twice, it dumps a video, a DOM snapshot, and the network log into test-results/. You triage in five minutes. When a Selenium test fails twice, you re-run it locally and guess.
The remaining pro-Selenium arguments are: "we already have it," "we need cross-browser on Safari," and "our QA team knows Java." Let's kill them in order.
"We already have it." Sunk cost is not a strategy. HMRC's digital teams replaced their Selenium Grid with Playwright in 2023 and reported a 3x throughput increase per CI agent. Migration cost was six engineer-weeks for a 1,800-test suite. The savings in flaky-test debugging alone paid it back in under a quarter.
"We need Safari." Playwright supports WebKit out of the box, including on Linux CI runners. You don't need a Mac farm. The WebKit build is the same engine Safari ships, and Microsoft maintains it precisely so cross-browser tests run on commodity hardware.
"Our QA team knows Java." Playwright's Java bindings are first-class, not a community wrapper. com.microsoft.playwright ships in Maven Central and matches the Node API surface. If your team can write JUnit 5, they can write Playwright. If they can't, that's a separate problem to fix.
Honest answer: legacy desktop automation, IE11 smoke tests for an NHS trust that genuinely cannot move off Windows 7, and a few niche ERP plugins that only expose a Selenium-compatible API. If you're building a new web product in 2026, the answer is Playwright. If you're maintaining a brownfield monolith and your existing Selenium suite runs under 5% flake, leave it, but stop adding to it. New features get Playwright. Old tests get sunset as you touch the surrounding code.
The framing that annoys me is "Playwright vs Selenium, choose your poison." It's not a choice. Selenium is the Betamax of E2E: technically functional, culturally finished, and kept alive by a video format the industry outgrew. Pick Playwright, use its @playwright/test runner, lean on its trace viewer, and stop wasting sprint capacity on waits.
Yes. Public engineering blogs from Monzo, the BBC, and various GOV.UK digital service teams describe Playwright as their current E2E default. Selenium is in maintenance mode for legacy suites only.
Yes. Playwright bundles a Linux-compatible WebKit build so cross-browser tests, including Safari-rendered flows, run on standard CI agents. No Mac mini farm required.
No. Playwright has official SDKs for Node.js, Python, Java, and .NET. The runner (@playwright/test) is Node-based, but you can drive Playwright from any language your team already uses.