Playwright is an open-source browser-automation library, originally built by Microsoft, that drives Chromium, Firefox, and WebKit through a single API — the most common choice for headless-browser scraping today alongside Puppeteer, largely due to its auto-waiting behavior and multi-browser support.
Puppeteer, from the Chrome DevTools Protocol team at Google, only drives Chromium. Selenium is the oldest and broadest in browser support via the WebDriver protocol, but carries a heavier, more verbose API and slower startup. Playwright covers all three major engines through one consistent API and adds auto-waiting — it waits for an element to actually be visible and actionable before interacting with it, instead of requiring manual sleep or explicit-wait calls, which removes a whole class of flaky-scraper timing bugs that plague both of the other two.
That combination — one API, three engines, waits handled for you — is why new scraping projects reaching for a headless browser default to Playwright more often than not, while Puppeteer and Selenium remain common in existing codebases built before Playwright matured.
Reach for Playwright specifically when a target needs JavaScript execution to expose its data — infinite scroll, content populated by an XHR call after load, or a login flow that has to run in a real page context. For anything that doesn't need that, a plain HTTP client is faster and dramatically cheaper: spinning up a browser context costs far more CPU and memory per page than a single request.
In production, Playwright is rarely used bare — stealth patches (removing navigator.webdriver and other automation tells) and a matched proxy identity are layered on top, since a default Playwright instance is fingerprintable on its own despite driving a real browser engine.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com/products")
page.wait_for_selector("div.product-card") # auto-wait, no manual sleep
prices = page.locator("span.price").all_text_contents()
browser.close()How Crawlora handles this
Crawlora's browser-rendering tier runs this same rendering step server-side — real Chromium, stealth patches, matched residential IP — so you get the fully-rendered page or normalized JSON back without standing up and maintaining Playwright infrastructure and fingerprint patches yourself.
Related reading
Glossary
FAQ
Playwright for new projects needing multi-browser support and fewer timing bugs, thanks to auto-waiting. Puppeteer if you only need Chromium and prefer its API. Selenium mainly persists in existing codebases or when you specifically need its broader legacy browser/driver support.
By default, yes — it exposes automation tells similar to any headless browser (navigator.webdriver, headless-specific rendering quirks). Avoiding detection requires stealth patches and a consistent, realistic browser and IP configuration on top of Playwright itself.
No — only when the data isn't present in the raw HTML response, typically because JavaScript renders it client-side. Static or server-rendered pages are faster and cheaper to scrape with a plain HTTP request.
Beyond Playwright, Crawlora's own docs cover the rest of the stack — browse the APIs, test a request in Playground, and move from scraping infrastructure work to production data workflows.