"Which framework should I learn?" is the most common question in QA automation, and most answers age badly. Articles written in 2022 still say Selenium makes you download drivers by hand. That stopped being true.
This compares the three tools as they are now, in 2026. Same test in all three, an honest table, and a clear recommendation at the end.
The short answer
If you have two minutes, here it is.
| You are... | Learn |
|---|---|
| New to automation, choosing today | Playwright |
| Working on a team that already uses Cypress | Cypress, and stay |
| Targeting enterprise or Java roles | Selenium |
| Testing Safari, multiple tabs or several domains | Playwright |
| Testing components as well as pages | Cypress |
| Automating old browsers or a legacy stack | Selenium |
None of these is a bad tool. They lost the "which is best" argument years ago and became three reasonable answers to different questions.
How each one actually works
The architecture explains almost every difference that follows, so it is worth thirty seconds.
Selenium talks to a browser driver over the WebDriver protocol, a W3C standard. Your test is a normal program in any language. It sends commands, the driver executes them, and results come back.
Cypress runs your test inside the browser, in the same event loop as the app. That is unusual and it is the source of both its best feature and its main limits.
Playwright drives the browser from outside over a websocket connection, similar in spirit to Selenium but with a faster, richer protocol.
The practical result:
- Cypress can reach directly into your application, stub network calls and inspect state, because it lives there. It also inherits the browser's rules about tabs and origins.
- Playwright and Selenium sit outside, so multiple tabs, multiple origins and downloads are ordinary operations.
The same test in all three
One scenario: add a product to the cart, then check the badge says 1.
Playwright
import { test, expect } from '@playwright/test';
test('adds a product to the cart', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Add to cart' }).first().click();
await expect(page.getByTestId('cart-count')).toHaveText('1');
});
Cypress
describe('Cart', () => {
it('adds a product to the cart', () => {
cy.visit('/');
cy.get('[data-testid="add-to-cart"]').first().click();
cy.get('[data-testid="cart-count"]').should('have.text', '1');
});
});
Selenium (JavaScript)
const { Builder, By, until } = require('selenium-webdriver');
const driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://localhost:3000/');
await driver.findElement(By.css('[data-testid="add-to-cart"]')).click();
const badge = await driver.wait(
until.elementLocated(By.css('[data-testid="cart-count"]')),
5000,
);
await driver.wait(until.elementTextIs(badge, '1'), 5000);
Three things stand out.
Playwright uses plain async/await. If you know JavaScript, you know the control flow.
Cypress uses a command chain. cy commands are queued and run in order. You do not await them. This confuses people who arrive from Playwright and try to await cy.get(...).
Selenium is more explicit. You build a driver, you manage waits, you clean up. That verbosity is also why it fits into any language and any test runner.
The comparison table
| Topic | Playwright | Cypress | Selenium |
|---|---|---|---|
| Runs | Outside the browser | Inside the browser | Outside, via WebDriver |
| Style | async/await | command chain | explicit, language native |
| Languages | JS/TS, Python, Java, C# | JS/TS only | Java, Python, C#, JS, Ruby, Kotlin |
| Chromium | Yes | Yes | Yes |
| Firefox | Yes | Yes | Yes |
| WebKit / Safari | Yes, WebKit engine | Experimental | Yes, real Safari on macOS |
| Multiple tabs | Yes | Limited | Yes |
| Multiple origins | Yes | Via cy.origin() |
Yes |
| Auto-waiting | Yes | Yes | No, you write waits |
| Parallel runs | Free, built in | Free locally, orchestration is paid | Via Grid or a third party |
| Component testing | No | Yes | No |
| Debugging | Trace viewer, UI mode | Time-travel runner | Standard debugger |
| Mobile web emulation | Yes | No | Limited |
| Age | 2020 | 2017 | 2004 |
Browser support, honestly
This is where marketing pages tend to blur things.
Playwright bundles its own builds of Chromium, Firefox and WebKit. You get Safari's engine on Windows and Linux, which is genuinely useful. It is not literally Safari, so a Safari-specific bug can still slip through.
Cypress supports Chrome-family browsers and Firefox properly. WebKit support is, in Cypress's own words, experimental, and their documentation notes it is built on Playwright's WebKit. Cypress does not drive Safari itself.
Selenium is the only one that drives real Safari, through Apple's own SafariDriver, on a real Mac. If your contract says "must work in Safari" and you mean the actual browser, this matters.
Languages
If your team writes Java, this decides it. Selenium has the deepest Java support of the three by a wide margin, and most enterprise QA job posts still name it.
Playwright covers JavaScript, TypeScript, Python, Java and C#. The JavaScript version leads and the others follow behind it.
Cypress is JavaScript and TypeScript only. That is fine if your team is front-end, and a hard stop if it is not.
Speed
Playwright is usually fastest, and the reasons are structural. It reuses one browser process and gives each test a fresh context rather than a fresh browser, and it runs tests in parallel out of the box.
Cypress is fast for a single spec and slower across a large suite, because parallel orchestration across machines is a Cypress Cloud feature rather than something the open-source runner does for you.
Selenium's speed depends almost entirely on how you set it up. A well-tuned Grid is fast. A badly configured one is very slow.
One caveat worth saying plainly: benchmark numbers in vendor blog posts are close to worthless. They compare a tuned version of their tool against a naive version of the other. Your suite's speed will be decided by how much you log in through the UI, how much test data you create, and how well you parallelise, not by the framework's own overhead.
Waiting and flakiness
This is the biggest day-to-day difference.
Playwright and Cypress both wait automatically. Before a click, Playwright checks that the element is attached, visible, stable and enabled. Cypress retries commands and assertions until they pass or time out.
Selenium does not wait for you. You write explicit waits yourself:
await driver.wait(until.elementIsVisible(el), 5000);
That is more code and more chances to get it wrong, and it is why so many older Selenium suites are full of Thread.sleep. It is also why Selenium tests can be more precise once you know what you are doing, because nothing is waiting behind your back.
No framework prevents flaky tests. Bad selectors and shared data make any of the three unreliable. Fixing flaky tests covers the causes that apply to all three.
Debugging
Cypress has the best interactive experience of the three. The runner shows each command, and hovering a step snaps the app back to that moment. For learning, it is excellent.
Playwright wins on debugging failures you cannot reproduce. Turn on tracing and a failed run gives you DOM snapshots before and after every action, the network log and a console log, all viewable offline. That is the tool you want when a test only fails in CI. UI mode covers the interactive side.
Selenium has no equivalent built in. You use your language's debugger, screenshots, and whatever your reporting stack provides.
Cost
All three are free and open source. The money question is orchestration.
- Playwright parallelises across workers on one machine for free, and sharding across CI machines is configuration, not a purchase.
- Cypress runs in parallel locally for free. Splitting a suite across CI machines with balanced timing and merged reports is Cypress Cloud, which is paid above a free tier.
- Selenium Grid is free to run and costs your team's time to maintain, which is rarely zero. Hosted grids are paid.
What changed recently, and what most articles get wrong
Three things are commonly out of date in comparisons you will read.
Selenium no longer makes you manage drivers. Selenium Manager, now built in, downloads and matches the right driver for you. The "you have to download ChromeDriver and keep it in sync" complaint is a decade old and no longer true. If you still hit a version mismatch, this guide explains it.
Selenium has WebDriver BiDi. BiDi is a W3C bidirectional protocol, and it gives Selenium the things it used to lack: network interception, request mocking, console capture and JavaScript error listening, as a cross-browser standard rather than a Chrome-only hack. Recent Selenium releases have been rolling this out across the language bindings. It closes a real part of the gap.
Cypress can cross origins. cy.origin() exists, so the flat "Cypress cannot test more than one domain" claim is wrong. It is more work than in Playwright, but it is possible.
Anyone comparing 2026 Selenium to a 2019 memory of Selenium will reach the wrong answer.
Which should you learn first?
Learn Playwright, unless you have a specific reason not to.
The reasoning is practical rather than tribal. The syntax is ordinary JavaScript, so you are learning testing rather than a dialect. Auto-waiting removes the single biggest source of beginner frustration. Demand has grown quickly. And the concepts transfer: locators, waiting, assertions and test isolation are the same ideas in all three tools.
Two honest exceptions. If you are targeting Java-heavy enterprise roles, learn Selenium, because that is what those job posts ask for. If you are joining a team that already runs Cypress, learn Cypress, because the tool your team uses beats the tool an article recommends.
Which should your team use?
Different question, different answer, because the cost of switching is real.
Stay where you are unless you are hitting a limit you can name. "Playwright is more modern" is not a limit. "Our checkout flow redirects to a payment provider and we cannot test it" is.
Move to Playwright if you need real Safari-engine coverage, multi-tab or multi-domain flows, parallel CI without a subscription, or tests in Python, Java or C#.
Stay on Cypress if your app is a single-page app on one domain and your team values the interactive runner. It is still an excellent tool, and component testing has no equivalent in the other two.
Stay on Selenium if you have a large existing suite, a Java or C# team, or a requirement for real Safari or older browsers. Modern Selenium with Manager and BiDi is a very different tool from the one people remember.
If you are considering a move, Selenium to Playwright covers whether it is worth it and how to do it in stages, and Cypress to Playwright is a command-by-command translation.
Frequently asked questions
Is Selenium dead? No. It is the only one that drives real Safari, it has the widest language support, and it still appears in more job posts than the other two in many regions. It has also changed a lot recently, with Selenium Manager and WebDriver BiDi.
Is Playwright better than Cypress? For multi-tab, multi-origin and Safari-engine testing, yes, clearly. For component testing and interactive debugging, Cypress is stronger. For an ordinary single-page app, either will do the job well.
Which is easiest for a beginner? Cypress and Playwright are close, and both are far easier than Selenium, because they wait for you. Cypress has the friendlier first hour thanks to its runner. Playwright has the more transferable syntax.
Which pays best? Salary tracks seniority and domain far more than framework. Selenium appears in more enterprise postings, Playwright in more recent ones. Knowing the concepts matters more than the tool on your CV.
Can I use more than one? Yes, and larger teams often do. The concepts transfer almost one to one, so a second framework takes days rather than months.
Do any of them test mobile apps? Not natively. All three test web applications. For native iOS and Android, teams use Appium, which is built on the WebDriver protocol Selenium uses.
Remember this
Architecture explains the differences. Cypress runs inside the browser, which buys a great debugger and costs it tabs and origins. Playwright and Selenium drive from outside, so those flows are ordinary.
Learn Playwright first if you are choosing today. Keep what your team already runs unless you can name the limit you are hitting. And do not compare 2026 Selenium to a memory of Selenium from 2019.
The fastest way to feel the difference is to write the same test twice. Open the practice editor, pick a problem, and solve it in two frameworks. The same graded problems work in all three.