Test Automation
Playwright vs Cypress vs Selenium in 2026: How to Choose
Every framework comparison ends with "it depends," which is true and not helpful when you're the one who has to pick. The honest version is that these three tools solve overlapping but not identical problems, and the right choice depends on your stack, your team's language, and how much you actually need cross-browser coverage versus speed.
Playwright: the default for new projects
Playwright auto-waits for elements, runs against Chromium, Firefox, and WebKit from one API, and supports parallel execution out of the box. Its trace viewer records every step of a run, which cuts debugging time on CI failures dramatically compared to reading a stack trace and guessing.
The tradeoff: it's younger than Selenium, so some enterprise tooling and legacy CI integrations haven't caught up yet. For a project starting from scratch in 2026, that's rarely a real blocker.
Cypress: strongest developer experience for JS-heavy teams
Cypress's interactive test runner, watching a test run step by step in a real browser with time-travel through each command, is still the fastest feedback loop for a developer writing a new test. Its automatic retries and built-in waiting solve the same flakiness problems Playwright solves, with a slightly different API shape.
The real limitation is architectural: Cypress runs inside the browser.
Multi-tab testing isn't supported, and a flow that crosses domains has to be
wrapped in cy.origin(), where Playwright handles both natively. For a
JavaScript-first team building a single-page app, that rarely matters. For
testing an OAuth redirect flow across two domains, it does.
Selenium: still the right call in specific cases
Selenium's language bindings cover Java, Python, C#, Ruby, and JavaScript, and it drives browsers through WebDriver, the W3C standard that browser vendors implement themselves. Playwright also supports Python, Java and .NET, so language alone rarely forces the choice anymore. If your CI infrastructure is already built around Selenium Grid, your team writes Ruby, or you need to test in Safari itself rather than a WebKit build, Selenium is still the correct choice, not a legacy fallback.
// Selenium: same API shape across every supported language
const { Builder, By, until } = require("selenium-webdriver");
const driver = await new Builder().forBrowser("chrome").build();
await driver.get("https://example.com");
await driver.wait(until.elementLocated(By.css("[data-cy=submit]")), 5000);
The same wait, three different shapes
The clearest way to see the actual API difference is the same operation in all three: submit a form and wait for the network response before asserting, without a fixed sleep.
// Playwright: wait on the response object itself
const [response] = await Promise.all([
page.waitForResponse((res) => res.url().includes("/api/register")),
page.click("[data-cy=submit]"),
]);
expect(response.status()).toBe(201);
// Cypress: intercept first, alias it, then wait on the alias
cy.intercept("POST", "/api/register").as("register");
cy.get("[data-cy=submit]").click();
cy.wait("@register").its("response.statusCode").should("eq", 201);
// Selenium: the usual pattern is to wait on a DOM effect instead
await driver.findElement(By.css("[data-cy=submit]")).click();
await driver.wait(
until.elementLocated(By.css("[data-cy=success-message]")),
5000
);
That last block is the real practical gap. Playwright and Cypress both let a test assert directly on the network layer in a few lines. Selenium 4 can intercept traffic through the Chrome DevTools Protocol, and the newer WebDriver BiDi protocol is bringing that to other browsers, but the API is lower-level and Chromium-first. In practice most Selenium suites still put a proxy such as mitmproxy in front of the browser, or assert on whatever the UI does once the response lands. It remains one of the main reasons teams migrate off Selenium when API-level assertions become important.
Picked a framework without checking what your team actually needs from it?
The right tool depends on your stack, your team's language, and how much cross-browser coverage you actually need, not which one has the loudest fans. We help teams make that call, and migrate when the old one no longer fits.
Parallelization and CI cost
All three parallelize, but the cost model is different enough to matter for a CI bill.
- Playwright ships built-in sharding (
--shard=1/4) that splits a suite across workers with zero extra infrastructure, and each worker gets an isolated browser context for free. - Cypress parallelizes through Cypress Cloud or a self-hosted queue
(
cypress-parallel,sorry-cypress), which works well but is an added moving part rather than a CLI flag. - Selenium parallelizes through Selenium Grid, a hub-and-node setup that's more infrastructure to run yourself, or a paid grid provider (BrowserStack, Sauce Labs) if you don't want to run it.
For a team without dedicated DevOps time, that ordering (Playwright, then Cypress, then Selenium) is also roughly the ordering of setup cost.
Component testing isn't equally supported
Beyond full end-to-end runs, testing a single UI component in isolation, mounting it with specific props and asserting on its rendered output without spinning up the whole app, is a different capability, and the three tools aren't close on it. Cypress's component testing is the most mature of the three, with first-class runners for React, Vue, Angular, and Svelte. Playwright's component testing exists but is explicitly experimental and covers fewer frameworks. Selenium has no concept of component testing at all. It drives a full browser against a full page, by design. A team planning to lean on component-level coverage, not just end-to-end flows, should weight this more heavily than raw speed benchmarks.
What migrating off Selenium actually costs
The tool comparison usually happens after a team already has a Selenium suite and is asking whether switching is worth it. The honest answer depends on how the suite is structured, not on the tool itself.
- Page Object Model suites migrate cheaply. If locators and actions are already abstracted behind page objects, only the object implementations change. The test logic and assertions stay untouched.
- Suites with inline
Thread.sleep()calls migrate expensively. These need rewriting to auto-waiting patterns anyway, and that rewrite is most of the migration effort. The framework swap itself is the easy part. - Custom WebDriver wrappers are the hidden cost. Years of home-grown retry logic and wait helpers built to compensate for Selenium's lack of auto-waiting don't port over; they get deleted, which is a net win, but finding every place they're called takes time.
Migrating rarely pays for itself on tooling speed alone. It pays off when the existing suite's maintenance burden, mostly from manual wait handling, is already high enough that the rewrite cost is smaller than another year of that burden.
Cypress vs Selenium: which is better for testing?
For a JavaScript team testing a modern web app, Cypress is usually the better fit: faster feedback while writing tests, automatic waiting, and network stubbing built in. Selenium is the better choice when tests are written in Java, C#, Python or Ruby, when you need real Safari or a large browser matrix through Selenium Grid, or when a flow spans several tabs.
Playwright vs Selenium
For a new project, Playwright is the stronger default in most cases. It supports JavaScript, TypeScript, Python, Java and .NET, waits automatically, and ships sharding, tracing and network interception without extra infrastructure. Selenium keeps the edge on Ruby support, existing Grid investment and testing in vendor-shipped browsers like Safari, and it is built on a W3C standard rather than one vendor's protocol.
The actual decision framework
- New project in JavaScript, TypeScript, Python, Java or .NET, with real cross-browser coverage: Playwright.
- JavaScript stack, prioritizing debugging speed over multi-tab scenarios: Cypress.
- Existing Selenium Grid infrastructure, a Ruby codebase, or a requirement to test in Safari itself: Selenium.
- Mixed stack across multiple teams: pick one and standardize. The cost of running two frameworks in parallel almost always exceeds the cost of a suboptimal single choice.
We build and migrate test automation suites in all three, and the migration conversation is usually less about which tool is "best" and more about which one matches the team that has to maintain it for the next two years. If the bigger question is how much framework to build around the tool, see choosing a test automation framework. For a worked example of stable Cypress tests, see testing HTML tables in Cypress.