First of all, thank you for your interest in Puppeteer! We’d love to accept your patches and contributions!
Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution, this simply gives us permission to use and redistribute your contributions as part of the project. Head over to <https://cla.developers.google.com/> to see your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you’ve already submitted one (even if it was for a different project), you probably don’t need to do it again.
git clone https://github.com/puppeteer/puppeteer
cd puppeteer
or
npm install
# Or to download Firefox by default
PUPPETEER_BROWSER=firefox npm install
npm run build
npm test
To build a single package, you can run:
npm run build --workspace <package> # e.g. puppeteer
This will build all dependent packages automatically, so specifying a single package is sufficient. This is all possible due to wireit which behaves similar to GNU Make.
To continuously build a package, you can run:
npm run build --watch --workspace <package> # e.g. puppeteer
You have to only specify a single package to watch else things will not work as expected As stated above because of wireit when a change happens all dependencies will be build or rebuild (if needed).
It’s possible some generated artifacts (such as
packages/puppeteer-core/src/types.ts
) can become stale since these artifacts
rely on complex conditions (such as names of distinct files) that cannot be
captured by the build system. To clean artifacts, you can run
npm run clean
# or specify the package
npm run clean --workspace <package>
Outside of npm test
, there are several other
npm
scripts that are
usually check through CI:
test-install
- Tests whether puppeteer
and puppeteer-core
install
properly and are functional.test-types
- Tests the TypeScript types in puppeteer
using
tsd
.test:chrome:**
- Tests puppeteer
on Chrome.test:firefox:**
- Tests puppeteer
on Firefox.unit
- Runs unit tests.The default npm test
runs test:{chrome,firefox}:headless
which is generally
sufficient.
Puppeteer uses a custom test runner on top of Mocha that consults the
TestExpectations.json
to see if a given test result is expected or not. See more info about the test
runner in
tools/mocha-runner
.
Tests that only test code (without the running browser) are put next to the classes they test and run using the Node test runner (requires Node 20+):
npm run unit
All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.
Our coding style is fully defined in
eslint.config
(ESLint) and
.prettierrc.cjs
(Prettier).
Code is checked for PRs automatically and you can check your code manually by running:
npm run lint
If some errors are returned, you can attempt to fix them using:
npm run format
The following is a description of the primary folders in Puppeteer:
packages
contains all public source code.test
contains all test source code.test-d
contains type tests using
tsd
.tools
contains miscellaneous scripts that are used in building and etc.tools/mocha-runner
- contains the source code for our test runner.When authoring new API methods, consider the following:
page.keyboard
and page.coverage
Commit messages should follow the Conventional Commits format.
In particular, breaking changes should clearly be noted as “BREAKING CHANGE:” in the commit message footer. Example:
fix(page): fix page.pizza method
This patch fixes page.pizza so that it works with iframes.
Issues: #123, #234
BREAKING CHANGE: page.pizza now delivers pizza at home by default.
To deliver to a different location, use the "deliver" option:
`page.pizza({deliver: 'work'})`.
Documentation is generated from TSDoc comments via npm run docs
. It is automatically
published to our documentation site on merge and gets versioned on release.
This means that you should not change the markdown in files docs/api
manually.
Each change to Puppeteer should be thoroughly documented using TSDoc comments. Refer to the API Extractor documentation for information on the exact syntax.
@public
or @internal
added as a tag
depending on if it is part of the public API.npm i --ignore-scripts
.npm run docs
which will generate all the .md
files on
puppeteer/docs/api
.npm i
in puppeteer/website
.npm start
in puppeteer/website
.For all dependencies (both installation and development):
A barrier for introducing new installation dependencies is especially high:
There are additional considerations for dependencies that are environment
agonistic. See the
third_party/README.md
for details.
If a test is expected to fail on certain configurations or became flaky, update
TestExpectations.json
to reflect that. See more info about TestExpectations.json in
tools/mocha-runner
.
Every public API method or event should be called at least once in tests. To
ensure this, the main test
command runs coverage during testing.
See Debugging Tips.
Copy the provided default .vscode/launch.template.json
to .vscode/launch.json
and then use the integrated VSCode debugger to debug test.
Remember to build test before launching via:
npm run build --workspace @puppeteer-test/test
There is a GitHub action that runs once per day. The action has a manual trigger that can be found on the Actions Tab.
You can run the tools/update_browser_revision.mjs
locally
and try see if any changes need to be committed.
Note: You may need to run
node --experimental-fetch tools/update_browser_revision.mjs
as the script relies onfetch
The following steps are manual version of the script above.
revision
and version
via https://googlechromelabs.github.io/chrome-for-testing/ or https://chromiumdash.appspot.com/.packages/puppeteer-core/src/revisions.ts
with the found version
number.versions.json
with the new Chrome-to-Puppeteer version
mapping and
update lastMaintainedChromeVersion
with the next one in from the list.npm run check
. If it fails, update
packages/puppeteer-core/package.json
with the expected devtools-protocol
version and run npm install
to generate an updated package-lock.json
.npm run clean
, npm install
and npm run build
.npm test
and ensure that all tests pass. If a test fails,
bisect the upstream cause of the failure, and
either update the test expectations accordingly (if it was an intended
change) or work around the changes in Puppeteer (if it’s not desirable to
change Puppeteer’s observable behavior).Chrome <version>
format to ensure
that pptr.dev can parse it correctly, e.g.
feat(chrome): roll to Chrome 90.0.4427.0
.For bisecting Chrome/Chromium changes use https://www.chromium.org/developers/bisect-builds-py/.
We use release-please to automate releases. When a release should be done, check for the release PR in our pull requests and merge it.
In the event release-please fails, the following needs to be done:
Update anything missing in the CHANGELOG of every package that was supposed to be published. For example, if the header is missing, you may need to add
For puppeteer:
## [{NEW_VERSION}](https://github.com/puppeteer/puppeteer/compare/v{PREVIOUS_VERSION}...v{NEW_VERSION}) ({CURRENT_DATE})`
For other packages:
## [{NEW_VERSION}](https://github.com/puppeteer/puppeteer/compare/{PACKAGE_FOLDER_NAME}-v{PREVIOUS_VERSION}...{PACKAGE_FOLDER_NAME}-v{NEW_VERSION}) ({CURRENT_DATE})
Create a GitHub release for each package, following the practice of previous releases.
Check incoming bug reports that do not have a confirmed
or needs-feedback
label:
bug
or feature
.needs-feedback
label.confirmed
.upstream
label, and post a link to crbug.com in the comments.documentation
.Issues with PDFs:
Blink>Layout
component.Internals>Headless
component.