How to Migrate from Selenium to Playwright in 2026: Complete Guide

Published: · 4 min read

A practical, step-by-step guide to migrating your Selenium test suite to Playwright. Includes code comparison, common pitfalls, and a migration strategy that won't disrupt your team.

Selenium to Playwright migration guide 2026 - step by step tutorial

Why Migrate from Selenium to Playwright?

I've been using Selenium since 2015. It served me well at Williams-Sonoma, Apple, and countless other companies. But after migrating to Playwright at CooperVision, I won't go back.

Here's how they compare:

Setup time:

  • Selenium: 30+ minutes
  • Playwright: 5 minutes

Auto-waiting:

  • Selenium: Manual (causes flaky tests)
  • Playwright: Built-in

Cross-browser:

  • Selenium: Needs separate drivers
  • Playwright: Bundled

Parallel testing:

  • Selenium: Requires Grid setup
  • Playwright: Built-in

Test execution:

  • Selenium: Slower
  • Playwright: 40-60% faster

Debugging:

  • Selenium: Stack traces only
  • Playwright: Trace viewer with recordings

If your Selenium tests are slow, flaky, or a pain to maintain — migration is worth it.

The Migration Strategy

Don't rewrite everything at once. Follow this incremental approach:

Phase 1: New tests in Playwright

Stop writing new Selenium tests. All new tests go in Playwright.

Phase 2: Migrate critical paths first

Identify your highest-value tests (login, checkout, core features) and migrate those.

Phase 3: Gradual Selenium deprecation

As you touch Selenium tests for maintenance, migrate them. Eventually, the old suite goes to zero.

This approach minimizes risk and lets your team learn Playwright gradually.

Step 1: Set Up Playwright Alongside Selenium

You don't need to remove Selenium to start. Create a parallel Playwright project:

npm init playwright@latest -- --quiet

Your project structure becomes:

tests/
├── selenium/  # Existing Selenium tests
└── playwright/  # New Playwright tests

Both can run in CI simultaneously during transition.

Step 2: Translate Common Patterns

Here's a side-by-side comparison of common operations:

Navigation:

Selenium (Java):

driver.get("https://example.com");

Playwright (TypeScript):

await page.goto('https://example.com');

Finding elements:

Selenium:

driver.findElement(By.id("username"));

driver.findElement(By.cssSelector(".submit-btn"));

driver.findElement(By.xpath("//button[text()='Submit']"));

Playwright:

page.locator('#username');

page.locator('.submit-btn');

page.getByRole('button', { name: 'Submit' });

Clicking:

Selenium:

driver.findElement(By.id("submit")).click();

Playwright:

await page.locator('#submit').click();

Or better:

await page.getByRole('button', { name: 'Submit' }).click();

Typing:

Selenium:

driver.findElement(By.id("email")).sendKeys("test@example.com");

Playwright:

await page.locator('#email').fill('test@example.com');

Or:

await page.getByLabel('Email').fill('test@example.com');

Waiting:

Selenium (the source of most flakiness):

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("result")));

Playwright (auto-waits by default):

Just interact — Playwright waits automatically

await page.locator('#result').click();

Or explicitly assert visibility:

await expect(page.locator('#result')).toBeVisible();

Assertions:

Selenium (with JUnit):

String title = driver.getTitle();

assertEquals("Expected Title", title);

Playwright:

await expect(page).toHaveTitle('Expected Title');

Screenshots:

Selenium:

File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

FileUtils.copyFile(screenshot, new File("screenshot.png"));

Playwright:

await page.screenshot({ path: 'screenshot.png' });

Step 3: Migrate Page Objects

If you're using Page Object Model in Selenium, the pattern translates directly.

Selenium (Java):

public class LoginPage {
    private WebDriver driver;
    public LoginPage(WebDriver driver) {
        this.driver = driver;
    }
    public void login(String email, String password) {
        driver.findElement(By.id("email")).sendKeys(email);
        driver.findElement(By.id("password")).sendKeys(password);
        driver.findElement(By.id("submit")).click();
    }
}

Playwright (TypeScript):

export class LoginPage {
  constructor(private page: Page) {}
  async login(email: string, password: string) {
    await this.page.getByLabel('Email').fill(email);
    await this.page.getByLabel('Password').fill(password);
    await this.page.getByRole('button', { name: 'Sign in' }).click();
  }
}

The structure is almost identical. You're just swapping APIs.

Step 4: Replace WebDriver Waits with Auto-Wait

This is where you get the biggest reliability win.

Remove all explicit waits:

In Selenium, you probably have code like:

WebDriverWait wait = new WebDriverWait(driver, 10);

wait.until(ExpectedConditions.elementToBeClickable(By.id("button")));

driver.findElement(By.id("button")).click();

In Playwright, just:

await page.locator('#button').click();

Playwright automatically waits for:

  • Element to be attached to DOM
  • Element to be visible
  • Element to be enabled
  • Element to be stable (not animating)

This single change eliminates most flaky tests.

Step 5: Set Up CI/CD

Playwright's CI setup is simpler than Selenium Grid.

GitHub Actions example:

name: Playwright Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

No Selenium Grid. No browser driver management. Just install and run.

Common Migration Pitfalls

1. Trying to rewrite everything at once

This is the number one cause of failed migrations. Use the incremental approach.

2. Copying Selenium's explicit waits

Don't translate WebDriverWait to waitForSelector. Trust Playwright's auto-waiting.

3. Keeping fragile locators

Migration is a chance to improve. Replace XPath and positional CSS with role-based locators.

4. Not training the team

Playwright has different patterns. Invest in a training session or pair programming during the first weeks.

Migration Checklist

Before declaring migration complete:

  • All new tests written in Playwright
  • Critical user journeys migrated
  • CI/CD running Playwright tests
  • Team trained on Playwright patterns
  • Old Selenium tests deleted (don't leave dead code)
  • Trace viewer configured for failure debugging

How Long Does Migration Take?

Based on my experience:

Small suite (under 50 tests): 1-2 weeks

Medium suite (50-200 tests): 1-2 months

Large suite (200+ tests): 3-6 months

The biggest factor isn't the number of tests — it's how tangled your Selenium architecture is. Clean Page Objects migrate fast. Spaghetti code requires refactoring.

The Results Are Worth It

At CooperVision, after completing migration:

  • Test execution time: 40% faster
  • Flaky test rate: Reduced by 80%
  • CI pipeline reliability: 98%+ pass rate
  • Developer experience: "I actually like writing tests now"

That last point matters more than any metric. When tests are pleasant to write, people write more tests.

Need Help with Your Migration?

If you're planning a Selenium to Playwright migration and want guidance from someone who's done it multiple times, I can help. I offer consulting packages that include:

  • Migration strategy and roadmap
  • Team training on Playwright patterns
  • Architecture review of existing tests
  • Hands-on migration for critical paths

Let's talk

Subscribe

Get notified when I publish something new, and unsubscribe at any time.

Latest articles

Read all my blog posts

· 2 min read

Page Object Model in Playwright with TypeScript: Complete Guide

Learn how to structure scalable Playwright tests using the Page Object Model pattern. Includes TypeScript examples, best practices, and real-world architecture patterns.

Page Object Model in Playwright with TypeScript: Complete Guide

· 4 min read

How to Migrate from Selenium to Playwright in 2026: Complete Guide

A practical, step-by-step guide to migrating your Selenium test suite to Playwright. Includes code comparison, common pitfalls, and a migration strategy that won't disrupt your team.

How to Migrate from Selenium to Playwright in 2026: Complete Guide