Selenium vs Playwright: Which Browser Testing Tool to Pick

Selenium drives real, branded browsers through the W3C WebDriver standard and leaves the test runner to you. Playwright drives its own browser builds and, in Node.js, ships a full test runner. How they differ on architecture, languages, browsers, waiting, runners and AI agents, with the same small test in each.

7 min read

Pick Playwright if you are starting a new web test suite in TypeScript, Python, Java or .NET and want waiting, isolation, parallel runs, traces and reports in one package. Pick Selenium if you must test the browsers your customers actually install, including branded Safari, if your team writes Ruby or Kotlin, or if you already have a Selenium suite and a Grid that work. The deeper difference is architecture. Selenium is a library that speaks the W3C WebDriver standard to drivers the browser vendors support, and it is moving to the newer WebDriver BiDi standard. Playwright drives browsers through its own automation layer, using its own builds of Chromium, Firefox and WebKit. Both are free, open source and actively maintained, and both are now written as often by AI agents as by people.

Selenium vs Playwright at a glance

  • Protocol: Selenium uses W3C WebDriver, with WebDriver BiDi taking over. Playwright uses its own automation layer and patched browser builds.
  • Languages: Selenium has Java, Python, C#, Ruby, JavaScript and Kotlin. Playwright has TypeScript and JavaScript on Node.js, Python, Java and .NET.
  • Browsers: Selenium drives Chrome, Edge (including Internet Explorer mode), Firefox and Safari. Playwright drives Chromium, Firefox and WebKit builds, plus installed Chrome and Edge.
  • Test runner: Selenium brings none and works with your language’s runner. Playwright Test comes with Node.js; other languages use pytest, JUnit, TestNG, MSTest, NUnit or xUnit.
  • Waiting: Selenium leaves the waiting strategy to you. Playwright waits for elements to be actionable before acting and retries assertions.
  • Scale: Selenium Grid spreads browsers across machines. Playwright runs tests in parallel and can shard a suite across machines.
  • AI agents: Playwright has an official MCP server, CLI and test agents. Selenium has guidance for coding agents and community MCP servers.

Architecture: WebDriver and BiDi vs Playwright’s own engine

Selenium is “an umbrella project” of tools: WebDriver, the library you write tests with; Selenium IDE, a recorder extension; and Selenium Grid, for running browsers on many machines. WebDriver sends commands to a driver for each browser, and the drivers implement the W3C WebDriver specification, so the same script runs against every major browser. Selenium Manager, built into the bindings, now finds the installed browser and downloads the matching driver for you.

The classic WebDriver protocol is request and response: your code asks, the browser answers. Selenium’s WebDriver BiDi page (opens in a new tab) describes BiDi as the W3C bidirectional protocol, “created by the Selenium project together with the browser vendors,” and as the cross-browser replacement for the Chrome DevTools Protocol. With it, the browser can push events back, such as console logs and network requests. Selenium says it is updating its whole implementation from WebDriver Classic to BiDi while keeping backward compatibility where it can.

Playwright does not go through WebDriver. It installs its own browsers: Chromium builds, a Firefox that tracks the current stable release, and a WebKit built from WebKit’s main branch. Because it relies on patches, Playwright’s browser page (opens in a new tab) says it does not work with branded Firefox or branded Safari, though it can drive the Google Chrome and Microsoft Edge already on your machine through channels such as chrome and msedge. The trade is clear: tighter control and richer events from Playwright, real branded browsers from Selenium.

Languages and browsers

Selenium’s documentation gives examples in six languages: Java, Python, C#, Ruby, JavaScript and Kotlin. It lists browser-specific options for Chrome, Edge, Firefox, Safari and Internet Explorer, though standalone Internet Explorer has been unsupported since June 2022 and the IE driver now runs Microsoft Edge in IE mode. If your release checklist says “tested in Safari,” Selenium with safaridriver, which ships with macOS, is the way to mean it literally.

Playwright covers four language families. Its test framework runs on Windows, Linux and macOS, and it emulates mobile Chrome on Android and Mobile Safari through device settings rather than real phones. WebKit testing on Windows or Linux is a close stand-in for Safari, not Safari itself.

Test runners

Selenium automates browsers; it does not organize tests. Its getting-started guide suggests a runner for each language: JUnit or TestNG for Java, pytest or unittest for Python, NUnit or MSTest for C#, RSpec or Minitest for Ruby, Jest or Mocha for JavaScript, and Kotest or JUnit 5 for Kotlin. Reports, retries and parallel runs come from that runner and its plugins.

Playwright’s answer depends on the language. On Node.js, Playwright Test is the runner, with assertions, isolation, parallel workers, an HTML report you can filter by browser and by passed, failed, skipped or flaky, a UI Mode with watch and time-travel debugging, and a trace viewer. According to Playwright’s language page (opens in a new tab), Python uses the Playwright pytest plugin, Java leaves the choice of JUnit or TestNG to you, and .NET ships base classes for MSTest, NUnit and xUnit. So “Playwright has everything built in” is true mainly of the TypeScript and JavaScript version.

Speed and flakiness, as each project states it

Speed comparisons you find online depend heavily on the suite being timed, so treat any single number with suspicion. What each project says about its own design is more useful.

  • Playwright says it “automatically waits for actionability checks to pass before performing each action,” and that its web-first assertions describe expectations “that will eventually be met, eliminating flaky timeouts and racy checks.” Each test gets a fresh browser context, which Playwright compares to a brand-new browser profile.
  • Selenium says plainly that “synchronizing the code with the current state of the browser is one of the biggest challenges with Selenium.” Its answer is explicit waits for a specific condition; it calls an implicit wait “rarely the best solution.”
  • For scale, Selenium Grid distributes browser sessions across machines. Playwright runs test files in parallel workers and can split a suite into shards.

In practice, a Selenium suite with explicit waits and stable locators can be as steady as a Playwright one. Playwright simply makes the steady way the default.

The same small test in each

Here is the first script from Selenium’s getting-started guide (opens in a new tab), in Python. It opens a form, types, submits and reads the result. Note the explicit call to set a wait; the guide uses an implicit wait only because it is the easiest to show.

Selenium (Python)
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

driver.get("https://www.selenium.dev/selenium/web/web-form.html")

title = driver.title

driver.implicitly_wait(0.5)

text_box = driver.find_element(by=By.NAME, value="my-text")
submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button")

text_box.send_keys("Selenium")
submit_button.click()

message = driver.find_element(by=By.ID, value="message")
text = message.text

driver.quit()

And here is the second test from Playwright’s writing-tests page (opens in a new tab), in TypeScript. There is no wait and no browser setup: the page fixture arrives in its own isolated context, the click waits for the link, and the assertion retries until the heading appears.

Playwright Test (TypeScript)
import { test, expect } from '@playwright/test';

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  // Click the get started link.
  await page.getByRole('link', { name: 'Get started' }).click();
  // Expects page to have a heading with the name of Installation.
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

AI agents: Playwright MCP and Selenium’s agent guidance

This is where the two differ most in 2026. Microsoft publishes Playwright MCP, an official server that lets Claude Code, Cursor, VS Code or Codex drive a browser through accessibility snapshots, plus a Playwright CLI for coding agents and test agents that plan, generate and repair tests. Setup, options and safety are covered in Playwright MCP.

Selenium has no official MCP server. Its guide to using AI coding agents with Selenium (opens in a new tab) mentions community MCP servers but calls them “third-party projects rather than part of the Selenium project.” The guide is worth reading even if you never connect one: it lists the mistakes agents make from old training data, such as third-party driver managers, fixed sleeps, absolute XPath locators and Grid 3 syntax, and recommends pointing the agent at the site’s llms.txt and writing the project’s Selenium rules into an AGENTS.md.

Which to pick: a checklist

  1. Do you need real branded Safari, or Edge in Internet Explorer mode? Selenium.
  2. Is your team on Ruby or Kotlin? Selenium.
  3. Do you have a working Selenium suite and Grid? Keep them; move only the flakiest areas if a rewrite pays for itself.
  4. Starting fresh in TypeScript or JavaScript? Playwright Test.
  5. Starting fresh in Python, Java or .NET? Either works; Playwright saves wait code, Selenium keeps you on the W3C standard.
  6. Will AI agents write or run most of the tests? Playwright has the official tooling; with Selenium, give the agent the project’s rules first.

Whichever you pick, the order of what to automate first matters more than the tool. Test automation covers that, and why a flaky test should be treated as a bug.

Where the failures go

A failing or flaky browser test is work for someone, and it is easy to lose in a CI log. On fenbs, file each as a task of kind bug (BUG-), with the test name, the browser and the trace or screenshot location in the note, and a priority from 1 to 10. When it is fixed, record the test status and test notes on the task: which browsers you reran it in, and what you did not check. An AI assistant connected over MCP can do the same filing from a Playwright run, and History records it under the assistant’s name. fenbs has no CI integration, so the filing is done by a person or an assistant, not by your pipeline.

Related

An AI agent in the browser: Playwright MCP. What to automate first: test automation. The layers of testing: types of software testing. How much end-to-end coverage you need: end-to-end testing. A ready board for failures: the bug tracker template.

Questions people ask.

Is Playwright faster than Selenium?

It depends on the suite, and published comparisons rarely transfer to yours. Playwright avoids much of the waiting code that slows and destabilizes many Selenium suites, and runs tests in parallel by default on Node.js. A well-written Selenium suite with explicit waits and a Grid can still be fast.

Can Playwright test real Safari?

No. Playwright drives its own WebKit build, which is close to Safari but not the branded browser, and it says it does not work with branded Safari because it relies on patches. To test the Safari your users install, use Selenium with safaridriver on a Mac.

Does Selenium have an MCP server for AI agents?

Not an official one. Selenium’s documentation mentions community MCP servers and says they are third-party projects rather than part of the Selenium project. Playwright, by contrast, has an official MCP server published by Microsoft.

Should I migrate from Selenium to Playwright?

Only if the suite costs you more than a rewrite would. If flaky waits are the problem, try explicit waits and stable locators first. If you need branded Safari, Ruby or Kotlin, stay with Selenium. New suites in TypeScript are the clearest case for Playwright.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.