
The short answer, before anything else: for new scraping projects in 2026, Playwright is the default; Puppeteer keeps Chrome-only Node pipelines; Selenium stays wherever language breadth or existing Grid infrastructure demands it. The differences that decide are the protocol (WebDriver's extra hop against direct CDP), the languages, and the stealth ecosystems.
One scenario cuts across all three identically: data behind logins you own. All three start clean browsers, so all three hand you login scripting and cookie maintenance; ego (lite) deletes that part, free: every site you've signed into stays signed in, and the agent works in its own isolated Space.
Every scraping team eventually holds this three-way debate, usually with one member defending the Selenium suite they've run for a decade, one who came up on Puppeteer, and one who read that Playwright won.
All three positions have merit, because the tools were built in different eras for different jobs: Selenium (2004) for cross-browser testing breadth, Puppeteer (2017) for direct Chrome control, Playwright (2020) for modern-web reliability.
How do the three architectures differ?

Selenium speaks the WebDriver protocol: your script sends JSON-over-HTTP commands to a browser-specific driver binary, which relays them to the browser. That indirection is why Selenium runs everywhere (any browser that ships a driver, including legacy ones), and why every single command pays a network round trip through an intermediary.
Puppeteer and Playwright skip the middleman and speak Chrome DevTools Protocol (Playwright uses equivalent direct channels for Firefox and WebKit): a persistent connection, lower per-command latency, and access to browser internals WebDriver never exposed, like network interception without a proxy.
For a test suite running dozens of steps, the protocol difference is a rounding error. For a scraper executing millions of commands across thousands of pages, per-command overhead and connection stability compound into real throughput differences, which is why scraping infrastructure drifted CDP-ward years before the testing world did.
One fairness note on trajectory: the gap is narrowing. WebDriver BiDi, the W3C's bidirectional successor protocol, is landing across the Selenium ecosystem and already powers things like console and network capture in Selenium-based tooling such as mcp-selenium's diagnostics tool. The architecture argument above describes 2026's shipping reality, not a law of nature.
Protocols are destiny at scale.
How do they compare on the scraping matrix?
Five rows cover what scraping teams actually ask. Each cell includes the limitation, because that's the half that decides.
| Dimension | Selenium | Puppeteer | Playwright |
|---|---|---|---|
| Languages | 7+: Java, Python, C#, JS, Ruby, Perl, PHP | JS/TS only; Python port unofficial and lagging | 5 official with parity: JS/TS, Python, Java, C# |
| Browsers | Broadest, including legacy (IE, older Edge) | Chrome-first; Firefox beta, no WebKit | Chromium, Firefox, WebKit; no legacy browsers |
| Waiting model | Manual: implicit, explicit, fluent waits you compose | Manual: explicit waitForSelector calls | Auto-wait with actionability checks before every action |
| Stealth ecosystem | undetected-chromedriver, SeleniumBase | puppeteer-extra-plugin-stealth, the classic | playwright-extra, plus current forks (Patchright, Camoufox) |
| Parallel sessions | Grid: mature but heavyweight infrastructure | Process-per-browser typical; contexts less ergonomic | Browser contexts: cheap isolated sessions in one process |
The waiting row is worth seeing in code, because it's the row that produces 2 a.m. pages. The same guarded click in each:
# Selenium: you compose the wait
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#load-more"))).click()
// Puppeteer: you remember the wait
await page.waitForSelector('#load-more', { visible: true })
await page.click('#load-more')
// Playwright: the wait is the action
await page.click('#load-more')Multiply that difference by every interactive element in a 30-site scraper portfolio, written partly by juniors or coding agents, and you've explained most real-world flake-rate gaps between the three stacks.
What are the pros and cons of each?

Selenium.
Pros: unmatched language and browser breadth, twenty years of infrastructure patterns (Grid), and the largest install base of automation skills in the industry. Cons: the WebDriver hop costs latency at scraping scale, waits are entirely your discipline, and the modern scraping tooling wave (agent integrations included) ships elsewhere first.
Puppeteer.
Pros: direct CDP speed on Chrome, the most battle-tested stealth classic, and the deepest pile of scraping recipes on the internet. Cons: JavaScript only, Chrome-first with Firefox in beta, and manual waiting that turns hurried code into flaky scrapers.
Playwright.
Pros: auto-waiting kills the flake class the other two make you manage, browser contexts make parallel session fleets cheap, five official languages, and the current stealth-fork generation targets it. Cons: youngest scraping folklore of the three, heavier install (it manages its own browser builds), and no legacy browser story at all.
Which should you pick for scraping in 2026?
By situation, since that's how the decision actually arrives. Starting fresh with no constraints: Playwright, for auto-waiting plus contexts plus the active stealth scene; that combination is why it's become the default recommendation across scraping guides.
Node shop, Chrome targets, screenshot-heavy: Puppeteer remains excellent, and its per-capture speed advantage is real.
Team writes Ruby or PHP, or scraping rides on existing Selenium Grid infrastructure: Selenium, without embarrassment; the WebDriver tax is invisible until your volumes are large, and infrastructure you've already amortized beats infrastructure you haven't built.
The trap to avoid is migrating a working stack for identity reasons. All three scrape competently; switching costs are real; move when a specific limit (language, flake rate, parallelism cost) actually binds, and measure that limit on your own targets before the rewrite, not after.
What about your own logged-in sources?
One scenario cuts across all three identically: the data lives behind logins you own (vendor portals, dashboards, member communities). Selenium, Puppeteer, and Playwright all start clean browsers, so all three hand you the same chores: script the login, persist the cookies, patch it when 2FA or session policy changes.
That maintenance is the part ego (lite) deletes. It's a free browser built for sharing your logged-in browser state with AI agents like Claude Code and Codex: every site you've signed into stays signed in, the agent inherits that state and works in its own isolated Space, and it drives the browser by writing JavaScript through the ego-browser skill, with whole workflows running outside the model's context.
Here's what the ego-browser skill actually looks like in practice: a real ego-browser session against a live page today, task written as JavaScript and piped in, with only the extracted fields coming back, not a page dump.
ego-browser nodejs <<'EOF'
const task = await egoBrowser.newTaskSpace('evidence-egobrowser-hn')
console.log({ taskSpaceId: task.id })
await task.page.goto('https://news.ycombinator.com/', { waitUntil: 'load', timeout: 20000 })
const title = await task.page.title()
const topStory = await task.page.locator('.athing .titleline > a').first().innerText()
const points = await task.page.locator('.subtext .score').first().innerText().catch(() => null)
console.log({ title, url: task.page.url(), topStory, points })
EOF
# Real output
{
"taskSpaceId": 13
}
{
"title": "Hacker News",
"url": "https://news.ycombinator.com/",
"topStory": "Qwen 3.8 27B",
"points": "412 points"
}It doesn't replace any of the three for large-scale public scraping or CI test infrastructure; it replaces the login-scripting half of the job for sources where the account is yours.
See ego (lite) vs Selenium, or download ego (lite) for Mac, free.
FAQ
Which is better, Selenium or Puppeteer?
For Chrome-only scraping in a JavaScript codebase, Puppeteer: direct CDP control without the WebDriver hop. For anything needing other languages, other browsers, or existing Grid infrastructure, Selenium. They're rarely both viable for the same team, which makes this the easier of the pairwise calls.
What are Playwright vs Selenium pros and cons in short?
Playwright: auto-waiting, cheap parallel contexts, modern tooling; but no legacy browsers and younger folklore. Selenium: widest languages and browsers, mature Grid; but per-command WebDriver overhead and fully manual waiting. New scraping projects lean Playwright; established Selenium estates rarely benefit from moving.
Is Selenium too slow for web scraping?
Not too slow, just taxed: the JSON-over-HTTP driver hop adds per-command latency that CDP tools skip. At small and medium volumes it's unnoticeable; at millions of commands it's a real line item, and that's the scale where teams migrate.
Which of the three works best with AI coding agents?
Playwright, by infrastructure: its MCP server and CLI are first-party and maintained, while Puppeteer's reference MCP server is deprecated and Selenium's is community-run. Auto-waiting also makes agent-written Playwright scripts flake less. Selenium shops can still connect agents through the community mcp-selenium; our Selenium MCP guide covers that setup.
Is Playwright replacing Selenium?
In new-project defaults, largely yes; in installed base, no. Selenium's language breadth, Grid infrastructure, and two decades of institutional knowledge keep it running enormous estates that have no reason to move. The accurate statement is that the frontier shifted, not that the incumbent died.
Do any of the three handle CAPTCHAs or bot walls automatically?
No. Stealth plugins reduce fingerprint signals; none defeats protocol-level detection reliably, and CAPTCHA solving means third-party services with their own terms. Scope your scraping to targets that tolerate it, and use your own authenticated access (not automation tricks) for sources where you have accounts.

