How Puppeteer Gets a Browser Download URL
Use Puppeteer’s supported API to get a browser archive URL, configure its download host, and troubleshoot downloads across platforms.
@puppeteer/browsers provides getDownloadUrl(browser, platform, buildId, baseUrl?). It returns a URL for the archive identified by that browser, platform, and build ID. Use this supported API when you need the URL as a value; do not assume one hand-built URL pattern works for every browser and platform.
1. Get a browser download URL
Install the browser utility package if it is not already available in your project:
npm install @puppeteer/browsers
Then call getDownloadUrl with explicit inputs. This runnable Node.js example prints the URL for a Chrome for Testing build. Replace the example build ID with the build you actually intend to use.
import { getDownloadUrl } from '@puppeteer/browsers';
const browser = 'chrome';
const platform = 'linux64';
const buildId = '131.0.6778.204';
const downloadUrl = getDownloadUrl(browser, platform, buildId);
console.log(downloadUrl.href);
The function gives you a URL; it does not itself download or install the archive. Pass the returned URL to your own downloader if you need to fetch it directly, or use Puppeteer’s browser installation flow when your goal is to make a browser available to Puppeteer.
2. Understand what determines the URL
| Input | What it selects | What to check |
|---|---|---|
browser |
The browser distribution, such as Chrome or Firefox. | Use a browser identifier supported by the installed @puppeteer/browsers version. |
platform |
The platform-specific archive. | Use the platform identifier expected by the package and matching the machine or deployment target. |
buildId |
The particular browser build. | Keep it explicit and compatible with the browser and platform. Build IDs identify binaries and are used for caching. |
baseUrl |
An optional download host or URL prefix. | Use it when the archive is mirrored or served from a custom location; ensure the provider has the expected compatible archive. |
The API reference specifies the inputs and returned URL, but does not give one universal path template for all browser-platform combinations. Let the API construct the archive URL rather than concatenating a guessed path. See the getDownloadUrl API reference and install options.
3. Configure the download host
If you are installing a browser rather than merely inspecting its URL, set baseUrl in the install options. Puppeteer documents Chrome for Testing’s default host as https://storage.googleapis.com/chrome-for-testing-public and Firefox’s as https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central. These defaults are browser-specific; do not substitute one host for another without confirming that it serves the required browser archive.
import { install } from '@puppeteer/browsers';
const installed = await install({
browser: 'chrome',
platform: 'linux64',
buildId: '131.0.6778.204',
cacheDir: './.cache/puppeteer',
baseUrl: 'https://storage.googleapis.com/chrome-for-testing-public',
});
console.log(installed.executablePath);
Use the build ID and platform that match your deployment. The cacheDir above is an explicit example path; choose a writable cache directory appropriate to your environment.
Package configuration
Puppeteer package configuration also has browser-specific downloadBaseUrl settings. For Chrome, the documented environment variable is PUPPETEER_CHROME_DOWNLOAD_BASE_URL. Configure the package’s browser download host when you want installation behavior to use a changed host; use InstallOptions.baseUrl when controlling an individual install call. The configuration documentation says a base URL must include a protocol and should not end with a slash. See Puppeteer configuration.
# Example for a shell session
export PUPPETEER_CHROME_DOWNLOAD_BASE_URL=https://mirror.example.com/chrome-for-testing-public
mirror.example.com is a placeholder, not a recommended or verified mirror. Confirm that your own host contains the expected compatible files. Puppeteer notes that alternative providers are not officially supported; compatibility and testing of such providers are your responsibility.
4. Choose direct URL lookup or installation
| Need | Use |
|---|---|
| Return the archive URL to another program or display it. | getDownloadUrl(browser, platform, buildId, baseUrl?) |
| Download and install a browser into a cache. | install with explicit browser, platform, build ID, and optionally baseUrl. |
| Install a browser after package installation scripts were skipped. | npx puppeteer browsers install (or specify a browser as needed). |
| Use Puppeteer without its automatic Chrome download behavior. | Use puppeteer-core and manage the browser installation yourself. |
See the installation guide for the documented manual installation route and package behavior.
5. cURL, Python, and Node.js examples
The Puppeteer API is a JavaScript API. These examples show how to use the equivalent URL in common download workflows. They require a URL that you obtained for the exact browser, platform, and build you need; the example URL below is deliberately represented by a placeholder because the API determines the path.
cURL
curl --fail --location --output browser-archive.zip 'PASTE_URL_RETURNED_BY_GETDOWNLOADURL'
Python
from urllib.request import urlopen
url = 'PASTE_URL_RETURNED_BY_GETDOWNLOADURL'
with urlopen(url, timeout=90) as response:
archive = response.read()
with open('browser-archive.zip', 'wb') as output:
output.write(archive)
Node.js
const url = 'PASTE_URL_RETURNED_BY_GETDOWNLOADURL';
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
}
const bytes = new Uint8Array(await response.arrayBuffer());
await (await import('node:fs/promises')).writeFile('browser-archive.zip', bytes);
For production download code, stream large response bodies to disk rather than retaining the whole archive in memory. Add the expected archive format and extraction logic for the browser and platform you selected; archive formats can differ, so do not assume every result is a ZIP.
6. Proxies, integrity, and repeatable builds
For network environments that require a proxy, Puppeteer documents HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. The @puppeteer/browsers package requires the optional proxy-agent peer dependency for proxy support. Set only the proxy variables needed by your environment and ensure the package can resolve the proxy agent.
npm install @puppeteer/browsers proxy-agent
export HTTPS_PROXY=http://proxy.example:8080
export HTTP_PROXY=http://proxy.example:8080
# Add NO_PROXY only for hosts that should bypass the proxy
The proxy hostname above is an example placeholder. Avoid putting proxy credentials in source code or logs.
The install API supports optional expectedHash for a SHA-256 archive check. Supply the digest from a trusted source when your workflow needs to verify the downloaded archive; a digest copied from an untrusted mirror does not establish trust. Pin browser build IDs in CI and deployments so a rebuild uses the intended binary rather than a moving target. Relevant references: install options and browsers API.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The URL does not point to a downloadable archive. | The browser, platform, or build ID combination is wrong, or a guessed path was constructed. | Call getDownloadUrl with the matching supported inputs. Do not treat an example build ID as current for every environment. |
| The download host returns not found. | The chosen base URL does not host that browser/build/platform, or a custom mirror has an incompatible layout. | Check the browser-specific default and mirror contents; try the documented default host to isolate a mirror issue. |
| The browser was not downloaded during npm install. | The package manager may have blocked install scripts. | Run the documented manual command npx puppeteer browsers install. |
| Downloads fail only on a corporate network. | A proxy is required, proxy variables are missing, or proxy support is unavailable because the optional peer dependency is absent. | Configure HTTP_PROXY/HTTPS_PROXY, set NO_PROXY only for bypass hosts, and install proxy-agent. |
| Installation succeeds locally but fails in CI. | The target platform, permissions, proxy, cache location, or environment configuration differs. | Set the platform and build explicitly, use a writable cache directory, and provide the same required proxy and host configuration in CI. |
| A custom provider serves a file Puppeteer cannot use. | The provider may not be compatible with the expected archive or layout. | Validate the provider against the exact browser/platform/build. Alternative providers are not officially supported by Puppeteer. |
| You need to detect a corrupt or unexpected archive. | No expected digest was checked. | Provide expectedHash to the install API using a SHA-256 digest from a trusted source. |
8. Performance, reliability, and cost
URL generation is the lookup step; the time and reliability of obtaining the browser depend on the selected archive host, network path, proxy, and whether a usable cached build is available. Pinning a build ID and reusing a managed cache avoids making the intended browser version ambiguous and can avoid unnecessary repeated downloads. In CI, make cache persistence and cache permissions explicit.
Consider the archive source in deployment costs: a custom mirror may change where bytes are served from, but it also makes your workflow responsible for compatibility and availability of that mirror. The cited Puppeteer documentation does not publish a universal download time or cost for this operation. Budget based on your own network and hosting arrangements rather than assuming a fixed figure.
9. Or skip the browser setup
If your goal is a website screenshot rather than managing a Puppeteer browser binary, ScreenshotNeo is a website screenshot API and MCP server. One GET request captures a URL as PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.
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}`);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. 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.
10. FAQ
Does getDownloadUrl install Chrome?
No. It returns a URL value. Use the install API or Puppeteer’s browser installation command to install a browser.
Can I change where Puppeteer gets the archive?
Yes. Use InstallOptions.baseUrl for an install call or browser-specific package configuration for package download behavior. A custom provider must serve compatible archives.
Can I use a moving build identifier?
Use an explicit build ID when repeatable installations matter. The intended archive is selected by browser, platform, and build ID.
Is a custom download provider officially supported?
Puppeteer’s documentation says alternative providers are not officially supported; you are responsible for compatibility and testing.


