All comparisons
Comparison

playwright vs puppeteer: a test runner versus a browser control library

Playwright is a framework that bundles a test runner, browser library, coding-agent CLI and MCP server behind one install. Puppeteer is a library that drives Chrome or Firefox over the DevTools Protocol or WebDriver BiDi and ships no runner, assertions or reporting. Pick Playwright for cross-browser end-to-end testing; pick Puppeteer when you are scripting a browser from Node.js.

Published September 29, 2026

At a glance

Projectmicrosoft/playwrightpuppeteer/puppeteer
LicenceApache-2.0Permissive: commercial use allowedApache-2.0Permissive: commercial use allowed
MaintenanceCommits in the last six monthsLast push November 7, 2026Commits in the last dayLast push November 7, 2026
LanguageTypeScriptTypeScript
GitHub stars99,53795,811
Read moreOur analysisGitHubOur analysisGitHub

Star history

  • microsoft/playwright99,537 ★ · +5,932
  • puppeteer/puppeteer95,811 ★ · +480
Star history
Repository2026-07-222026-11-07
microsoft/playwright93.6k99.5k
puppeteer/puppeteer95.3k95.8k

Open the full Star history comparison

Which one to choose

playwright

Choose playwright if you need cross-browser end-to-end tests, want auto-waiting and web-first assertions without assembling a stack, or want an AI agent to drive a real browser through the CLI or MCP server.

puppeteer

Choose puppeteer if you are writing Node.js scripts that control Chrome or Firefox and want a high-level API over the DevTools Protocol or WebDriver BiDi, without a test runner attached.

One is a framework with four entry points, the other is a library

Playwright is a Microsoft-published, Apache-2.0 browser automation framework. The README presents four entry points: Playwright Test for end-to-end testing, Playwright CLI for coding agents such as Claude Code and Copilot, Playwright MCP for LLM-driven automation, and Playwright Library for browser automation scripts. A VS Code extension covers authoring and debugging. The install is one command, and the decision is mostly about which of those entry points your team actually needs. Playwright Test runs tests across Chromium, Firefox and WebKit with full browser isolation, auto-waiting and web-first assertions. The CLI is designed to be more token-efficient than MCP because commands avoid loading large tool schemas and accessibility trees into the model context. The MCP server lets agents interact with pages using structured accessibility snapshots, so no vision model or screenshots are required. Puppeteer is a JavaScript library providing a high-level API to control Chrome or Firefox over the DevTools Protocol or WebDriver BiDi, running headless by default. It ships no test runner, no assertions and no reporting layer. Our analysis of puppeteer says teams that expect those from the package will be disappointed. This is the core difference: Playwright is a testing framework that also exposes a library, while Puppeteer is a browser control library that leaves the test stack to you.

Installing each one, and the browser binary question

Playwright Test installs with npm init playwright@latest, or manually with npm i -D @playwright/test followed by npx playwright install. The CLI installs globally with npm i -g @playwright/cli@latest, and playwright-cli install --skills adds richer agent integration. The MCP server needs no install at all: add npx @playwright/mcp@latest to your MCP client configuration. Our analysis of playwright says you should run npx playwright install on the CI image you actually use, confirm Node is at least 20, and decide whether trace artefacts go into your existing report storage. Puppeteer installs with npm i puppeteer, which downloads a compatible Chrome during installation, or npm i puppeteer-core, which downloads nothing and expects you to supply the browser. The README notes that modern package managers, including npm, pnpm, Yarn, Bun and Deno, block dependency install scripts by default. If that script is blocked, the browser is not downloaded and runtime errors follow. The workaround is npx puppeteer browsers install after installation, or adding "puppeteer" to "allowScripts" in package.json. Our analysis of puppeteer says you should verify that your package manager runs the install script, or accept running npx puppeteer browsers install yourself, and confirm which binary you intend to drive, because puppeteer-core downloads nothing. Playwright's browser download is an explicit, separate step; Puppeteer's is tied to a lifecycle script that many package managers now refuse.

Writing and running tests versus writing scripts

Playwright Test starts from a config file and a test file. The README example imports test and expect, navigates to a URL, and asserts on the page title and on a heading after a click. Tests run in parallel across all configured browsers, headless by default, and each test gets a fresh browser context, which the README describes as full isolation with near-zero overhead. Locators are written the way users see the page: getByRole, getByLabel, getByPlaceholder, getByTestId. Authentication state can be saved once with storageState and reused across tests. Tracing captures execution traces, screenshots and videos on failure, inspectable in the Trace Viewer via npx playwright show-trace trace.zip. Auto-waiting means no artificial timeouts, and assertions retry until conditions are met. Puppeteer's README example is a script: launch the browser, open a page, navigate to a URL, set the viewport, press a key, fill a locator written as ::-p-aria(Search), then wait and click. There is no test function, no assertion library, no parallel runner and no trace viewer in the package. You can build all of that around Puppeteer, and many teams do, but you are choosing and wiring the pieces. Our analysis of puppeteer states plainly that it is the wrong tool when you need a cross-browser test runner out of the box.

Operations, scaling and what lands in CI

Playwright's operational surface is wide because the framework owns the run. Tests parallelise by default across configured browsers. Each test gets a fresh context, which limits cross-test contamination. Trace, screenshot and video capture are configured in playwright.config.ts, for example trace: 'on-first-retry', so artefacts appear only when a retry happens. The CLI adds playwright-cli show, a visual dashboard with live screencast previews of all running browser sessions, where clicking a session zooms in for remote control. The MCP server exposes structured accessibility snapshots to an agent instead of pixels. Puppeteer's operational surface is narrower by design. It runs headless by default, and the README example sets a viewport explicitly. Session management, retries, parallelism, artefact retention and reporting are your responsibility. Puppeteer does offer an MCP path: the README points to chrome-devtools-mcp, a Puppeteer-based MCP server for browser automation and debugging, and notes experimental WebMCP support. The difference in scaling is therefore one of ownership. Playwright gives you a runner with parallelism and artefact capture built in. Puppeteer gives you a browser handle and expects your own orchestration around it. For a small scraping job the second is lighter. For a suite that must run on every pull request across three engines, the first removes work you would otherwise write.

Where each one falls short

Playwright's constraint is scope. Our analysis of playwright says to skip it if you only need HTTP-level checks, because pulling a browser and a runner into that job is unnecessary weight. It also flags a platform risk: if the WebKit build is a hard requirement on a platform where the download fails and you have no fallback, Playwright is the wrong fit. The framework also expects Node 20 or newer, and trace artefacts need somewhere to live, which is a storage decision rather than a default. Puppeteer's constraint is the opposite: it is a library, so everything above the browser is missing. No runner, no assertions, no reporting. Teams that install it expecting a testing framework will find themselves assembling one. The install-script problem is a second, sharper edge: because npm, pnpm, Yarn, Bun and Deno block dependency install scripts by default, a plain npm i puppeteer can leave you without a browser and with runtime errors that look unrelated to installation. Puppeteer also centres on Chrome and Firefox, where Playwright's single API covers Chromium, Firefox and WebKit. Neither project is archived, and both repositories show recent pushes in the facts table above, but the maintenance question differs in kind: Playwright carries a test runner, a CLI and an MCP server as first-party surfaces, while Puppeteer's MCP story routes through chrome-devtools-mcp, a separate repository.

Licence and maintenance implications

Both projects ship under Apache-2.0, so the licence itself does not separate them: permissive terms, patent grant included, no copyleft obligation on your test code or scripts. The practical difference is what you are maintaining. Adopting Playwright means adopting four surfaces that Microsoft publishes: the test runner, the library, the coding-agent CLI and the MCP server. Each has its own install path and its own release cadence, and the facts table shows recent releases on the main repository. Our analysis of playwright frames the decision as choosing which of those entry points your team actually needs, which is also a maintenance decision: every entry point you enable is something your CI and your documentation must track. Adopting Puppeteer means adopting one library plus a browser binary you are responsible for provisioning. The README's install-script warning is the maintenance consequence in miniature: package managers are tightening default behaviour, and Puppeteer's browser download depends on a lifecycle script those managers now block. You either allow the script or run npx puppeteer browsers install in every environment. Puppeteer's MCP support sits in chrome-devtools-mcp, so agent-driven browser work through Puppeteer means tracking a second repository. Playwright's MCP server is first-party. Neither repository is archived, and both were pushed recently, so the choice is about which maintenance surface matches your team's capacity.

Choosing for concrete scenarios

A team adding end-to-end coverage to a web application across Chromium, Firefox and WebKit should start with Playwright Test. The runner, isolation, auto-waiting, locators, storageState reuse and trace viewer are already there, and the install is one command. A team that wants an AI coding agent to drive a real browser should look at Playwright CLI for token efficiency or Playwright MCP for accessibility-snapshot control, depending on whether the agent works from a shell or an MCP client. A team writing a Node.js script to log into a site, render a page, capture a PDF or scrape structured data is better served by Puppeteer, especially puppeteer-core when the browser binary is already managed by the environment. A team that needs both is not choosing: the two can coexist in one repository, with Playwright covering the test suite and Puppeteer covering a production script or a service that renders pages. For HTTP-level checks, neither is needed. Our analysis of playwright says to confirm Node is at least 20 and to run npx playwright install on the actual CI image before committing. Our analysis of puppeteer says to confirm your package manager runs the install script, or plan to run npx puppeteer browsers install, and to decide which browser binary you are driving.

Bottom line

Pick Playwright when the job is cross-browser end-to-end testing or agent-driven browser control, because the runner, assertions, isolation and trace viewer arrive together. Pick Puppeteer when the job is a Node.js script that drives Chrome or Firefox and you want no runner attached. Verify first: on Playwright, that Node is at least 20 and npx playwright install succeeds on your CI image; on Puppeteer, that your package manager runs the install script or that you will run npx puppeteer browsers install yourself, and which browser binary you intend to drive.

Sources

  1. microsoft/playwright repository
  2. microsoft/playwright README
  3. puppeteer/puppeteer repository
  4. puppeteer/puppeteer README

Was this useful?