Open-source project
puppeteer/puppeteer avatar
puppeteer/puppeteer

Puppeteer: a JavaScript API for Chrome and Firefox

JavaScript API for Chrome and Firefox

95,621 stars9,579 forksTypeScriptApache-2.0

At a glance

What is it?
Puppeteer drives Chrome or Firefox over the DevTools Protocol or WebDriver BiDi from Node.js. It is the right tool when you need a scripted browser, and the wrong one when you need a cross-browser test runner out of the box.
Who is it for?
Adopt Puppeteer if you are scripting Chrome or Firefox from Node.js and want a high-level API over the DevTools Protocol or WebDriver BiDi. Do not adopt it if you need a test runner, assertions or a reporting layer; Puppeteer ships none of those, and teams that expect them from the package will be disappointed.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Puppeteer solves, and who it is for

Puppeteer exists for the case where you need a browser under program control and you are writing JavaScript or TypeScript. The README describes it as "a JavaScript library which provides a high-level API to control Chrome or Firefox over the DevTools Protocol or WebDriver BiDi", and it runs headless by default, meaning no visible UI. That combination covers a lot of ground: scraping pages that render client-side, generating PDFs, taking screenshots, filling forms, checking what a page looks like at a given viewport, or driving a browser as part of a larger pipeline. The audience is developers who are comfortable in Node.js and who want to talk to a browser directly rather than through a test framework. The API is deliberately lower level than a test runner. There is no assertion library, no test file discovery, no reporter. You get browser control and you build the rest. That is the design, not a gap that will be filled.

DevTools Protocol, WebDriver BiDi and the two packages

The mechanism is a client that speaks a browser automation protocol to a real browser process. Puppeteer launches or connects to Chrome or Firefox and exposes objects such as browser and page. Calls like page.goto navigate, page.setViewport changes the rendering size, page.keyboard.press sends input, and page.locator targets elements. The README example uses an accessibility-oriented selector, ::-p-aria(Search), which is one of the locator syntaxes the project exposes. The notable architectural fact is that two protocols are supported. Chrome is driven over the DevTools Protocol, and the repository also documents WebDriver BiDi, including a dedicated examples/webdriver-bidi.mjs file. Firefox support is the visible consequence of that second protocol, and examples/cross-browser.js exists alongside it. The split into two npm packages matters more than it first appears. The puppeteer package downloads a compatible Chrome during installation, so the version of the browser is pinned for you. The puppeteer-core package is the same library without that download, which is what you want when the browser already exists in your image, when you connect to a remote browser, or when you refuse to let an install script fetch a binary.

Installing Puppeteer and running a first script

Installation is one command for the common case. The README gives npm i puppeteer and notes that this downloads a compatible Chrome during installation. The alternative, npm i puppeteer-core, installs the library without downloading Chrome. There is a caveat that trips people up: modern package managers including npm, pnpm, Yarn, Bun and Deno block dependency install scripts by default, and if that script is blocked, Puppeteer will not download the browser during installation, leading to runtime errors. The documented workaround is to download browsers after installation:

bash
npx puppeteer browsers install

Alternatively, the README says you can allow the install script to run, for example with npm by adding "puppeteer" to "allowScripts" in your package.json. Once a browser is present, a first script looks like the README example. It launches the browser, opens a page, navigates, sets a viewport, presses a key, and fills a field located by its accessible name:

ts
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();

await page.goto('https://developer.chrome.com/');
await page.setViewport({width: 1080, height: 1024});
await page.keyboard.press('/');
await page.locator('::-p-aria(Search)').fill('automate beyond recorder');

What you should see is a headless browser that navigates and types without any window appearing. If instead you get an error about a missing browser, the install script was blocked and the npx command above is the fix.

Where the install model bites you

The install script behaviour is the most common failure mode, and it is worth stating plainly: a blocked postinstall produces a package that imports fine and then throws at launch time, which is a confusing place to discover a packaging problem. The second constraint is the download itself. Fetching a browser binary during npm install is unwelcome in locked-down CI images, in air-gapped environments, and in monorepos where every install now pulls a browser. Choosing puppeteer-core avoids the download but shifts the burden onto you to supply a compatible browser, and the README does not document rollback or a version-pinning strategy for that case. The third limitation is scope. Puppeteer is not a test framework. If your team expects retries, parallel workers, fixtures, snapshots and an HTML report, none of that is in this package, and assembling it from scratch is real work. The project does not claim otherwise, but the gap between "browser automation library" and "end-to-end test suite" is where most disappointment lives.

Puppeteer compared with Playwright

The comparison people search for is Puppeteer versus Playwright, and the difference is one of scope rather than protocol. Puppeteer is a JavaScript library for controlling Chrome or Firefox, with a high-level API over the DevTools Protocol or WebDriver BiDi, and it runs headless by default. Playwright is a test framework built around browser automation, so it brings the runner, the assertions, the fixtures and the reporting that Puppeteer leaves to you. If you are writing a script that logs into a site and exports a PDF, Puppeteer's smaller surface is an advantage: fewer concepts, no test harness to configure, and a direct mapping from your code to browser calls. If you are building a regression suite across browsers with retries and parallel execution, you will be rebuilding Playwright's outer layers on top of Puppeteer, and the honest question is why. The protocol story is the other axis. Puppeteer's support for WebDriver BiDi is what makes Firefox a first-class target alongside Chrome, and the repository reflects that with examples/webdriver-bidi.mjs and examples/cross-browser.js. That is a genuine capability, not a checkbox, but it does not change the fact that the surrounding test infrastructure is your responsibility.

MCP, WebMCP and the automation surface around the library

Puppeteer is also used as a foundation for other tooling. The README points at chrome-devtools-mcp, described as a Puppeteer-based MCP server for browser automation and debugging, and notes that Puppeteer supports the experimental WebMCP API, documented at pptr.dev/guides/webmcp. The word experimental is the project's own, and it should be read literally: the WebMCP surface can change. The MCP server is a separate repository, so its release cadence and maintenance are not governed by Puppeteer's. For a team evaluating this, the practical point is that Puppeteer sits underneath a growing set of agent and debugging tools, and those tools inherit both its strengths and its install model. If the browser download is blocked in your environment, every tool built on top of Puppeteer inherits that problem.

Maintenance, licence and what an upgrade costs

The repository is not archived, and the last push was on 2026-08-25. Recent releases include puppeteer-v25.9.0 and puppeteer-core-v25.9.0 on the same date, with puppeteer-v25.8.0 on 2026-08-17, so the two packages are versioned and released in step. That matters for upgrades: if you depend on puppeteer-core and manage your own browser, you are responsible for keeping the browser compatible with the library version, and the release notes are where you would look for that. The licence is Apache-2.0, a permissive licence that allows commercial use, modification and redistribution provided the licence and notices are preserved and modified files are marked. Apache-2.0 also includes an express patent grant, which is a meaningful difference from MIT for some legal teams. This is a description of the licence text, not legal advice; if your organisation has a policy on bundled browser binaries, the download performed by the puppeteer package is the part to review, and puppeteer-core exists precisely so you can avoid it. The upgrade cost is dominated by the browser, not the API: a major version of the library can change which Chrome build is considered compatible, and CI images pinned to an older browser will need attention.

Editorial conclusion

Adopt Puppeteer if you are scripting Chrome or Firefox from Node.js and want a high-level API over the DevTools Protocol or WebDriver BiDi. Do not adopt it if you need a test runner, assertions or a reporting layer; Puppeteer ships none of those, and teams that expect them from the package will be disappointed. Before committing, verify that your package manager runs the install script or that you are willing to run npx puppeteer browsers install yourself, and confirm which browser binary you intend to drive, because puppeteer-core downloads nothing.

Frequently asked questions

How to install Puppeteer in Node.js?

Run npm i puppeteer, which downloads a compatible Chrome during installation. If your package manager blocks install scripts, the browser will not be downloaded and you will get runtime errors; run npx puppeteer browsers install afterwards, or allow the script to run by adding "puppeteer" to "allowScripts" in package.json.

How to use Puppeteer in Node.js?

Import the package, call puppeteer.launch() to start a browser, then open a page with browser.newPage(). From there you navigate with page.goto, adjust the rendering size with page.setViewport, send input with page.keyboard.press, and target elements with page.locator using selectors such as ::-p-aria(Search).

How to install Puppeteer?

The README gives two options: npm i puppeteer, which downloads a compatible Chrome during installation, or npm i puppeteer-core, which installs the library without downloading Chrome. Modern package managers block dependency install scripts by default, so if the download is blocked you run npx puppeteer browsers install manually.

How to use Puppeteer MCP?

The README directs you to install chrome-devtools-mcp, a Puppeteer-based MCP server for browser automation and debugging. Puppeteer also supports the experimental WebMCP API, documented at pptr.dev/guides/webmcp.

How to use Puppeteer?

Launch a browser with puppeteer.launch(), open a page with browser.newPage(), and then call methods on that page: page.goto to navigate, page.setViewport to set the screen size, page.keyboard.press to send keys, and page.locator to fill or click elements. Puppeteer runs headless by default, so no window appears.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/puppeteer-puppeteer.svg)](https://hysenlabs.com/projects/puppeteer-puppeteer)
Community notes

Community notes