Guide · Scraping practice
Playwright vs Puppeteer vs Selenium for web scraping
For new scraping code, Playwright is often the most convenient of the three: it drives Chromium, Firefox and WebKit from JavaScript, Python, Java or .NET, waits for elements before acting, and takes an authenticated proxy per browser or per context. Puppeteer suits JavaScript teams working mainly with Chrome, with proxy credentials supplied per page. Selenium implements the W3C WebDriver standard, covers the most languages and existing test grids, but has no field for proxy credentials. All three render pages in a real browser, which costs far more bandwidth than an HTTP client — so first check whether you need a browser at all.
Reviewed 30 Oct 2026
The short answer
- Use a browser only when the data is built client-side and you cannot find the JSON request behind it.
- Playwright:
proxywithserver,usernameandpasswordon launch or on each new context. - Puppeteer:
--proxy-server(orproxyServerper browser context) for the address,page.authenticate()for credentials on every page. - Selenium:
options.proxytakes host and port only; authenticated proxies need a local forwarder that adds the credentials. - The choice usually follows your team's language and existing infrastructure more than any feature gap.
The three tools side by side
| Aspect | Playwright | Puppeteer | Selenium |
|---|---|---|---|
| Languages | JavaScript/TypeScript, Python, Java, .NET | JavaScript/TypeScript | Java, Python, C#, Ruby, JavaScript |
| Browsers | Chromium, Firefox, WebKit | Chrome, Firefox | Chrome, Firefox, Edge, Safari via their drivers |
| Control | Its own browser builds, installed with playwright install | Chrome DevTools Protocol or WebDriver BiDi | W3C WebDriver, plus WebDriver BiDi |
| Waiting | Actionability checks before every action | Locators wait for element state before acting | Explicit waits; implicit wait defaults to 0 |
| Proxy credentials | username and password fields | page.authenticate() per page | No field; local forwarder |
| Proxy per isolated context | Yes, new_context(proxy=…) | Yes, createBrowserContext({ proxyServer }) | One proxy per driver session |
| Request blocking | route() | Request interception | Through WebDriver BiDi; support varies by language binding |
How each tool takes a proxy
Playwright documents a proxy option that can be set globally for the browser or per browser context, with server, username and password. It answers the proxy's authentication challenge itself. One context per task, each with its own sticky-session username, gives each task its own exit and cookie jar. Details and code: Playwright proxy setup.
Puppeteer passes the proxy address to Chrome as --proxy-server or per context as proxyServer; Chrome's flag has no place for credentials, so they go to page.authenticate(), which must be called on every new page before its first navigation. See Puppeteer proxy setup.
Selenium sets host and port through its proxy capability, but neither that capability nor Chrome's flag carries a username and password. The dependable pattern is a small local forwarder that Selenium talks to without credentials and that adds them on the way to the gateway. See Selenium proxy setup.
Waiting, network control and bandwidth
Scrapers fail most often on timing: the element is not there yet. Playwright performs actionability checks before each action and waits for them to pass. Puppeteer's locator API likewise waits — for example for an element to be enabled and to have a stable position — before clicking. Selenium leaves it to you: its documentation describes an implicit wait that defaults to zero and explicit waits for specific conditions, and warns against mixing the two.
Network control decides your bandwidth bill. Blocking images, media and fonts is one line in Playwright's route() and a request-interception handler in Puppeteer; Selenium can intercept requests through WebDriver BiDi, with support that varies by language binding. A rendered page with assets is megabytes against kilobytes for its HTML, so blocking is worth doing in any of them — see how to reduce proxy bandwidth.
Concurrency and sessions
- Playwright contexts are isolated — separate cookies and storage — and cheap to create, so one browser can run many tasks, each with its own proxy username and sticky session.
- Puppeteer browser contexts give the same isolation, and
proxyServerper context lets each use its own exit; rememberauthenticate()on each page. - Selenium isolates per driver session, which means one browser process per concurrent task and one forwarder or proxy setting per session. Selenium Grid distributes sessions across machines if you already run one.
Which one to choose
- Python or .NET team, new project: Playwright. If you already use Scrapy, scrapy-playwright adds rendering to the requests that need it.
- Node.js team, Chrome-centred, existing Puppeteer code: Puppeteer.
- Existing Selenium test suite or Grid, Java, C# or Ruby codebase: Selenium, with a local forwarder for proxy credentials.
- Data available in HTML or a JSON endpoint: none of them — use an HTTP client. A headless browser is the expensive fallback, not the default.
FAQ
Questions
Something not covered? Write to contact@arcproxies.io.
Is Playwright better than Selenium for scraping?
For new scraping code it is often more convenient: built-in waiting, isolated contexts and proxy credentials in the launch options. Selenium is the better fit when you already run Selenium infrastructure or work in a language Playwright does not support, such as Ruby.
Can Puppeteer use a proxy with a username and password?
Yes. Pass the proxy address with --proxy-server or as proxyServer on a browser context, then call page.authenticate() with the username and password on each page before it navigates.
Does Selenium support authenticated proxies?
Not directly. Selenium's proxy capability takes a host and port but no credentials. The usual approach is a local forwarding proxy that adds the credentials to each request on its way to the upstream proxy.
Which of the three is fastest?
There is no general answer: page load time is dominated by the site, the network and what you block, not by the automation library. Measure on your own targets with the same browser and blocking rules in each.
Can I use Playwright from Python?
Yes. Playwright has official libraries for Python, Node.js, Java and .NET, all with the same proxy options on launch and on new contexts.
Do I need a headless browser for web scraping?
Only when the content is built by JavaScript and you cannot request the underlying data directly. Many dynamic pages load their data from a JSON endpoint you can call with an HTTP client at a fraction of the bandwidth.
Sources & review
Last reviewed by the ARC Proxies team. Prices are read from the live catalog at build time.
- [1]Playwright: Network: HTTP proxy
- [2]Playwright: Auto-waiting (actionability checks)
- [3]Puppeteer: Puppeteer — introduction
- [4]Puppeteer: Page interactions: locators
- [5]Selenium: Waiting strategies
- [6]W3C: WebDriver
Next
Where to go from here
Guides