Puppeteer Chrome Release Channels: Stable, Beta, Dev, and Canary
Learn how Puppeteer’s Stable, Beta, Dev, and Canary channels work, when to launch installed Chrome, and how to install Chrome for Testing by channel.
Puppeteer recognizes four Chrome release channel names: stable, beta, dev, and canary. Use launch({ channel }) to ask Puppeteer to find a regular Chrome installation in a known system location. That option does not install the channel into Puppeteer’s managed browser cache. To install a managed Chrome for Testing build by channel, use @puppeteer/browsers, for example npx @puppeteer/browsers install chrome@stable.
For the most predictable compatibility, use Puppeteer’s downloaded Chrome for Testing. Puppeteer says that is the browser version it works best with and does not guarantee compatibility with other Chrome versions. If you specifically prefer Google Chrome over Chrome for Testing, Puppeteer suggests trying Chrome Canary or Dev, but that is not a compatibility guarantee.
Which Chrome channel should I use with Puppeteer?
Choose based on how you want to manage the browser:
- Use Puppeteer’s managed Chrome for Testing for the documented compatibility baseline. Let Puppeteer download its matching browser, or install a channel build with
@puppeteer/browsers. - Use an installed Google Chrome channel when your environment already provides Chrome and you want to launch it by channel name. Puppeteer searches known system locations.
- Use
puppeteer-corewhen you manage the browser yourself or connect to a remote browser. Supply anexecutablePathor achannelat launch; the package does not download Chrome during installation.
Puppeteer’s channel enum contains exactly stable, beta, dev, and canary. The channel names identify which installed Chrome channel to locate; they do not, by themselves, describe a compatibility guarantee. See the official ChromeReleaseChannel enum and LaunchOptions API.
Install Chrome for Testing by channel
The @puppeteer/browsers CLI installs Chrome for Testing builds. Its documented channel syntax is chrome@<channel>. The following commands install Stable, Beta, Dev, or Canary respectively:
npx @puppeteer/browsers install chrome@stable
npx @puppeteer/browsers install chrome@beta
npx @puppeteer/browsers install chrome@dev
npx @puppeteer/browsers install chrome@canary
The same tool supports installing a specific version or milestone when reproducibility requires pinning a browser build. Consult the official @puppeteer/browsers documentation for current CLI and API details. Channel builds move over time, so record the resolved browser version in CI logs if you need to diagnose a later change.
Launch a system-installed Chrome channel
Use Puppeteer’s channel launch option when you want it to find a regular Chrome installation in a known system location. Install the corresponding Chrome channel separately on the machine first.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
channel: 'stable',
headless: true,
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
console.log(await page.title());
} finally {
await browser.close();
}
Change 'stable' to 'beta', 'dev', or 'canary' to select another recognized channel. This code assumes a compatible local Chrome installation and a Node.js environment that supports ES modules and top-level await. In a CommonJS project, use const puppeteer = require('puppeteer'); and place the asynchronous code inside an async function.
For reproducibility, you can instead provide a known executable path:
const browser = await puppeteer.launch({
executablePath: '/path/to/chrome',
headless: true,
});
Use the actual path for your machine or container. A hard-coded path is environment-specific; use configuration or an environment variable when the same code runs in multiple environments.
Use Puppeteer-managed Chrome for Testing
The regular puppeteer package downloads a Chrome for Testing browser that matches its supported setup during installation, subject to installation configuration and environment. The simplest approach is to launch without a channel:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
} finally {
await browser.close();
}
If you use puppeteer-core, install or provide a browser yourself and pass either channel or executablePath. puppeteer-core does not download Chrome during package installation. See the official installation guide.
Stable vs Beta vs Dev vs Canary in Puppeteer
Puppeteer documents the four channel identifiers, but the cited Puppeteer documentation does not provide a channel-by-channel release cadence or maturity ranking. The practical distinction established by the API is which installed channel Puppeteer will look for. Do not infer that a channel is guaranteed to work just because Puppeteer accepts its name.
| Choice | What Puppeteer does | Compatibility guidance |
|---|---|---|
channel: 'stable' |
Looks for a regular Stable Chrome installation in a known system location. | Still a system Chrome version; Puppeteer does not guarantee compatibility with every Chrome version. |
channel: 'beta' |
Looks for an installed Beta channel. | Use when you specifically need that installed channel; validate against your Puppeteer version. |
channel: 'dev' |
Looks for an installed Dev channel. | Puppeteer suggests Dev or Canary when preferring Google Chrome over Chrome for Testing; this is not a guarantee. |
channel: 'canary' |
Looks for an installed Canary channel. | Same compatibility caveat: test the actual browser and Puppeteer versions you deploy. |
| Managed Chrome for Testing | Uses the browser Puppeteer downloads or the version installed with @puppeteer/browsers. |
This is Puppeteer’s documented best-supported baseline. |
The supported-browser table is version-specific and changes over time. At the research date, it paired Puppeteer v25.12.0 with Chrome for Testing 154.0.8037.57; check the current supported browsers table rather than relying on that mapping later.
Configuration and reproducibility
- Channel: choose one of the four supported strings. A channel selects a local regular Chrome installation, not a managed download.
- Executable path: use
executablePathto point directly to a browser binary when automatic location is unsuitable. Keep the path appropriate for the runtime environment. - Headless mode:
headlesscontrols whether the browser runs without a visible window. It is independent of the selected channel. - Version pinning: install a specific Chrome for Testing version with
@puppeteer/browserswhen builds must be repeatable. A moving channel can resolve to a different version later. - Package choice:
puppeteerprovides the managed-browser workflow;puppeteer-coreis for setups where you provide or manage the browser.
For CI, pin the Puppeteer package version and browser version when repeatability matters. Ensure the browser binary is available in the same environment where the script runs, and capture the browser version in build diagnostics. Review the official launch options for the options supported by your installed Puppeteer release.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| “Could not find Chrome” or launch fails before a page opens | The requested channel is not installed in a location Puppeteer checks, or the machine has no browser installation. | Install that Chrome channel, use the managed Chrome for Testing browser, or pass a valid executablePath. |
puppeteer-core cannot launch without a path |
puppeteer-core does not download a browser during installation. |
Install/manage the browser separately and provide channel or executablePath in launch(). |
| Unknown channel or TypeScript type error | The value is misspelled or not one of the four channel names. | Use exactly stable, beta, dev, or canary; check the enum for your package version. |
| Works locally but fails in CI or a container | The local browser installation or its known location is absent in the runtime image. | Install the browser as part of the image/build, use the managed browser download, or configure the correct binary path for that environment. |
| Browser launches but automation behaves differently after an upgrade | The selected channel may now resolve to a different browser version, or the browser and Puppeteer versions may not be compatible. | Record both versions, pin versions where needed, and reproduce with Puppeteer’s managed Chrome for Testing baseline. |
Performance, reliability, and cost notes
Channel selection does not itself make page navigation or screenshots faster. Runtime depends on the site, browser version, machine resources, and automation workload. For reliable builds, prefer Puppeteer’s managed Chrome for Testing or pin a specific browser version, and avoid relying on an unrecorded channel update. Browser downloads and storage consume CI setup time and disk space; caching the installed browser can reduce repeated setup work, but the cache must correspond to the browser version your job expects.
If the task is simply to capture a website image or PDF and you do not need to operate a browser, a screenshot API can avoid maintaining a local browser installation. ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It accepts one GET request with a URL and returns PNG, JPEG, WebP, or PDF. Its parameter names also work with those used by other screenshot APIs, which can make switching straightforward.
Or skip the browser setup
Call the ScreenshotNeo endpoint directly; see the API documentation for options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
ScreenshotNeo accepts cookie and consent banners like a visitor, then removes 60+ known consent platforms, newsletter popups, and chat widgets before the capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. The same features are available on every plan.
Sign up for 1,000 free screenshots a month with no card.
FAQ
Does channel: 'stable' download Chrome Stable?
No. It asks Puppeteer to find a regular Chrome installation in a known system location. Use @puppeteer/browsers to install a managed Chrome for Testing build by channel.
Is Canary the recommended channel for every Puppeteer project?
No. Puppeteer suggests Canary or Dev if you specifically prefer Google Chrome over Chrome for Testing, but it gives no compatibility guarantee for those versions.
Can I use these channels with puppeteer-core?
Yes. Provide a channel or executable path at launch, and make sure the browser is installed or otherwise managed by your environment.
Will a channel name keep my CI browser version fixed?
No. For repeatable runs, pin a browser version and the Puppeteer package version, then verify the current supported-browser mapping.


