Instruction manual

puppeteer/puppeteer instruction manual

Apache-2.0 TypeScript library and browser-management tooling for automating Chrome and Firefox through the DevTools Protocol or WebDriver BiDi; it is not an evidenced Claude Code extension, but can serve as browser infrastructure beneath the separately hosted Puppeteer-based chrome-devtools-mcp server named by the README.

1. What Puppeteer is, what this repository covers, and its Claude Code classification

Puppeteer is an Apache-2.0-licensed TypeScript repository whose public description is “JavaScript API for Chrome and Firefox.” Its main package is a JavaScript library that controls Chrome or Firefox through the Chrome DevTools Protocol or WebDriver BiDi. Browser sessions are headless—without a visible browser window—by default. The repository also documents browser and driver management, an Angular schematic, its own test infrastructure, Docker packaging, examples, and the documentation website.

**Claude Code classification: unclassified.** The supplied first-party files do not document a Claude Code plugin, skill, hook, command, configuration file, or Claude-specific setup. The root README points to `chrome-devtools-mcp`, a separate Puppeteer-based MCP server for browser automation and debugging, and mentions experimental WebMCP support. That establishes a general relationship to MCP, but it does not establish how this repository itself integrates with Claude Code. Do not treat Puppeteer as a native Claude Code extension on the supplied evidence.

Choose the package according to browser provisioning needs:

npm i puppeteer
npm i puppeteer-core

`puppeteer` downloads a compatible Chrome during installation. `puppeteer-core` is the library-only alternative and does not download Chrome. If a modern package manager blocks dependency installation scripts, the browser download may not occur and runtime errors can result. The documented manual recovery is:

npx puppeteer browsers install

The README also says npm users may allow the `puppeteer` install script by adding `"puppeteer"` to `"allowScripts"` in `package.json`.

2. First browser automation program and the meaning of each call

The documented introductory program launches a browser, creates a blank page, navigates, resizes the viewport, interacts through the keyboard and locators, reads page content, prints it, and closes the browser:

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');
await page.locator('.devsite-result-item-link').click();
const textSelector = await page
  .locator('::-p-text(Customize and automate)')
  .waitHandle();
const fullTitle = await textSelector?.evaluate(el => el.textContent);
console.log('The title of this blog post is "%s".', fullTitle);
await browser.close();

`puppeteer.launch()` starts the browser. `browser.newPage()` opens a page. `page.goto()` loads a URL, while `page.setViewport()` sets the emulated screen dimensions. `page.keyboard.press('/')` sends a key press. `page.locator()` creates a locator: `::-p-aria(Search)` finds the input by accessible name, the CSS selector finds a result link, and `::-p-text(...)` finds text. `fill()` enters text, `click()` activates an element, and `waitHandle()` waits for and returns an element handle. `evaluate()` runs the supplied function against that element to obtain `textContent`. Optional chaining allows for a missing handle, `console.log()` prints the result, and `browser.close()` ends the session.

The same example may import from `puppeteer-core`, but that package does not provision Chrome. The README links the complete API, guides, FAQ, troubleshooting, and contribution documentation at `pptr.dev`; this manual does not infer unshown API behavior.

3. Managing browser and driver binaries with @puppeteer/browsers

`@puppeteer/browsers` manages and launches browsers or drivers from a CLI or programmatically. It requires a compatible Node version as declared by the package. Firefox archive extraction needs `xz` and `bzip2` on Linux or `hdiutil` on macOS. Chrome extraction needs `unzip` on Linux/macOS or `tar.exe` on Windows. System-browser launching is documented as limited to Chrome/Chromium.

Start with the built-in help; per-command help is the authoritative usage source:

npx @puppeteer/browsers --help
npx @puppeteer/browsers install --help
npx @puppeteer/browsers launch --help
npx @puppeteer/browsers clear --help
npx @puppeteer/browsers list --help

`install` downloads a browser or driver, `launch` starts one, `clear` removes all installed browsers, and `list` reports installed browsers. Version the CLI with `@latest` or an exact package version such as `@2.4.1`; `npx --yes` automatically confirms installation. Supported examples include:

npx @puppeteer/browsers install chrome@stable
npx @puppeteer/browsers install chrome@116.0.5793.0
npx @puppeteer/browsers install chrome@117
npx @puppeteer/browsers install chromedriver@canary
npx @puppeteer/browsers install chromedriver@116.0.5793.0
npx @puppeteer/browsers list
npx @puppeteer/browsers clear

On Ubuntu/Debian, Chrome can be installed with required system dependencies; this requires root privileges and still attempts dependency installation if that browser version already exists:

npx puppeteer browsers install chrome --install-deps

The CLI and library honor `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` when `proxy-agent` is installed:

npm install proxy-agent

Verbose diagnostics use `NODE_DEBUG`; available channels cover cache, file utilities, installation, and launching:

env NODE_DEBUG="puppeteer:browsers:*" npx @puppeteer/browsers install chrome@stable

4. Programmatic browser management and custom providers

The browser-management API documents `install`, `canInstall`, `launch`, `computeExecutablePath`, and `computeSystemExecutablePath`. In plain language, these install a binary, check whether installation is possible, start a browser, calculate the cached executable location, or find a system executable. The supplied files refer readers to the package’s `test` folder for usage examples and do not provide signatures for every method, so no additional calls should be invented.

A custom `BrowserProvider` can point installation at a corporate mirror, private repository, or specialized build. Its documented responsibilities are: `supports(options)` decides whether the provider handles a request; `getDownloadUrl(options)` constructs the archive URL or returns `null`; and `getExecutablePath(options)` returns the browser executable’s path inside the extracted archive. The example maps Linux, Intel and ARM macOS, and 32/64-bit Windows archive names, supports only `Browser.CHROME`, and throws for unsupported platforms.

After defining that documented `SimpleMirrorProvider`, use it as follows:

import {install} from '@puppeteer/browsers';

const customProvider = new SimpleMirrorProvider('https://internal.company.com');

await install({
  browser: Browser.CHROME,
  buildId: '120.0.6099.109',
  platform: BrowserPlatform.LINUX,
  cacheDir: '/tmp/puppeteer-cache',
  providers: [customProvider],
});

Here, `install()` requests a specific Chrome build for Linux, stores it under `/tmp/puppeteer-cache`, and tries the supplied provider. Multiple providers may be placed in the array; they are tried in order until one succeeds, with a standard provider such as Chrome for Testing used as an automatic fallback. Custom providers are explicitly **not officially supported**. Their users assume responsibility for binary compatibility, testing, and maintenance.

5. Angular schematic, generated E2E tests, and Protractor concepts

The Angular schematic adds Puppeteer-based end-to-end tests to an Angular CLI application and adds itself as a project dependency. Run it from the application directory and answer its prompts:

ng add @puppeteer/ng-schematics

The required `--test-runner` option accepts `"jasmine"`, `"jest"`, `"mocha"`, or `"node"`. Once configured, run the generated E2E setup with:

ng e2e

Generate one E2E test file by name with:

ng generate @puppeteer/ng-schematics:e2e "<TestName>"

If the E2E server would conflict with `ng start`, set `port` in the relevant `angular.json` `e2e` or `puppeteer` target and make the test utility’s `baseUrl` match, for example `http://localhost:8080`.

For Protractor migration, Puppeteer’s `Browser` represents the browser process, while `Page` is the closer counterpart to Protractor’s global `browser`. The generated utility’s `setupBrowserHooks()` prepares browser state, and `getBrowserState()` returns values such as `page`. Locators can click, fill, clear, and read properties. Documented selector equivalents include `page.$('<CSS>')`, `page.$$('<CSS>')`, `page.$('#<ID>')`, text selectors such as `page.$('<CSS> ::-p-text(<TEXT>)')`, deep CSS with `:scope >>>`, XPath with `::-p-xpath(...)`, and `page.evaluateHandle()` for JavaScript queries. The experimental Locators API is recommended in the source for improved reliability and reduced flakiness.

Repository contributors can exercise the schematic’s fresh Angular integration smoke tests and its unit tests with the documented commands:

node tools/smoke.mjs
npm run test

Unit tests use `@angular-devkit/schematics/testing` to verify generated files and `package.json` changes.

6. Puppeteer’s test helpers, test state, and ordinary test execution

Puppeteer’s own unit tests use Mocha and the Expect assertion library. Common setup in `mocha-utils.js` runs before each test. `getTestState()` reads automatically reset test state: `puppeteer` is the normal library instance; `puppeteerPath` points to the root source file; `defaultBrowserOptions` supplies launch defaults that a test may override; `server` and `httpsServer` are dummy servers; `isFirefox` and `isChrome` identify the browser; and `isHeadless` identifies headless execution.

`setupTestBrowserHooks()` prepares a browser and arranges cleanup between suite runs; retrieve that browser through `getTestState()`. `setupTestPageAndContextHooks()` similarly prepares a page and browser context, exposed as `page` and `context`. The documentation recommends examining existing tests for concrete helper usage.

Run all tests applicable to the current platform with:

npm test

After local source changes, build the test workspace first:

npm run build --workspace=@puppeteer-test/test && npm test

Runner options are `--no-coverage`, `--no-suggestions`, `--save-stats-to <file>`, `--reporter <file>`, `--retries <number>`, `--timeout <number>`, `--no-parallel`, `--fullTrace`, and `--test-suite <name>`. They respectively disable coverage, disable expectation suggestions, save run statistics, choose a custom Mocha reporter, retry failures, set a timeout, disable parallel test files, show full stacks, or select a suite from `TestSuites.json`.

Temporarily change `it` to `it.only` to run one test or `it.skip` to disable one. Run visible Chrome tests with `npm run test:chrome:headful`. To select a local browser binary, the documented form is:

BINARY=<path-to-executable> npm run test:chrome:headless

Firefox may instead use `BINARY=<path-to-executable> npm run test:firefox`. Persistent conditional skips belong in `test/TestExpectations.json`.

7. Mocha Runner suites, expectations, patterns, and flaky-test diagnosis

The repository’s Mocha Runner wraps Mocha, using `/test/TestSuites.json` to define configurations and `/test/TestExpectations.json` to interpret outcomes. Test suites live under `testSuites`; their `parameters` can be referenced by expectations, while `parameterDefinitions` maps those parameters to environment values. Run the runner’s own tests with `npm test`. Build and run Puppeteer tests—or select one suite—with:

npm run build && npm run test
npm run build && npm run test -- --test-suite chrome-headless

An expectation supplies `testIdPattern`, optional `platforms`, `parameters`, and acceptable `expectations`. Platforms (`linux`, `win32`, `darwin`) use OR matching; parameters use AND; acceptable results (`PASS`, `FAIL`, `TIMEOUT`, `SKIP`) use OR. Later matching entries override earlier ones. Any accepted `SKIP` prevents execution. A literal `*` greedily matches tests: `[jshandle.spec] *` selects a file, `[page.spec] Page Page.goto *` selects tests with that prefix, and `[navigation.spec] * should work` selects a suffix. The runner suggests manual expectation-file updates when actual outcomes differ.

Flake helpers are `describe.withDebugLogs(title, body)`, which captures and prints logs for failed tests; `it.deflake(repeat, title, function)`, which repeats a test and prints failed-run logs; and `it.deflakeOnly(...)`, which also limits execution to that test. Environment-driven deflaking wraps a matching test as though `describe.withDebugLogs` were used:

PUPPETEER_DEFLAKE_TESTS="[navigation.spec] *" npm run test:chrome:headless

The same patterns are supported. Tests repeat 100 times by default; override that count with:

PUPPETEER_DEFLAKE_RETRIES=1000 PUPPETEER_DEFLAKE_TESTS="[navigation.spec] *" npm run test:chrome:headless

8. Examples, internal TestServer, Docker image, and internal architecture

To run official examples, check out the repository, install dependencies, build Puppeteer, then execute an individual file. The documented search example uses `NODE_PATH=../` so Node can resolve the built repository package:

npm install
npm run build
NODE_PATH=../ node examples/search.js

`@pptr/testserver` is internal test infrastructure. `TestServer.create(root, port)` creates HTTP service rooted at a directory; `TestServer.createHTTPS(root, port)` creates HTTPS service; and `setRoute(path, handler)` assigns a response handler. The source-supported example is:

import {TestServer} from '@pptr/testserver';

const httpServer = await TestServer.create(import.meta.dirname, 8000);
const httpsServer = await TestServer.createHTTPS(import.meta.dirname, 8001);
httpServer.setRoute('/hello', (req, res) => {
  res.end('Hello, world!');
});
console.log('HTTP and HTTPS servers are running!');

The `docker` directory provides dependencies needed to run a browser in a container. From that documented build context, build and run the image with:

docker build -t puppeteer-chrome-linux .
docker run -i --init --rm --cap-add=SYS_ADMIN --name puppeteer-chrome puppeteer-chrome-linux node -e "`cat test/smoke-test.js`"

`--cap-add=SYS_ADMIN` enables Chrome’s sandbox, which the file says makes the browser more secure. It notes `--no-sandbox` as an alternative browser flag, but the supplied run command uses the sandbox. A GitHub Actions `publish.yml` workflow automatically builds, tests, and publishes the image.

Internally, injected files are transpiled by esbuild into `src/generated` and loaded into every Puppeteer execution context. Vendored third-party modules use local entrypoints and relative imports so builds do not depend on Node module resolution. The low-level `bidi/core` layer wraps flat WebDriver BiDi resources in structured objects and event ordering; its design follows the relevant specifications rather than Puppeteer-specific convenience.

9. Building and deploying the documentation website; operational boundaries

The website uses Docusaurus 3. In the website workspace, install dependencies and start its live-reloading local development server with:

npm install
npm start

Build static documentation with:

npm run build

That command materializes current documentation as `next`, materializes the latest `puppeteer-v*` Git tag as released documentation, and writes static content to `build`. Fetch tags before building. For a shallow checkout, explicitly select the source and displayed version:

DOCS_RELEASE_REF=HEAD DOCS_RELEASE_VERSION=25.8.0 npm run build

The generated documentation inputs are ignored by Git. Deployment can authenticate through SSH or a GitHub username:

USE_SSH=true npm run deploy
GIT_USER=<Your GitHub username> npm run deploy

For GitHub Pages, the deployment command conveniently builds the site and pushes it to `gh-pages`.

Use the documented boundaries when operating this repository. Installing `puppeteer` may download Chrome; blocked install scripts require manual installation or package-manager permission. `puppeteer-core` does not download a browser. Browser archives require the platform extraction utilities listed earlier. Installing Chrome system dependencies with `--install-deps` is Ubuntu/Debian-only in the supplied documentation and requires root. Proxy support requires `proxy-agent`. Custom binary providers are unsupported and user-maintained. The Docker command grants `SYS_ADMIN` specifically to enable Chrome’s sandbox. Test expectations can intentionally accept failures or skips, so an accepted runner result is not necessarily an unconditional pass. Finally, the files supplied here do not document a Claude Code setup; use the separately linked MCP project’s own first-party instructions if evaluating that distinct integration.