ScreenshotNeo

BlogComparisons

Why Choose Puppeteer Over Selenium for Browser Automation?

Choose Puppeteer for JavaScript-first Chrome automation and high-level browser APIs. Choose Selenium for broader language, browser, and remote WebDriver support.

By the ScreenshotNeo team4 October 20269 min read

Choose Puppeteer when your automation project is JavaScript-centered and primarily targets Chrome. Its high-level browser API and default Chrome DevTools Protocol (CDP) support make it a direct fit for Chrome-focused scripts that need browser-specific capabilities. Choose Selenium when you need more language bindings, a wider browser matrix, or local and remote WebDriver execution through Selenium Server.

Puppeteer also supports Firefox, using WebDriver BiDi by default there. Chrome can be launched with BiDi too, but some Puppeteer APIs remain unavailable over that protocol. Neither tool is a universal speed winner: compare them using your browsers, versions, environment, and workload.

1. What Puppeteer and Selenium do

Puppeteer is a JavaScript library for controlling Chrome or Firefox through CDP or WebDriver BiDi. It runs headless by default and its standard package can download a compatible Chrome for Testing. Browser versions are mapped to Puppeteer releases, so check that mapping when pinning an environment.

Selenium WebDriver is a W3C Recommendation for browser automation. Selenium provides language bindings across its ecosystem and can drive browsers locally or remotely through Selenium Server. That makes it useful when the suite needs to be written in a language other than JavaScript or run on a remote browser infrastructure.

2. Decision guide: when Puppeteer is the better fit

Choose Puppeteer when

  • Your automation code is already JavaScript or TypeScript, and you want to keep browser scripts in the same ecosystem.
  • Chrome is the main target and you need Puppeteer’s high-level APIs or Chrome’s CDP capabilities.
  • You want to launch and control a browser directly from a script, with headless execution as the default.
  • Your team can pin Puppeteer and its corresponding browser version, and can validate upgrades against your required APIs.
  • Your required Firefox workflow uses supported Puppeteer APIs over BiDi.

Choose Selenium when

  • Your team needs language bindings beyond JavaScript.
  • Your browser matrix includes browsers such as Safari or Edge, or legacy Internet Explorer requirements that Selenium documents.
  • Remote WebDriver execution through Selenium Server is part of your test architecture.
  • You need a WebDriver-centered setup and can use the browser-specific capabilities Selenium documents.
  • Your event-stream needs fit Selenium’s evolving WebDriver BiDi implementation.

Questions to settle before choosing

  1. Which exact browsers and versions must pass? Write the browser/version matrix down. Puppeteer’s browser support and version mapping vary by release; Selenium documents browser-specific support and capabilities.
  2. Which APIs does the suite require? List network interception, console and logging events, emulation, tracing, coverage, accessibility, screenshots, and other APIs the workflow depends on. Verify protocol support rather than assuming CDP and BiDi are interchangeable.
  3. Where will browsers run? Decide whether scripts launch locally managed browsers or connect to remote WebDriver sessions.
  4. Who maintains the browser pin? Plan how framework and browser updates will be reviewed and validated.

3. Protocols and browser coverage

Decision Puppeteer Selenium
Language JavaScript library. Multiple language bindings in the WebDriver ecosystem.
Documented browsers Chrome and Firefox, with versions mapped to Puppeteer releases. Chrome, Edge, Firefox, Safari, and legacy Internet Explorer are documented with browser-specific capabilities.
Protocol CDP by default for Chrome; BiDi by default for Firefox. Chrome can use BiDi, with documented gaps. WebDriver, with WebDriver BiDi capabilities for bidirectional event use cases; implementation is evolving.
Execution Launches a browser, headless by default. Drives browsers locally or remotely through Selenium Server.
Version planning Use Puppeteer’s browser version mapping and pin compatible versions. Check the browser-specific Selenium support and capability requirements.

CDP provides Chrome-specific capabilities. Puppeteer continues to use it by default for Chrome because not all CDP features are available through BiDi. The Puppeteer BiDi support list identifies gaps in areas including tracing, coverage, accessibility, several emulation features, and CDP-specific APIs. Confirm the current support list for the exact Puppeteer version before choosing BiDi.

WebDriver BiDi is a bidirectional standard intended to support browser events and commands. Selenium documents event-stream use cases for network, logging, and scripts and describes its implementation as developing. Treat coverage as version-dependent and check the exact APIs in use.

Primary documentation: Puppeteer, Puppeteer supported browsers, Puppeteer WebDriver BiDi, Selenium WebDriver, Selenium WebDriver BiDi, and Selenium browser documentation. Check these sources at implementation time because browser and protocol support evolves.

4. Runnable JavaScript examples

The following minimal Puppeteer script opens a page, waits for its load event, and prints the page title. Install Puppeteer in a Node.js project with npm install puppeteer; the standard package downloads a compatible Chrome for Testing.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'load' });
    console.log(await page.title());
  } finally {
    await browser.close();
  }
})();

The matching Selenium example uses the JavaScript binding and ChromeDriver. Install the binding with npm install selenium-webdriver and install/configure ChromeDriver according to the Selenium browser documentation for your environment.

const { Builder, Browser } = require('selenium-webdriver');

(async () => {
  const driver = await new Builder().forBrowser(Browser.CHROME).build();
  try {
    await driver.get('https://example.com');
    console.log(await driver.getTitle());
  } finally {
    await driver.quit();
  }
})();

These examples deliberately use a simple page navigation. Add your own waits, assertions, browser options, and test-runner integration based on the application and browser matrix.

5. Practical setup and configuration

Puppeteer

  • Browser installation: The standard Puppeteer package downloads a compatible Chrome for Testing. If your environment manages browsers separately, follow the current Puppeteer installation guidance and ensure the executable matches the release mapping.
  • Headless mode: Puppeteer launches headless by default. For local diagnosis, configure launch options for a visible browser as documented for your installed release.
  • Firefox: Confirm the Puppeteer release’s Firefox support and APIs. Firefox uses BiDi by default, so CDP-only assumptions do not carry over.
  • Chrome over BiDi: Enable it only after checking the support list for each needed API; CDP remains the default for Chrome.
  • Lifecycle: Close pages and browsers in cleanup paths, including error paths, to avoid orphaned processes in repeated runs.
  • Version pinning: Pin the library and its expected browser version in CI and review both together during upgrades.

Selenium

  • Language binding: Install the binding for the language your team uses and keep its version aligned with the project’s WebDriver setup.
  • Browser driver: Configure the browser-specific driver and capabilities required by the target browser. Use Selenium’s current browser documentation rather than assuming one configuration works everywhere.
  • Remote sessions: When using Selenium Server, configure the remote endpoint and requested browser capabilities, and make sure the remote environment has the browser and driver versions needed.
  • BiDi events: Check current support for the particular event stream and command your suite needs; Selenium describes BiDi implementation as evolving.
  • Lifecycle: Always call the driver’s quit operation in a finally/cleanup block to end local or remote sessions.

6. Common failures and fixes

Symptom Likely cause What to check or fix
Puppeteer cannot launch Chrome The browser is missing, incompatible with the installed Puppeteer release, or unavailable in the runtime environment. Use the standard package installation or verify the executable and browser version against Puppeteer’s support mapping. Check the runtime’s browser dependencies and launch error output.
A Puppeteer API fails under BiDi The API is not yet supported on that protocol. Check Puppeteer’s BiDi support list. Use the documented Chrome CDP path where appropriate, or adjust the required workflow.
Firefox behavior differs from Chrome The browser engines and protocols differ; Firefox uses BiDi by default. Test against the required browser directly and avoid relying on Chrome-only APIs for cross-browser workflows.
Selenium cannot create a browser session Browser, driver, binding, or remote capabilities are missing or incompatible. Check the browser-specific Selenium setup, driver availability, requested capabilities, and remote server configuration.
Selenium BiDi event is unavailable The needed event or command may not be implemented for that browser and version. Consult current Selenium BiDi documentation and validate the exact browser/protocol combination.
Automation hangs at navigation The page may keep connections open or the chosen navigation condition may not occur. Choose a navigation wait condition that matches the page, add an explicit bounded timeout, and wait for a specific application selector when that is a better readiness signal.
CI runs out of resources or accumulates browser processes Browsers or sessions are not being closed, or too much work runs concurrently for the available resources. Close each browser/driver in cleanup, cap parallel sessions to the environment’s capacity, and inspect worker and browser logs.

7. Performance, reliability, and cost

The available official documentation does not establish a universal speed winner. A meaningful comparison must hold browser version, machine, headless/headful mode, test data, network, concurrency, and workload constant. Measure the operations your suite performs, including startup and teardown if those are part of each job.

Reliability usually depends on the browser/version matrix, readiness conditions, cleanup, and execution environment as much as on the framework. Pin versions, use bounded waits tied to meaningful page conditions, keep logs for failed sessions, and test the browsers that matter to users. Remote Selenium adds a server and network path to account for; locally launched Puppeteer places more browser lifecycle responsibility in the script environment.

Neither framework’s cited documentation provides a comparable price figure. Budget based on your chosen machines or remote browser infrastructure, the number of concurrent sessions, and ongoing maintenance of browser and driver versions. Do not infer a cost advantage from the library choice alone.

8. Screenshot alternative: ScreenshotNeo

If the job is to capture a website image or PDF rather than interact with a browser for a test, try ScreenshotNeo first. It is a website screenshot API and MCP server from Yorker Media: one GET request returns a PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Only clean shots are billed: bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

For browser interaction, use Puppeteer or Selenium. For a screenshot or PDF deliverable, an API can remove browser installation and lifecycle work. ScreenshotNeo also supports full-page capture with lazy images loaded, selector capture, device presets and custom viewports, retina scale, PDF settings, custom CSS and JavaScript, waits, request blocking, custom headers and cookies, caching, signed image links, asynchronous jobs, bulk capture, and a usage API. See the ScreenshotNeo API documentation for parameters and setup.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.

9. Frequently asked questions

Is Puppeteer only for Chrome?

No. Current Puppeteer documentation covers Chrome and Firefox. The protocol differs: CDP is the default for Chrome and WebDriver BiDi for Firefox.

Can Puppeteer use WebDriver BiDi with Chrome?

Yes, but some APIs remain unsupported over BiDi. Check the current feature list for the exact APIs your script requires.

Is Selenium required for cross-browser testing?

No single framework choice replaces checking the required browser and capability matrix. Puppeteer documents Chrome and Firefox; Selenium documents a broader set including Edge and Safari. Pick based on the actual browsers and APIs the suite must cover.

Which framework is faster?

The cited documentation does not support a universal answer. Compare both under the same browser versions, environment, and representative workload.

Should a screenshot task use browser automation?

Use browser automation when the task needs interaction or test assertions. For a rendered image or PDF, a screenshot API such as ScreenshotNeo can handle capture without you managing a browser process.