Skip to main content

Browser Automation for Web Scraping: Playwright, Puppeteer, and Selenium Deep Dive (2026)

· 7 min read
Yassine El Haddad
Software Developer & Automation Specialist

I build production AI agents, web scrapers, and automation pipelines. Most of what I publish here comes from the actual problems they run into: proxies that get banned, anti-bot stacks that fingerprint your client, RAG that drifts when the underlying data moves. Stack: Python, TypeScript, Go, FastAPI, LangChain, Crawlee, Playwright, deployed on AWS, GCP, and Cloudflare.

When simple HTTP requests fail — because content is JavaScript-rendered, login is required, or pagination is AJAX-driven — you need a real browser. Playwright, Puppeteer, and Selenium are the three dominant tools. This deep dive covers when to use each, advanced techniques (network interception, CDP access, fingerprint evasion), and how to run them at scale on Apify.

When You Need Browser Automation (vs Simple HTTP)

ScenarioHTTP (Cheerio, requests)Browser (Playwright, Puppeteer)
Static HTML✅ Fast, cheap❌ Overkill
JavaScript-rendered content❌ Sees empty DOM✅ Renders full page
Login flows❌ Session/cookies complex✅ Native form fill, cookies
Infinite scroll❌ Can't emulate scroll✅ page.evaluate scroll
AJAX pagination❌ Hard to trigger✅ Click "Next", wait for load
Dynamic price loading❌ Often misses data✅ Waits for render
Anti-bot detection❌ Easily fingerprinted⚠️ Still detectable; use stealth

Rule of thumb: Try HTTP first. If the target requires JS execution or interaction, use a browser. See Playwright vs Puppeteer vs Selenium 2026 for a full comparison.

Playwright Deep Dive

Playwright is Microsoft's multi-browser framework. It supports Chromium, Firefox, and WebKit from a single API. Default choice for new scraping projects in 2026.

Key features:

  • Auto-wait: Actions wait for elements to be actionable (visible, stable, not obscured). No manual waitForSelector for clicks.
  • Network interception: page.route() to block resources, mock responses, or log requests.
  • Request mocking: page.route('**/api/prices', route => route.fulfill({ body: '...' })) for testing.
  • CDP access: page.context().newCDPSession(page) for Chrome DevTools Protocol.
  • Codegen: npx playwright codegen records interactions into scripts.
  • Trace viewer: trace: 'on' for post-mortem debugging.

Network optimization for scraping:

await page.route('**/*.{png,jpg,jpeg,gif,svg,css,woff,woff2}', route => route.abort());

Block images, fonts, and CSS. Pages load 2–3x faster. Content and structure remain.

Apify integration: Crawlee's PlaywrightCrawler uses Playwright. Deploy to Apify Actors for production. See building Apify Actor with TypeScript.

Puppeteer Deep Dive

Puppeteer is Google's Chrome automation library. Connects via Chrome DevTools Protocol (CDP).

Key features:

  • Chrome and Firefox: Node.js only. Python via pyppeteer (community).
  • Raw CDP access: page._client for low-level protocol calls.
  • Lighter weight: Smaller binary, faster cold start in some benchmarks.
  • No built-in test runner: Use Jest, Mocha, or custom scripts.

page.evaluate() for DOM manipulation:

const data = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.item')).map(el => ({
title: el.querySelector('.title')?.textContent,
price: el.querySelector('.price')?.textContent
}));
});

Puppeteer suits teams that need tight CDP control or already run Chrome-only pipelines. For multi-browser and scraping at scale, Playwright is usually better.

Selenium Deep Dive

Selenium uses the W3C WebDriver protocol. A driver binary (chromedriver, geckodriver) sits between your code and the browser.

Key features:

  • Language bindings: Python, Java, C#, Ruby, JavaScript. Strong for Java/C# enterprises.
  • Grid: Parallel execution across multiple machines for testing.
  • Legacy ecosystem: Huge install base, many integrations.

WebDriver flow:

  1. Start driver (e.g., webdriver.Chrome()).
  2. Navigate, find elements, interact.
  3. No auto-wait by default — use WebDriverWait and expected_conditions.
  4. StaleElementReferenceException when DOM changes between find and use — re-query.

Selenium remains for teams with existing test suites or Java/C# stacks. New projects should prefer Playwright.

When to Use Each Tool

Playwright: Default for new projects. Best DX, auto-wait, Crawlee integration, multi-browser. Use when you don't have strong reasons to choose otherwise.

Puppeteer: Choose if you need raw CDP (e.g., performance profiling, network capture) or have an existing Puppeteer codebase. Slightly lighter footprint. Chrome-focused.

Selenium: Choose if your team is Python/Java/C# dominant and Playwright adoption is blocked, or you're maintaining legacy Selenium suites. WebDriver Grid for distributed testing is mature. For scraping specifically, migration to Playwright usually pays off.

Browser Pooling

Reusing browser instances improves throughput. Instead of launching a new browser per page:

  • Playwright: One browser, multiple browserContexts. Each context = isolated session (cookies, storage). Share browser process.
  • Puppeteer: Similar. browser.newPage() is cheap; puppeteer.launch() is expensive.
  • Crawlee: Manages browser pool automatically. Set maxConcurrency and useSessionPool.

Network Optimization

OptimizationEffectTrade-off
Block images40–60% faster loadNone for scraping
Block CSS10–20% fasterMay break layout-dependent selectors
Block fonts5–10% fasterNegligible
Request interceptionSkip tracking scriptsSlightly more complex setup

Playwright example:

await page.route('**/*', route => {
const type = route.request().resourceType();
if (['image', 'stylesheet', 'font'].includes(type)) route.abort();
else route.continue();
});

Fingerprint Evasion

Sites detect automation via WebDriver flags, viewport, plugins, and behavior. Mitigations:

  • playwright-extra stealth: playwright-extra with stealth plugin patches common detection points.
  • camoufox: Firefox build with anti-fingerprinting. Works with Playwright.
  • User agent rotation: Vary UA per run. Don't use default "HeadlessChrome".
  • Viewport randomization: Vary width/height slightly.
  • Residential proxies: Harder to block than datacenter. See proxy configuration guide.

No solution is perfect. Sophisticated anti-bot systems evolve. Use reasonable request rates and back off on blocks.

Performance Benchmarks

ToolPages/min (equivalent setup)Cold startMemory
Playwright~45–552–3s~150MB/browser
Puppeteer~50–601.5–2.5s~120MB/browser
Selenium~35–452–4s~180MB/browser

Rough estimates; depends on site, concurrency, proxy. Playwright and Puppeteer are close; Selenium is typically slower due to WebDriver overhead.

For a detailed comparison table, see Playwright vs Puppeteer vs Selenium 2026.

Apify Integration

Run Playwright in Apify Actors with Crawlee:

  • Crawlee PlaywrightCrawler: Built-in retries, proxy rotation, session pools.
  • Persistent browser pools: Apify manages compute. Scale to hundreds of parallel pages.
  • Storage: Datasets, Key-Value stores, RequestQueues natively integrated.

For production resilience, add error handling: failedRequestHandler, maxRequestRetries, webhooks on ACTOR.RUN.FAILED.

Browser Automation Comparison Table

AspectPlaywrightPuppeteerSelenium
BrowsersChromium, Firefox, WebKitChrome, FirefoxAny WebDriver-compatible
LanguagesJS, Python, .NET, JavaJS (pyppeteer for Python)Python, Java, C#, Ruby, JS
Auto-wait✅ Built-in❌ Manual❌ Manual
CDP access✅ Via session✅ Direct⚠️ Chrome-only
Network block✅ page.route()✅ page.setRequestInterception()❌ Limited
Apify/Crawlee✅ Native✅ Supported⚠️ Custom
Best forNew scraping, multi-browserChrome-only, CDPLegacy, Java/C#

Winner for scraping: Playwright. Auto-wait reduces flakiness. Crawlee integration is first-class. Multi-browser is a bonus.

Apify Affiliate Banner 728x90Apify Affiliate Banner 728x90Apify Affiliate Banner 300x50Apify Affiliate Banner 300x50
Default to Playwright

For new web scraping projects, use Playwright. It has the best DX, auto-wait eliminates most timing bugs, and Apify's Crawlee is built around it. Use Puppeteer only if you need raw CDP or have an existing Puppeteer codebase.



Run Playwright on Apify | Stagehand AI Automation

Frequently Asked Questions

When the target requires JavaScript execution (SPAs), login flows, infinite scroll, or AJAX pagination. If the page returns full HTML with data in the initial response, HTTP (Cheerio, requests) is faster and cheaper.

Block images, CSS, and fonts via page.route(). Use multiple browser contexts. Increase concurrency. Consider Cheerio if the page works without JS. For anti-bot sites, you may need to slow down.

Playwright supports Chromium, Firefox, and WebKit; has auto-wait; better Crawlee integration. Puppeteer is Chrome-first, lighter, with direct CDP access. For scraping, Playwright is usually the better choice.

Apify and Crawlee are optimized for Playwright/Puppeteer. You can run Selenium in a custom Actor (Docker image with Chrome + chromedriver), but you lose Crawlee's built-in retries, proxy config, and storage. Prefer Playwright for new projects.

Use playwright-extra stealth or camoufox. Rotate user agents and viewports. Use residential proxies. Add human-like delays. Limit concurrency. Some sites are unbeatable; consider official APIs or data providers.

Common mistakes and fixes

Playwright tests flaky or timeout

Use auto-wait; avoid page.waitForTimeout. Prefer waitForSelector or waitForLoadState. Check for race conditions and dynamic content.

Puppeteer detected as bot

Use playwright-extra stealth plugin or camoufox. Rotate user agents. Consider residential proxies. Block images/CSS for speed.

Selenium StaleElementReferenceException

Re-query elements before use. Use explicit WebDriverWait. Consider migrating to Playwright for native auto-wait.