How to Fix Puppeteer Screenshot Errors Caused by a Mismatched Chrome Version
Find the Chrome binary Puppeteer actually launches, match it to the official browser mapping, and make the fix repeatable in local and CI builds.
A Puppeteer screenshot can fail when the Chrome or Chromium binary it launches is not compatible with the installed Puppeteer release. First check the actual executable and its version, then compare that version with the official Puppeteer supported-browser table. The most reliable fix is to use Puppeteer’s installed browser; if you manage Chrome yourself, pin a supported browser version and configure its path deliberately.
1. Check which Puppeteer and Chrome versions are in use
Do not infer a version mismatch from a screenshot error alone. A missing browser, bad executable path, or missing system dependency can produce a launch failure too. Start by collecting the package version, the configured browser path, and the version of the binary that path points to.
Inspect the installed Puppeteer package
npm ls puppeteer puppeteer-core
If both packages are present, identify which one your application imports. puppeteer normally manages a compatible browser installation. puppeteer-core is the browser-agnostic package: your application or environment must provide the browser executable.
Print the executable path and browser version from the script
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
console.log('Puppeteer package:', require('puppeteer/package.json').version);
console.log('Browser version:', await browser.version());
console.log('Browser process:', browser.process()?.spawnfile);
await browser.close();
})().catch(error => {
console.error(error);
process.exitCode = 1;
});
Run this using the same command, environment, container, and CI job that produces the failing screenshot. When launch fails before a browser object is returned, inspect your launch configuration and environment variables for an executablePath or wrapper that selects a system browser.
Check a known executable directly
If your configuration names a binary, ask that binary for its version. Substitute the exact path from your environment:
/path/to/chrome --version
On systems where the command is available through PATH, which chrome, which chromium, or which chromium-browser can help identify a candidate, but the runtime printout or launch configuration is better evidence of what Puppeteer actually uses.
2. Match the browser to the Puppeteer release
Look up the installed Puppeteer version in the supported-browser table and use its mapped Chrome for Testing version. Do not assume that the newest system Chrome is compatible. Puppeteer documents that each release is paired closely with a browser release because the browser’s Chrome DevTools Protocol and WebDriver BiDi implementations change over time.
Since Puppeteer 20.0.0, Puppeteer downloads and works with Chrome for Testing; earlier releases used Chromium. If your exact Puppeteer version is not listed, Puppeteer’s documentation says to use the browser version listed for the immediately prior Puppeteer version.
For example, the documentation version checked for this guide lists Puppeteer 25.12.0 with Chrome for Testing 154.0.8037.57. Treat this as an example, not a permanent recommendation: consult the table for the version installed in your project because the mapping changes as releases advance.
3. Choose a browser management approach
| Approach | When it fits | What to manage |
|---|---|---|
| Use Puppeteer’s installed browser | You want the browser release Puppeteer supports for your package version. | Make sure installation and browser download/cache access work in every environment. The bundled browser is the compatibility guarantee documented by Puppeteer. |
| Manage Chrome or Chromium yourself | You need a particular browser binary or your platform provides it centrally. | Choose a version from the supported-browser mapping, pin it, configure its path, and verify the launched version. Puppeteer does not guarantee arbitrary custom executables. |
Option A: use Puppeteer’s browser installation
For the standard puppeteer package, remove a custom executablePath unless you specifically need it, then install the package and its managed browser as part of the project setup. Keep the lockfile so the package version is repeatable.
npm install puppeteer
npm ls puppeteer
Make sure the install step runs in the same build image or job where screenshots run. Some deployments install dependencies with scripts disabled or omit the browser cache; in those cases the package may exist while its browser does not.
Option B: install and pin a browser yourself
Puppeteer’s browser manager supports installing Chrome for Testing by stable channel or by explicit version, and listing installed browsers. A moving channel is convenient when you intentionally want current stable. For reproducible CI and containers, install an explicit version that matches the Puppeteer mapping.
npx puppeteer browsers install chrome@154.0.8037.57
npx puppeteer browsers list
Replace the example version with the one mapped to your installed Puppeteer release. Then either let Puppeteer find that managed installation or pass the exact executable path through your application’s configuration. Avoid silently falling back to whatever chrome happens to be first on PATH.
4. Make the screenshot script fail clearly
This CommonJS example logs the browser version, navigates to a page, and saves a screenshot. It supports a custom executable path through an environment variable so the path is visible and controllable in local and CI configuration.
const puppeteer = require('puppeteer');
(async () => {
const launchOptions = { headless: true };
if (process.env.CHROME_EXECUTABLE_PATH) {
launchOptions.executablePath = process.env.CHROME_EXECUTABLE_PATH;
}
const browser = await puppeteer.launch(launchOptions);
try {
const page = await browser.newPage();
console.log('Puppeteer:', require('puppeteer/package.json').version);
console.log('Browser:', await browser.version());
console.log('Executable:', browser.process()?.spawnfile);
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 30000
});
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
})().catch(error => {
console.error('Screenshot failed:', error);
process.exitCode = 1;
});
For Puppeteer 24 and later, headless mode behavior is configurable; use the mode supported by your installed release and target environment. The version pairing still needs to be valid regardless of headless mode.
5. Check CI and container differences
- Compare local and CI package versions. Use the lockfile and print
npm ls puppeteerin the failing job. - Print the launched browser version and executable. Do this from the screenshot process rather than a separate shell that may have a different
PATH. - Inspect configuration overrides. Check
executablePath, environment variables, container entrypoints, and scripts that install system Chrome. - Make installation part of the build. Ensure the browser download/cache is available in the runtime image; do not depend on a developer workstation’s cache.
- Pin both sides for reproducible builds. Keep the Puppeteer dependency locked and install the mapped browser version explicitly when managing the browser yourself.
- Re-run the smallest screenshot case. Once the pair is confirmed, test a simple page before restoring application-specific navigation and capture options.
6. Troubleshooting common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Protocol or session errors after launch | The executable is a browser release unsupported by the installed Puppeteer version. | Print the actual executable and browser version, then select a pair from the supported-browser table. |
Could not find Chrome or browser not found |
The browser installation did not run, its cache is unavailable, or runtime is looking in a different location. | Install the browser during the build, preserve or configure its cache location, and list installed browsers with Puppeteer’s browser manager. |
| Works locally, fails in CI | CI uses another Puppeteer version, a system browser, or a different cache/path. | Log package version, browser version, and executable in CI; compare the lockfile and remove unexpected path overrides. |
| Works after package install, fails in production image | The image contains Node dependencies but omits the downloaded browser or required runtime files. | Install the browser in the final image or use a documented browser path that exists there. Verify from inside that image. |
| Browser launches but screenshot navigation times out | This may be a page/network readiness problem rather than a version mismatch. | Confirm the browser pair first; then inspect URL reachability, navigation timeout, redirects, and the chosen waitUntil condition. |
| Chrome exits immediately in a container | Could be missing system dependencies, sandbox restrictions, or container configuration; a supported version pair does not rule these out. | Use Puppeteer’s official troubleshooting guide for the specific launch error and environment, and verify required dependencies in the image. |
| Custom browser works on one machine only | The configured path points to different browser versions across machines. | Pin the browser package or image, print the runtime path and version, and keep the Puppeteer mapping aligned. |
Puppeteer’s troubleshooting guide covers installation, cache, system dependency, and launch-environment failures. If your browser version matches the supported mapping, continue with those checks; a screenshot failure alone does not establish a version mismatch.
7. Reliability, performance, and cost considerations
- Reliability: A lockfile plus a pinned browser makes builds easier to reproduce. Stable-channel installs can move over time, so use them only when automatic browser updates are intended.
- Maintenance: When upgrading Puppeteer, review its supported-browser mapping and update a manually managed browser in the same change. Keep a simple startup diagnostic in CI so unexpected binaries are visible.
- Performance: A version mismatch is primarily a compatibility issue, not a screenshot speed setting. Avoid repeated browser downloads by preparing the browser in the build image or preserving the managed cache appropriately.
- Cost: A local or self-hosted Puppeteer script has no per-screenshot API charge, but your build or server still consumes compute, storage, and maintenance time. Account for browser installation and cache size in CI/container design.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. It returns a PNG, JPEG, WebP, or PDF from one GET request and manages the capture browser for you. The API documentation describes the request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response headers report the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.
FAQ
Does every Puppeteer screenshot error mean Chrome is mismatched?
No. Confirm the executable and browser version first. Missing installations, system dependencies, bad paths, navigation timeouts, or container restrictions can fail independently.
Can I use the Chrome already installed on the machine?
Yes, with a custom executablePath, but Puppeteer only guarantees compatibility with its bundled browser. Check the actual version against the mapping and accept the extra maintenance of keeping both versions aligned.
Should I upgrade Puppeteer or downgrade Chrome?
Choose the change that best fits the project’s required browser and deployment setup. Either use the browser paired with the installed Puppeteer release or select the Puppeteer release mapped to the browser you need.
How do I know which browser Puppeteer installed?
Use browser.version() after launch, inspect the process executable path, and use npx puppeteer browsers list to inspect managed installations.


