Selenium vs Playwright for Web Scraping: I Ran Both

Selenium vs Playwright for web scraping, measured on the same Chrome build: timed crawls, install sizes, bot leaks, and where each tool still wins.

MMotherlode Lab10 min read
Magpie title card: Selenium vs Playwright for Web Scraping: I Ran Both, over a storefront's HTML source

Every selenium vs playwright comparison on page one repeats the same three claims: Selenium supports more languages, Playwright is faster, Selenium has the bigger community. Two of those deserve scrutiny, and one is now backwards on GitHub. So I ran both on the same Chrome build against three ordinary jobs, a ten-page catalog crawl, an infinite-scroll page, and a bot-detection check; the clock said this, and the rest of the page says where each tool still earns its keep.

The verdict

Pick Playwright for new scraping work. Auto-waits remove the most common failure mode, browser contexts give you isolated cookie jars for multi-account jobs, and network interception lets you skip images and read XHR responses straight off the wire. On the same browser and the same crawl, Selenium needed 1.8 times the wall time. If the shortlist also includes Puppeteer, that fight is narrower than it looks: Puppeteer vs Playwright.

Pick Selenium when the choice was made for you: an existing Java or C# test suite, a grid of real devices, a hard requirement that names the W3C WebDriver standard, or a shop that has ten years of Selenium code and no appetite for a rewrite.

Both leak automation signals identically. Neither survives a serious anti-bot wall without patched builds or outside help. And if a site ships its HTML in the first response, you do not need either tool; a plain HTTP client beats both of them.

Playwright Selenium
What it is Browser automation library from Microsoft, released 2020 Browser automation framework, born 2004 at ThoughtWorks
Latest versions (Oct 2026) 1.64.x (npm); my benchmark ran the 1.58.0 Python package 4.51.0
Official languages JavaScript/TypeScript, Python, Java, .NET Java, Python, C#, Ruby, JavaScript, Kotlin
Browsers Chromium, Firefox, WebKit Chrome, Firefox, Safari, Edge, Internet Explorer
License Apache-2.0 Apache-2.0
GitHub stars (2026-10-16) 97,852 34,552
Waits Auto-waits before every action You build them (WebDriverWait)
Network interception page.route, request/response capture, HAR recording Limited; CDP via devtools protocol, BiDi still maturing
Isolation Browser contexts: many cookie jars, one process One session per driver; isolate by launching more browsers
Parallelism at scale Processes or workers on one machine Selenium Grid across machines and real devices
Install footprint Python package + pinned browser build (~400 MB) Python package + ~23 MB chromedriver, auto-fetched
Debugging Codegen, trace viewer, video recording Selenium IDE (browser extension)

Selenium vs Playwright, measured on the same Chrome

The setup: WSL2, Python, Selenium 4.51.0 and Playwright 1.58.0 driving the identical Chrome for Testing 156 binary, three timed runs each in alternating order, medians reported. The jobs were deliberately ordinary. Ten paginated catalog pages with twenty products each from books.toscrape.com. One infinite-scroll page from quotes.toscrape.com, scrolled until a hundred quotes existed. A pass over bot.sannysoft.com for automation signals.

Job Playwright Selenium
10 pages, 200 products 11.9 s (11.3–12.6) 21.0 s (20.7–21.2)
Scroll to 100 quotes 2.9 s (one 11.3 s outlier) 3.4 s (2.7–6.7)
Lines of code, identical work 74 90

The static-crawl gap is architecture, not luck. Selenium speaks the WebDriver protocol over HTTP: every find_elements, every get_attribute, every .text read is a request to chromedriver and back. My loop made roughly forty of those round trips per page. Playwright holds one pipe to the browser and evaluates inside the page, so the same loop is a handful of messages. Zenrows’ independent 100-iteration benchmark landed on the same order of magnitude: about 290 ms per Playwright action against 536 ms for Selenium.

The scroll job is a wash, and I will not pretend otherwise. Both tools spent their time waiting on the site’s XHR responses; the run-to-run variance (Selenium swung between 2.7 and 6.7 seconds, one Playwright run hit 11) exceeded the gap between their medians. On jobs that are network-bound, the framework barely shows up in the numbers.

The sixteen extra lines in the Selenium script are not overhead you can skip. That is the next section.

The wait problem

Playwright waits before every action: for the element to exist, be visible, be stable, be enabled. You can override it, but the default policy means a script that works once usually keeps working. The same job, print every title on one listing page, side by side:

# Playwright
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    page = p.chromium.launch().new_page()
    page.goto("https://books.toscrape.com/")
    for card in page.locator("article.product_pod").all():
        print(card.locator("h3 a").get_attribute("title"))
# Selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
driver.get("https://books.toscrape.com/")
WebDriverWait(driver, 10).until(
    lambda d: d.find_elements(By.CSS_SELECTOR, "article.product_pod"))
for card in driver.find_elements(By.CSS_SELECTOR, "article.product_pod"):
    print(card.find_element(By.CSS_SELECTOR, "h3 a").get_attribute("title"))

Selenium hands you WebDriverWait and lets you invent your own policy per call. Skip that until line and the loop below it can run against a page whose listing has not rendered yet, because get() returns on the load event, not on the data. That is the actual mechanism behind every “Playwright is more stable” post you have read. The difference is not magic. It is that one project made waiting the default and the other made it homework.

Setup: 23 MB of driver against 400 MB of browser

pip install selenium pulled in eight packages. On first launch, Selenium Manager fetched a matching chromedriver, 23 MB into ~/.cache/selenium, and everything worked. The old “find the chromedriver that matches your Chrome version” ritual died in 2022 when Selenium 4.6 shipped; if an article still tells you to manage drivers by hand, it is older than it looks.

pip install playwright pulled in two packages and then refused to launch until playwright install downloaded its own pinned browser build. That is the design, not a bug: Playwright tests against exact browser builds, and on this disk each one occupies about 400 MB. Selenium brings no browser at all; it drives whatever Chrome you point it at.

Neither tool costs money. Both licenses are Apache-2.0.

Neither survives a real anti-bot wall

The fingerprint check, same page, both tools:

Signal Playwright Selenium
navigator.webdriver true true
User-Agent HeadlessChrome HeadlessChrome
navigator.plugins.length 5 5

Identical. The flag that says “this browser is automated” is on from the first millisecond in both, and every competent bot manager reads it before your first click. bot.sannysoft.com is a 2019-era check and it still catches both; Cloudflare and DataDome catch them faster and from more angles.

The ecosystem workarounds are forks and patches: undetected-chromedriver on the Selenium side, stealth plugins and rebrowser-style patches on the Playwright side. They work until a vendor ships a new check, then the cat-and-mouse restarts. Anyone claiming one of the two base tools is “stealthier” is selling something; at this layer my runs show them leaking the same signals. What moves the needle is the surrounding kit, from proxies to patch sets, and that is true for both. Start at how to scrape without getting blocked before you blame the framework.

Where Selenium still wins

Six official language bindings against four. Java, Python, C#, Ruby, JavaScript, and Kotlin ship from the Selenium project itself; comparisons listing PHP or Perl are counting third-party wrappers that the project does not maintain. Playwright covers JavaScript/TypeScript, Python, Java, and .NET. If your team writes C# on Windows, Selenium’s binding is the more mature one.

Real devices and legacy browsers. Through Appium, which implements the WebDriver protocol, Selenium suites drive actual Android and iOS handsets, and Grid spreads runs across machines. Playwright offers emulation of phones, which is a browser pretending, not a phone. Selenium also still talks to Internet Explorer, which nobody should want and enterprises occasionally require.

The standard and the estate. Selenium speaks the W3C WebDriver standard, and twenty-two years of enterprise QA have built on it. Zenrows counts 283,000 GitHub repositories depending on Selenium against 116,000 for Playwright; the stars run the other way (34,552 versus 97,852), which tells you where new projects are going and where the existing ones live. Job specs that say “automation engineer” mostly mean this world.

Where Playwright wins

Contexts. One browser process hosts many browser contexts, each a sealed cookie jar with its own storage. Scraping five accounts is five contexts, not five browser installs and five driver processes. This is the feature I miss most when I go back to Selenium.

The network layer. page.route blocks images, fonts, and analytics before they download, which halves bandwidth on heavy pages. Request and response capture means you can read the site’s own XHR JSON instead of parsing the HTML it produced, and record HAR files for replay. Selenium reaches the same only through CDP side doors that the project does not treat as its main API.

The debugging kit. Codegen records your clicks as code. The trace viewer replays a failed run as a film with DOM snapshots at every step, and video recording is a launch option. In Selenium, none of that is built in.

And the waits, as covered: the default that makes scripts survive redesigns.

The third option: don’t drive the browser at all

A disclosure, since we publish it: we build Magpie, a Go scraper that treats the browser as a fallback rather than a requirement. It tries a plain static fetch first and escalates to a real browser (go-rod, the same CDP family Playwright’s Chromium side belongs to) only when the page needs JavaScript to render. It respects robots.txt, throttles itself, reports a bot challenge when it detects one rather than trying to defeat it, and ships under AGPL-3.0-or-later with a commercial licence option. For article-shaped and listing-shaped pages, skipping the browser stage removes most of what Selenium and Playwright get blamed for. When you do need the browser, the comparisons above still apply in full.

FAQ

Is Playwright replacing Selenium?

No. Selenium’s installed base is enormous and sticky: two decades of Java and C# suites, Grid deployments, Appium integration. New scraping projects mostly start on Playwright; existing QA estates stay on Selenium. Plenty of shops run both, one for tests and one for scraping.

Which is faster, Playwright or Selenium?

On my runs: Selenium needed 1.8x the wall time on a ten-page crawl of server-rendered pages, and a wash on a network-bound infinite-scroll job. The gap comes from WebDriver’s HTTP round trips versus Playwright’s single pipe. Your mileage depends on how much of the job is waiting on the site.

Can websites detect Selenium or Playwright?

Yes, both, trivially. In my checks both exposed navigator.webdriver: true and a HeadlessChrome user agent immediately. Patched builds and stealth plugins raise the bar; nothing guarantees a pass against Cloudflare or DataDome.

Should I learn Selenium or Playwright first?

For scraping, Playwright: the auto-wait model, contexts, and interception carry over to everything modern. For QA employment, Selenium appears in more Java and C# job specs. The DOM concepts transfer between them in a weekend; for syntax, start with the Selenium walkthrough or the Playwright walkthrough.

Do I need a browser automation tool at all?

Not for static sites. If the data is in the first HTML response, requests or httpx plus a parser is faster, lighter, and less likely to get flagged. Browser automation earns its 400 MB only when JavaScript builds the content.

One decision rule

If a third of your target pages render content with JavaScript, take Playwright and spend the saved flakiness on the sites that fight back. If an existing Selenium estate or a real-device grid already exists, extend it; rewriting working code is its own failure mode. And before installing either, view-source on one target page: if the data is sitting in the HTML, the fastest scraper on this page is the one you never launch.

Stop renting credits.

One flat price, your machine, your keys.

Download free for Windows, macOS and Linux

Windows · macOS · Linux $49/mo flat, cancel anytime