Selenium vs Cypress vs Playwright: Comparing Modern Test Automation Tools

Before any website goes live, I ask one question: will we click through this form, this checkout and this login by hand after every release? If the answer is no, you need to pick between test automation tools. In this guide I compare Selenium, Cypress and Playwright side by side. I show the same test in all three and explain which team fits which tool, based on my own field experience.
What are test automation tools, and how do Selenium, Cypress and Playwright differ?
Test automation tools are programs that control a browser through code and repeat the clicks, typing and navigation of a real user. The core difference is architecture: Selenium drives the browser from outside through the W3C WebDriver protocol, Cypress runs your test inside the browser, and Playwright talks to the browser directly over its own protocol.
On paper this looks like a small detail. In practice it shapes speed, stability, language support and multi-tab behaviour. For example, Cypress supports only JavaScript because its tests live inside the browser. So you should understand the architecture first and read the feature list second.
I cover the role itself, meaning what a test automation engineer does day to day and how the STLC works, in a separate article. Here I focus only on the tools. If the career side interests you, start there and then come back to this comparison.
Why are we still comparing three tools instead of naming one winner?
There is no single winner because each tool was born to solve a different problem. Selenium made browser automation possible in the mid-2000s. Today it stands behind the WebDriver protocol, which the W3C standardised. Cypress appeared with a simple idea: let front-end developers write a test and watch it run instantly. Playwright came out of Microsoft with the goal of driving every modern browser engine through one API.
In practice, here is what I see in the field. Selenium stays strong in large, multi-language teams. Meanwhile, JavaScript-heavy front-end teams love Cypress. New projects, in turn, increasingly default to Playwright, because it covers more ground. That is field experience, not a guarantee. In other words, put your own team's language, infrastructure and budget into the picture before you decide.
Also, these tools do not fully replace each other. Some teams use Cypress for component tests and Playwright for end-to-end flows. What matters is that you know why each test exists and keep only as many tools as you can maintain.
How does Selenium work, and when is it still the smartest choice?
Selenium WebDriver puts a driver layer between your test code and the browser. Your code sends a command to the driver, and the driver passes it to the browser. The design follows the W3C WebDriver specification. As a result, you can drive Chrome, Firefox, Edge and Safari with the same logic. Selenium Manager, which arrived with Selenium 4.6, also removed most of the pain of downloading drivers.
Above all, language support is Selenium's biggest strength. Official bindings exist for Java, Python, C#, Ruby and JavaScript. Therefore, if your backend team works in Java, you can write tests in the same language with the same toolchain. Selenium Grid then lets you spread tests across many machines and browsers.
- When it makes sense: a Java or C# enterprise team, a large existing suite, or a need for real Safari and older browsers.
- What needs care: you own the waiting strategy. Without explicit waits, flaky tests multiply.
- What people miss: Selenium is not a test runner. You pair it with JUnit, TestNG or pytest.
Why does the Cypress architecture matter so much?
Cypress runs tests inside the browser, in the same loop as your application. So you stay very close to the DOM, the network and the app state. While a test runs, you can watch every step and travel back to any earlier step to inspect the screen. For developer experience, this is the part people love most.
On the other hand, the same architecture brings permanent limits. The Cypress trade-offs page lists them openly. First, test code must be JavaScript or TypeScript. Second, you cannot control more than one browser at a time. Each test binds to a single superdomain, and you need cy.origin() to visit another origin.
In short, Cypress is a very comfortable place for front-end teams that build single-page apps and write their own tests. However, if payment redirects, multiple tabs or two users interacting at once are critical for you, plan for these limits from day one.
What does Playwright do differently, and why did it spread so fast?
Playwright drives Chromium, Firefox and WebKit through one API. According to the official documentation, it runs on Windows, Linux and macOS, locally or in CI, headless or headed, with native mobile emulation. WebKit support means you can approximate Safari behaviour even without a Mac.
What really spread Playwright, though, is daily ergonomics. Auto-waiting checks that an element is visible and enabled before a click. Trace Viewer lets you replay every step of a failed test, including network traffic and screenshots. Finally, codegen turns your clicks in the browser into test code.
- Official languages: JavaScript/TypeScript, Python, Java and .NET.
- Built-in parallel runs and an HTML report.
- Multiple tabs, windows and browser contexts in one test.
- UI Mode for watch mode and time-travel debugging.
That said, the Playwright ecosystem is younger than Selenium's. So if you need a very specific enterprise integration, your odds of finding a ready plugin may still be higher on the Selenium side.
How do test automation tools compare in one table?
The table below draws on the official documentation of each tool. Version details change over time, so check the relevant page once more before you commit.
| Criterion | Selenium | Cypress | Playwright |
|---|---|---|---|
| Architecture | W3C WebDriver, drives the browser from outside | Runs inside the browser | Direct protocol connection to the browser |
| Test language | Java, Python, C#, Ruby, JavaScript | JavaScript/TypeScript only | JS/TS, Python, Java, .NET |
| Browsers | Chrome, Firefox, Edge, Safari | Chrome family, Firefox, WebKit (experimental) | Chromium, Firefox, WebKit |
| Auto-waiting | No, you write explicit waits | Yes, commands retry | Yes, actionability checks |
| Multiple tabs or browsers | Supported | One browser; tabs via plugin | Supported |
| Debugging | Depends on runner and IDE | Visual time-travel runner | Trace Viewer, UI Mode |
| Parallel runs | Via Selenium Grid | Easier with the paid cloud service | Built in |
| Best fit | Multi-language enterprise team | JS-heavy front-end team | New project, mixed team |
Do not fixate on a single row when you read this comparison of test automation tools. For instance, if parallel runs do not matter to you, the Cypress difference there should not change your decision.
How does the same login test look in all three tools?
You see the difference best with one scenario, so let's use one. Ours is simple. Open the login page, type an email and a password, click the button, then confirm that the dashboard heading appears. These snippets show the concept, so adapt the selectors to your own project.
Selenium (Python): you open the page with driver.get(URL). Then you wait for the field with WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "email"))). Next, send_keys types the values and click presses the button. Finally, an assert checks the heading text.
Cypress (JavaScript): you start with cy.visit('/login'). After that come cy.get('#email').type(email), cy.get('#password').type(password) and cy.contains('Log in').click(). To verify, cy.contains('h1', 'Dashboard').should('be.visible') is enough. You write no waits at all.
Playwright (TypeScript): you open the page with await page.goto('/login'). Then you call await page.getByLabel('Email').fill(email) and await page.getByRole('button', { name: 'Log in' }).click(). For the check, you use await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible().
As you can see, you manage waiting yourself in Selenium, while the other two handle it for you. Moreover, role and label locators in Playwright tie the test to the accessibility tree. As a result, tests break less often when the design changes.
Which tool produces fewer flaky tests?
Put simply, a flaky test passes sometimes and fails sometimes, even though nothing in the code changed. Most flakiness I see comes from timing assumptions, not from the tool. Tests that sleep for fixed times, ignore animations or share test data will cause trouble in any tool.
Still, the tool difference is real. Auto-waiting in Cypress and Playwright removes many waits you would write by hand in Selenium. Therefore, I meet flakiness more often in Selenium teams, but usually as a problem that discipline can fix. That is field experience, not a guarantee.
- Use condition-based waits instead of fixed sleeps.
- Let every test create and clean up its own data.
- Prefer stable locators such as roles, labels or test IDs over CSS classes.
- Mock external services, especially payment and email steps, where you can.
- Quarantine a flaky test instead of silencing it, then find the root cause.
In my own projects I keep flaky tests on a separate list. If a test fails twice in a row for no clear reason, it goes on the list, and someone hunts the root cause that week. This small habit protects trust. A suite that people rerun all the time soon turns into noise that nobody takes seriously.
Which tool stands out for speed and CI/CD integration?
I will not give you a hard speed number. The result depends heavily on your app, your test count and your machines. I also suggest caution with claims like "tool X is 40 percent faster" when they come without a source. The honest method is simple: write the same five tests in each tool and measure them in your own CI.
All three also run on GitHub Actions, GitLab CI and Jenkins. However, their approaches differ. The Playwright setup wizard offers a ready GitHub Actions file, and parallel runs come built in. In Cypress, many teams turn to the paid cloud service for parallelisation and a recording dashboard. With Selenium, you set up scaling yourself through Grid or a cloud vendor.
When you measure, look beyond total runtime. Check the first run, the cached second run and how many minutes it takes to find the cause of a failure. In my view the last one matters most, because a team spends most of its real time on debugging.
Which browsers do you actually need to test?
First, answer this question before you choose a tool. Look at your analytics and see which browsers and devices your users bring. If a large share of your visitors use iPhones, Safari behaviour is critical for you. In that case Selenium stands out for real Safari, and Playwright's WebKit support helps for a close approximation.
Also, testing a mobile viewport is not the same as testing a real mobile device. Playwright's mobile emulation mimics screen size, touch events and the user agent. Yet it does not mirror real-device performance or every browser quirk. For the basic mobile checks, see my mobile-friendly test guide.
For example, on a corporate B2B site where most visitors use desktop Chrome and Edge, a wide browser matrix may simply waste CI minutes. So base the decision on your own analytics, not on assumptions. Run critical flows across the wide matrix and the rest on a single browser.
Can test automation tools replace performance and SEO testing?
No, they cannot. These tools check functional correctness. Does the button work? Does the form submit? And is the error message visible? Page speed, Core Web Vitals and SEO signals belong to other tools. Even Cypress states in its documentation that it is not a general-purpose automation or performance testing tool.
You can combine the two, though. For instance, you can log in with Playwright and then run Lighthouse on a protected page. I explain how I read Lighthouse in my Lighthouse performance test guide. For the ranking side, read how site speed affects SEO.
My rule in practice is simple. A red functional test stops the release. A drop in the performance score raises a warning but does not block the release automatically. That way the team does not panic over every small swing.
Where do these tools fit in the pre-launch testing process?
In practice, the checks I run before a site goes live form a long list: content, redirects, form notifications, tracking codes, speed and mobile layout. Automating that whole list is neither necessary nor efficient. I reserve automation for flows that repeat in every release and cost money when they break.
- Contact and quote form submission, including the thank-you page.
- Add to cart, the move to checkout and the order summary.
- Login, password reset and logout.
- Language switching and the redirect to the correct language page.
- Status 200 on critical pages and correct redirects from old URLs.
For a quick first pass on redirects, you can use the redirect checker. During big changes such as a migration, your automated tests should run next to the website migration SEO checklist.
How do you set up the page object model in each tool?
The page object model gathers the selectors and actions of each screen into one class. When the login button selector changes, you update one file instead of a hundred tests. The pattern does not depend on the tool, but each tool carries it with a different level of comfort.
In Selenium, page objects are close to mandatory. Without one place for explicit waits and selectors, test code spreads fast. Java teams also treat it as tradition. In Playwright you build classes the same way. Moreover, the fixture system makes it easy to inject a page that has already logged in.
Cypress, on the other hand, promotes custom commands and app actions over page objects in its docs. For example, it suggests logging in through cy.request in the background and going straight to the dashboard. That speeds tests up. Still, you must protect the real UI login in a separate test.
My habit is the same in every tool. Keep selectors in one place and write the test itself in business language. When someone reads it, it should say something like "the user submits the quote form".
How do component testing and API testing support differ?
End-to-end tests are valuable, but they are also slow. So a good strategy moves most of the work into faster layers. Here the three tools differ clearly, and that can affect your choice.
Cypress officially supports component testing for frameworks such as React, Vue, Angular and Svelte. You test a button or a form in a real browser without booting the whole app. Playwright also offers component testing, but its documentation labels the feature experimental. Selenium has no such goal; it focuses on driving the browser.
For API testing, Cypress offers cy.request and Playwright offers the request fixture. Both let you send HTTP calls directly. As a result, you prepare test data through the API instead of the UI, and tests get much shorter. In Selenium you use your language's own HTTP library for this, for example requests in Python.
In short, Cypress is the most mature option if your front-end team cares about component tests. If you want end-to-end and API tests in one package, Playwright offers a more balanced bundle.
How should you choose based on your team's language and skills?
When I choose between test automation tools, my first question is always the same: who will write the tests and who will maintain them? Test code needs upkeep just like production code. That is why the team's comfort language matters more than any feature list.
- The team builds the front end in JavaScript or TypeScript: Cypress or Playwright. If multiple tabs and origins matter, pick Playwright.
- The team works mainly in Java or C#: Selenium if the infrastructure already exists. If you start from zero, the Java or .NET version of Playwright is worth a look.
- The team uses Python: Selenium or Playwright. Cypress does not fit here.
- A separate QA team shares no language with developers: pick the language the QA team knows best.
Also, think about hiring. How easy is it to find someone who knows your chosen tool? Local job listings give you a more realistic picture than any popularity survey.
Does it make sense to migrate from Selenium to Playwright?
Not always, because context matters. Moving a stable Selenium suite that the team owns, only because a newer tool is popular, often turns into a rewrite that lasts months. Nobody writes tests for new features during that time, and morale drops. So make the migration decision to solve a problem, not to follow a trend.
Real signals that justify a move look like this. Flaky tests slow the team down. You now need WebKit or multiple tabs. Maintenance crowds out new tests. In that case I suggest a gradual path instead of a big bang. Write new tests in Playwright, move the most fragile old tests first and leave the rest until their natural end.
A move from Cypress to Playwright follows the same logic. Because both use JavaScript, you can keep most of your test data helpers and page objects.
What should you watch on the cost side?
The core of all three test automation tools is open source and free of licence fees. Yet total cost is more than licences. The real cost is the human time spent on writing and maintaining tests, plus the infrastructure that runs them.
- Human time: fighting flaky tests is the most expensive hidden line item.
- CI minutes: as your browser matrix grows, runtime and the bill grow with it.
- Cloud services: recording and parallelisation services such as Cypress Cloud, or real-device clouds, can add fees.
- Training: if the team moves to a new tool, put the learning curve on the calendar.
Where tests run is also a cost decision. Instead of the full matrix on every commit, run one browser on pull requests and the full matrix on merges to the main branch. That keeps feedback fast and the bill under control. In my web design projects we discuss this line item upfront, because tests added later usually cost more.
How does test automation protect conversions and ad spend?
This technical topic has a very concrete marketing side. When a visitor from an ad lands on a broken form, you pay for the click and get no conversion. On top of that, the conversion tag never fires, so campaign optimisation learns from wrong data.
That is why, in projects where I handle Google Ads management, I want the most critical conversion flow to run automatically after every release. A simple Playwright test fills in the form. Then it confirms that the thank-you page loads and that the conversion request leaves the browser. So you learn about a broken form on the same day, not a week later from a report.
It also helps, for example, to test that UTM parameters survive redirects. Build test links with the UTM builder and check at the end of the flow whether the parameters are still there. To clarify which goal to track, see my guide on how to set website conversion goals.
Do AI-assisted testing features change the choice?
Meanwhile, AI-assisted features have appeared around all three tools. There are code-writing assistants, plugins that heal broken selectors and tools that draft tests from plain language. These can speed up the start. However, in my experience, generated tests that nobody reviews tend to increase flakiness.
So treat AI as a helper, not as a decision criterion. Core architecture, language support and debugging quality still decide. Moreover, self-healing selectors can sometimes "heal" a real bug and hide it. That defeats the whole point of a test.
In short, a good test is still readable code with one job that checks a clear business rule. The tool or assistant you use to write it does not change that.
What do I recommend for a team starting from scratch?
If you have no legacy suite and you are starting a new web project, my default recommendation is Playwright. My reasons are cross-browser support, several language options, built-in parallel runs and the time Trace Viewer saves in debugging. This is advice, not a universal rule.
If your team works fully in JavaScript, your app stays on one origin and developers enjoy watching tests run visually, Cypress is an excellent choice too. On the other hand, if you have a large Java stack and a Selenium suite built over years, keeping it is often the most economical decision.
- Map your users' browser and device mix.
- Note the language your team is comfortable with and your CI setup.
- Pick your three most critical flows and prototype them in two candidate tools.
- Watch flakiness, runtime and ease of debugging for two weeks.
- Write down the decision and use only the chosen tool for new tests.
If you want to handle technical decisions like this as part of the whole web project, you can reach me through the contact page.




