Playwright and Cypress

End-to-end Testing with Playwright and Cypress

An end-to-end test starts your real site, opens a real browser and does what a user does: type, click, wait for the network, read the screen. The two leading open-source tools are Playwright 26,280 (playwright.dev (https://playwright.dev/ 26,280 )), Apache-2.0-licensed and developed by Microsoft, and Cypress 41,181 (cypress.io (https://www.cypress.io/ 41,181 )), MIT-licensed and backed by a company that sells the Cypress Cloud dashboard. In September 2026 the current versions are Playwright 1.63 and Cypress 16.0.

Playwright

npm 2,036 init playwright@latest installs @playwright/test, writes playwright.config.js and downloads browsers: version 1.63 bundles Chromium 153 4,389 , Firefox 155 555 and WebKit 26.6 15,343 , Safari 10 's engine, so you can test WebKit on Windows and Linux. In the config, webServer: { command: "npm run preview", url: "http://localhost:4173" } starts your site before the tests, and baseURL lets tests call page.goto("/"). The page under test is a to-do form that appends an <li> and updates a role="status" counter. The test finds elements as a user or screen reader would, by placeholder, role and accessible name, not by CSS classes that change with every redesign:

e2e/todos.spec.js: a user journey with web-first assertionsJavaScript
import { test, expect } from "@playwright/test";
test("adds a todo and updates the counter", async ({ page }) => {
  await page.goto("/");
  const input = page.getByPlaceholder("What needs doing?");
  await input.fill("Write tests");
  await input.press("Enter");
  await page.getByRole("textbox").fill("Ship it");
  await page.getByRole("button", { name: "Add" }).click();
  await expect(page.getByRole("listitem")).toHaveText(["Write tests", "Ship it"]);
  await expect(page.getByRole("status")).toHaveText("2 items left");
});
Output
> npx playwright test --reporter=list
Running 1 test using 1 worker
  ok 1 [chromium] › e2e\todos.spec.js:3:1 › adds a todo and updates the counter (825ms)
  1 passed (4.2s)

There is no sleep. Before each click Playwright auto-waits until the element is visible, stable and enabled, and expect(locator) assertions retry until they pass or time out, removing the most common cause of flaky tests. npx playwright codegen records your clicks as code, --ui opens a watch mode with time-travel debugging, and a trace recorded on a CI failure replays every step with DOM snapshots and network requests. Each test gets a fresh browser context, a clean profile that starts in milliseconds.

Cypress

Cypress takes the opposite approach: npx cypress open loads your site in a frame and runs the test code in the same browser beside it, with a command log where clicking any step shows the DOM at that moment. Commands queue and retry automatically:

cypress/e2e/todos.cy.js: the to-do journey in CypressCSS
describe("todos", () => {
  it("adds a todo and updates the counter", () => {
    cy.visit("http://localhost:4173");
    cy.get("input[name=todo]").type("Write tests{enter}");
    cy.get("input[name=todo]").type("Ship it");
    cy.contains("button", "Add").click();
    cy.get("li").should("have.length", 2);
    cy.get("[role=status]").should("have.text", "2 items left");
  });
});

Running inside the browser brings documented trade-offs: one browser at a time, tests only in JavaScript, one superdomain per test unless you use cy.origin(), and server-side work only through cy.task() or cy.request(). Cypress 16 requires Node.js 22, 24 or 26+, supports Chrome 1 , Edge and Firefox 140 or newer, offers WebKit only as an experimental option, and deprecates its bundled Electron 20,509 browser.

Playwright versus Cypress in September 2026
Playwright Cypress
Licence and cost Apache-2.0, free MIT app; Cloud free tier, Team from $67/month
Test languages JS/TS, Python, Java, .NET JavaScript and TypeScript
Engines Chromium, Firefox, WebKit Chromium, Firefox; WebKit experimental
Where tests run Node.js, outside the page Inside the browser
Tabs and origins Many per test One tab, cy.origin() for others
Parallel runs Built in, free Cypress Cloud or CI sharding
Debugging UI mode, trace viewer Interactive runner, time travel

Choose Playwright for new projects, WebKit coverage and multi-tab flows; keep Cypress where a team already knows it. Either way, test only the journeys that earn money (sign-up, checkout, search) end to end, against a production build in CI, and push everything else down into unit tests.