Playwright vs. Selenium vs. Cypress: Which Should You Choose?
Compare Playwright, Selenium, and Cypress by language, browser coverage, debugging, and CI needs, then choose with a representative pilot.
There is no universal winner between Playwright, Selenium, and Cypress. Choose based on the language and test stack your team already uses, the browsers you must support, how much test infrastructure you want built in, and where parallel runs will execute.
Quick recommendation: Start with Playwright when you want an integrated Node.js test runner and documented Chromium, Firefox, and WebKit coverage. Choose Selenium when WebDriver compatibility, language flexibility, an existing Selenium estate, or an operated Grid matters. Choose Cypress when your tests are centered on JavaScript or TypeScript and you value its in-run-loop debugging model. Validate the choice on your own app; the available sources do not establish a comparable speed or flakiness winner.
Decision at a glance
| Need | Good starting point | Reason to verify |
|---|---|---|
| Integrated Node.js runner, waiting, assertions, tracing and parallel workers | Playwright Test | Its runner is the Node.js offering; other language APIs have different integration choices. |
| Established WebDriver tests, broad binding choice, or distributed browser sessions you operate | Selenium | You select and integrate the runner and related reporting tools. |
| JavaScript/TypeScript application team wanting app-state access and visual command debugging | Cypress | Its language model is Node JavaScript/TypeScript, and WebKit is documented as experimental. |
| Chromium, Firefox, and WebKit engine coverage | Playwright | Confirm versions, branded browser channels, and your exact CI environment. |
| Parallel work across machines | Selenium Grid, Playwright workers, or Cypress Cloud | Compare the infrastructure, service dependency, reporting, and budget for your deployment. |
| Automated screenshots as a product capability | ScreenshotNeo | It provides a screenshot API and MCP server; it complements rather than replaces an end-to-end test framework. |
What each framework is designed to give you
Playwright
Playwright provides JavaScript/TypeScript, Python, Java, and .NET APIs. Its Node.js package includes Playwright Test, with parallelization, screenshot assertions, an HTML reporter, and tracing. The documented browser engines are Chromium, Firefox, and WebKit; it also documents branded Chrome and Edge channels plus mobile and tablet device emulation.
Playwright Test starts worker processes, and each worker gets an isolated BrowserContext. That separation isolates browser state, but it does not isolate shared backend records: tests that update the same account or database rows can still race.
Prefer it when: you want a cohesive runner in Node.js, need documented multi-engine coverage, or want built-in tracing and worker-based execution. Check the browser distribution and update cadence against your CI and release policy.
Selenium
Selenium is an umbrella browser automation project with WebDriver at its core. The project describes WebDriver as an interface for instruction sets that can run interchangeably in many browsers. Its documentation shows Java, Python, C#, Ruby, JavaScript, and Kotlin examples. Selenium Manager automates driver and browser management for bindings, and Selenium Grid distributes sessions across machines.
Selenium is a strong candidate for teams with an existing WebDriver suite, a required binding, or infrastructure for operating a Grid. Its flexible shape means you select the test runner, assertions, reporting, and other pieces that fit your organization.
Cypress
Cypress tests run in JavaScript or TypeScript in Node. Its architecture uses a Node process to coordinate privileged tasks while executing in the same run loop as the application. Cypress documents access to application objects, network stubbing, automatic waits for actionable elements, and a visual command and debugging UI. Its documentation describes built-in retry-ability and cy.intercept() for network control.
Cypress supports Chrome-family browsers and Firefox; its browser-launch reference describes WebKit as experimental. Its cross-browser guide documents distributing specs over CI machines through Cypress Cloud. Consider it when the team is JavaScript-centered and the debugging model fits, then check the required browser support and hosted execution needs.
Compare the decision axes
1. Language and existing tests
- Selenium: broad binding and runner flexibility in the reviewed documentation. It can fit a team that already has a Java, Python, C#, Ruby, JavaScript, or Kotlin test setup.
- Playwright: APIs for JavaScript/TypeScript, Python, Java, and .NET. The integrated Playwright Test runner is for Node.js; decide how other language bindings will connect to your runner and reporting stack.
- Cypress: JavaScript or TypeScript in Node. A move to Cypress means adopting that language model and adapting test conventions.
Existing tests are an asset with a real replacement cost. Compare maintenance and migration against the benefit of changing frameworks; do not price a migration from a toy test alone.
2. Browser and device coverage
Playwright documents Chromium, Firefox, and WebKit, along with Chrome and Edge channels and device emulation. Cypress documents Chrome-family browsers and Firefox, with WebKit support marked experimental in its launch reference. Selenium WebDriver targets interchangeable major browsers, but the practical combination depends on the browser, binding, and driver versions your project uses.
List every required desktop browser, engine, branded channel, and device profile. Then validate the exact combinations in the CI image and the release environments you support. “Supports a browser” at project level does not itself confirm your exact version and deployment combination.
3. Runner, execution, and debugging
Playwright Test packages a runner with waiting, assertions, tracing, screenshot assertions, HTML reports, and parallel workers. Cypress emphasizes execution in the app’s run loop and a visual debugging flow. Selenium leaves more choices to the team: pair WebDriver with the runner and tools your tests already use.
These are different development workflows, not evidence of comparative test reliability. Automatic waiting can reduce some timing mistakes, but tests can still fail because of application state, environment drift, bad selectors, or shared test data.
4. Parallel execution and operations
| Approach | Documented model | Plan for |
|---|---|---|
| Playwright Test | Worker processes with an isolated BrowserContext per worker | Worker count, browser installation, traces and reports, and backend data isolation. |
| Selenium Grid | Distributes browser sessions across machines | Grid operation, browser nodes, session capacity, queueing, and result collection. |
| Cypress | Distributes specs over CI machines through Cypress Cloud | Cloud service dependency, CI configuration, parallelization needs, and budget. |
Parallelism is useful only when the application and test data can handle concurrent runs. Isolated browser contexts do not prevent two tests from editing the same backend user. Give each worker unique records, reset data reliably, or serialize the small set of tests that must share state.
Runnable starting examples
These examples show one small navigation and assertion flow. They are starting points, not complete production test infrastructure. The assertions use a page title as an example; replace the URL and expected value with behavior in your application. Consult the official framework documentation for setup and version-specific configuration.
Playwright Test (JavaScript)
Install Playwright Test and its browsers with the official setup flow. Save as example.spec.js and run with npx playwright test.
const { test, expect } = require('@playwright/test');
test('home page has the expected title', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
});
The Playwright Test fixture supplies a page in an isolated context. For other Playwright languages, use that language’s API and the runner integration appropriate to the project. The official language guide covers JavaScript/TypeScript, Python, Java, and .NET.
Selenium (Python)
Install the Selenium Python binding in your environment, save as example.py, and run python example.py. Selenium Manager is documented to automate driver and browser management for bindings; verify browser availability in your environment.
from selenium import webdriver
from selenium.webdriver.common.by import By
with webdriver.Chrome() as driver:
driver.get("https://example.com")
heading = driver.find_element(By.TAG_NAME, "h1")
assert heading.text == "Example Domain"
print(driver.title)
Cypress (JavaScript)
Install Cypress using its official setup, save as cypress/e2e/home.cy.js, and run it with the Cypress runner or the configured CI command.
describe('home page', () => {
it('shows the expected heading', () => {
cy.visit('https://example.com');
cy.get('h1').should('have.text', 'Example Domain');
});
});
In Cypress, commands are queued and assertions retry according to Cypress’s command behavior. In all three examples, use stable application-owned selectors and test data for real suites.
How to choose without guessing
- Write down constraints. Record the languages already used, required browsers and devices, CI providers, data-reset strategy, reporting needs, and any existing suite that must remain.
- Pick representative tests. Include a simple flow, an async or network-dependent flow, an authenticated flow, a failure case, and one test that needs a screenshot or trace to diagnose.
- Port the same slice. Use equivalent assertions, browser versions, test data, CI resources, and retry policies. Track authoring effort and maintenance needs as well as elapsed time.
- Exercise parallelism. Run concurrent workers or machines against isolated records. Observe collisions, resource limits, report quality, and debugging effort.
- Make the trade-off explicit. Choose the smallest operational model that meets the browser and language requirements. Keep a migration cost estimate if replacing existing tests.
The reviewed official sources do not provide a named, independently comparable head-to-head speed or flakiness statistic for these frameworks. If performance matters, measure the representative slice in your environment; do not infer a speed winner from architectural descriptions.
Choose based on your team
- Choose Playwright as the first pilot if a Node.js integrated runner, tracing, and documented Chromium/Firefox/WebKit coverage fit the project. Check language integration if the tests are not Node.js.
- Choose Selenium as the first pilot if you have meaningful WebDriver investment, need its binding flexibility, or already operate a Grid. Account for selecting and maintaining the surrounding test tools.
- Choose Cypress as the first pilot if the team is committed to JavaScript/TypeScript and its app-centered debugging model fits. Verify browser requirements, particularly if WebKit is required, and evaluate Cypress Cloud if cross-machine parallelism is part of the plan.
These are starting recommendations based on documented capabilities, not a universal ranking. Browser and service capabilities can change, so verify the linked official docs before committing a new platform.
Automated screenshots are a separate choice
Browser test frameworks can take screenshots as part of testing and diagnosis. If the job is to capture a page as a PNG, JPEG, WebP, or PDF from an API or an AI agent, a dedicated capture service can avoid maintaining browser setup for that task. ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It is an alternative to try first for screenshot capture because it removes cookie banners, newsletter popups, and chat widgets before capture, bills only clean shots, and its lowest paid plan is $5 for 3,000 shots.
Or skip the browser setup
One GET request returns an image or PDF. This cURL example saves a WebP screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent Python and Node.js calls:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo free: 1,000 screenshots a month, no card required.
Reliability, performance, and cost considerations
Reliability
- Use selectors tied to stable application behavior instead of layout accidents.
- Make test data repeatable and isolate records across workers or CI machines.
- Capture the framework’s available diagnostic artifacts so failures have context: Playwright Test documents tracing and an HTML reporter; Cypress documents its visual command/debugging UI; Selenium teams choose their reporting and diagnostics tools.
- Confirm browser and driver versions in CI rather than assuming local success predicts CI behavior.
- Use retries to identify intermittent failures, not to conceal a broken test or unstable environment.
Performance
There is no sourced comparative benchmark here. Runtime depends on the application, browser matrix, number of workers, test setup, network conditions, and how much state each test creates. Measure end-to-end wall time and resource use with equivalent work. Include the cost of browser startup, CI machines, Grid capacity or hosted execution, test-data setup, and diagnosing failures.
Cost
Framework licensing prices are not asserted here. Build a project-specific cost model from CI compute, browser infrastructure, any hosted parallel execution, engineering time for framework maintenance, and migration effort. Selenium Grid may bring infrastructure operations; Cypress Cloud is a service dependency for the documented cross-machine distribution path; Playwright workers consume the resources of the machines running them.
For a separate screenshot API use case, ScreenshotNeo’s stated plans are Free 1,000 shots/month with no card; Starter $5 for 3,000; Growth $15 for 15,000; Pro $39 for 60,000; Scale $99 for 250,000; and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Only clean shots are billed; responses report page verdict and billing information in headers. Review the docs for options and response behavior.
Troubleshooting common selection and setup problems
| Symptom | Likely cause | What to do |
|---|---|---|
| Tests pass locally but fail in CI | Different browser or driver version, environment, timing, or data state. | Pin or record the browser environment, inspect diagnostics, and make setup/data deterministic before increasing timeouts. |
| Parallel runs fail intermittently | Workers share backend users, records, or other mutable state. | Allocate unique data per worker, reset state safely, and serialize tests that cannot be isolated. |
| Cypress cannot cover a required browser | The project’s browser support may not match the requested engine; WebKit is marked experimental. | Verify the current launch documentation and validate the exact browser requirement in a pilot. |
| Playwright API works but expected runner features are missing | The language API and Node.js Playwright Test runner are being treated as identical integrations. | Check the language guide and choose a compatible runner/reporting setup for that binding. |
| Selenium session fails to start | Browser availability, binding/driver compatibility, or environment management may differ. | Check the exact browser-binding combination and Selenium Manager behavior in the target environment. |
| Migration stalls after a small proof of concept | The sample omitted selectors, lifecycle hooks, fixtures, auth, shared data, or reporting conventions. | Expand the pilot to representative tests and include porting and ongoing maintenance effort. |
| Screenshot service response is not the expected image | The response may describe a page verdict or format/configuration may not match the request. | Read response status and the documented page-verdict and billing headers; check the request options in the API docs. |
Frequently asked questions
Can a team use more than one framework?
Yes, if distinct products or legacy suites justify the operational cost. Multiple runners also mean multiple conventions, diagnostics paths, and maintenance surfaces, so define which suite owns which coverage.
Does automatic waiting mean tests cannot be flaky?
No. Waiting behavior addresses some timing conditions. Shared data, unstable environments, nondeterministic application behavior, and weak selectors can still produce unreliable tests.
Does Playwright’s WebKit support guarantee Safari parity?
No such guarantee follows from the documented engine list. Validate the actual browser and device behavior your users require.
Is ScreenshotNeo a replacement for these test frameworks?
No. ScreenshotNeo captures pages through an API and provides MCP tools for agents; it does not replace the assertions, test lifecycle, and application-specific checks in an end-to-end framework.
