Automation

How to Migrate from Cypress to Playwright: A Practical QA Guide

How to Migrate from Cypress to Playwright: A Practical QA Guide

Teams migrating from Cypress to Playwright cite three primary reasons: Safari and WebKit coverage, support for Python, Java, or C# test code, and faster CI runs without a paid parallelism plan. The migration is non-trivial but achievable in two to four weeks for a typical medium-sized suite with good page object structure.

This guide covers the concept mapping between Cypress and Playwright, a step-by-step migration approach, common gotchas that slow teams down, and the cases where migration is not worth the effort.

Concept Mapping: Cypress to Playwright

Most Cypress commands have direct Playwright equivalents. The list below covers the most common mappings:

  • cy.visit(url) maps to page.goto(url)
  • cy.get(selector) maps to page.locator(selector)
  • cy.intercept() maps to page.route()
  • cy.fixture() maps to Playwright fixtures in test.extend()
  • beforeEach / afterEach maps to test.beforeEach / test.afterEach
  • cypress.json / cypress.config.js maps to playwright.config.ts
  • Custom Cypress commands map to Playwright fixtures or plain helper functions
  • Cypress plugins (cypress/plugins/index.js) map to Playwright global setup and teardown

Step-by-Step Migration Approach

A phased migration is safer than a full rewrite. Run both frameworks in parallel until Playwright coverage matches Cypress.

  1. Install Playwright alongside Cypress. Run npm init playwright@latest in the project. This creates playwright.config.ts and an e2e directory separate from the Cypress folder.
  2. Start with one test file. Pick a stable, representative Cypress spec. Rewrite it in Playwright, run both against the same environment, and confirm the same assertions pass.
  3. Migrate page objects and selectors. Playwright's locator API prefers user-visible locators: page.getByRole(), page.getByText(), page.getByLabel(). Update selectors as you migrate rather than directly porting cy.get('[data-testid]') calls, which still work but miss the value of Playwright's auto-waiting locators.
  4. Replace cy.intercept() with page.route(). Playwright's route handler takes a URL pattern and a callback. For assertions on request bodies, combine with page.waitForRequest().
  5. Replace Cypress commands and plugins with fixtures. Playwright's test.extend() fixture system covers setup, teardown, shared state, and reusable page objects. Custom Cypress commands that wrap complex UI flows become fixture methods.
  6. Migrate CI configuration. Replace the Cypress run step (npx cypress run) with npx playwright test. Configure sharding with --shard=1/4 for free parallelism across runners.
  7. Remove Cypress when coverage is equivalent. Once Playwright coverage matches Cypress test count and the suite is stable, remove the Cypress dependency.

Common Gotchas

Several patterns that work in Cypress do not transfer directly:

  • Automatic retry scope. Cypress retries entire assertion chains. Playwright retries locator actions (clicks, fills) but not arbitrary JavaScript. Assertions made via expect(await page.evaluate(...)) need explicit polling with expect.poll().
  • Clock control. cy.clock() maps to page.clock(), available from Playwright 1.45. Older Playwright versions require a sinon-based workaround.
  • Custom commands. Cypress commands added via Cypress.Commands.add() have no direct equivalent; convert them to Playwright fixtures or utility functions imported in test files.
  • Environment variables. Cypress reads CYPRESS_* prefixed env vars. Playwright reads from .env files via dotenv or from the shell directly; update CI secrets accordingly.

When Not to Migrate

Migration is not always the right call. If your team uses Cypress Component Testing heavily with React or Vue, and that component isolation workflow is central to your quality process, Playwright Component Testing is maturing but is not yet at the same level of polish. The E2E migration may still be worth it while keeping Cypress for component tests during a transition period.

Before committing to migration, compare both frameworks in detail in our Playwright vs Cypress 2026 guide. For alternatives beyond Playwright, see Best Cypress Alternatives in 2026, which covers Selenium, TestCafe, Puppeteer, and more options with full feature comparisons.

"Most Cypress commands map directly to Playwright; migration takes two to four weeks for a typical medium-sized suite."

Avanish Pandey

November 13, 2026

icon
icon
icon

Stop finding bugs after launch.

Talk to our QA team and start testing this week.

Get in touch →

Subscribe to our Newsletter

Sign up to receive and connect to our newsletter

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Ask our AI assistant…