Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Puppeteer usually fails on Render because the deployed service does not contain the browser binary it expects, cannot start that binary with the service user, or is missing Linux libraries and a writable profile. Open the Render build or runtime log first, install Puppeteer’s compatible browser during the build, avoid copying a laptop path into production, and pass an executablePath only when you have verified that path exists in the deployed environment. Then check sandbox, permissions, profile storage, and Render’s build, start, environment-variable, and Docker settings.
Why Puppeteer works locally but fails on Render
Your laptop and a Render service are different environments. They can use different Node or Puppeteer versions, environment variables, users, operating-system libraries, browser caches, and installed executables. A local installation may also have Chrome installed globally even though the deployed image has no Chrome at all.
Render’s own troubleshooting guidance recommends checking logs whenever an application misbehaves. A build log tells you whether dependencies and the browser were downloaded; a runtime log shows whether Chrome later failed to launch, access its profile, or load a page.
The exact error usually points to the repair:
- “Could not find Chrome” or a missing executable message means the expected browser was not downloaded, was installed somewhere else, or is being referenced with the wrong path.
- “Failed to launch the browser process” commonly means missing shared libraries, an incompatible binary, sandbox restrictions, or a permission problem.
- Profile, cache, or EACCES errors mean the runtime user cannot write to the selected directory.
- Build succeeds but the service fails at startup often means the build and runtime commands, environment variables, Docker entrypoint, or deployed filesystem do not match.
Repair Puppeteer on Render in the right order
1. Read the complete deploy or runtime log
- Open the failed deploy in the Render dashboard and expand the complete build log.
- For a service that deployed but crashes, open its runtime logs instead.
- Record the first Chrome-related error, the Puppeteer version, the Node version shown by the build, and any path printed by your application. Fix the first failure before chasing later stack traces.
Do not guess an executable path from your development computer. Windows and macOS paths are not valid Linux paths on Render.
#1 Best Overall
2. Deploy the lockfile and install dependencies during the build
Commit package.json and the lockfile used by your package manager. Configure Render’s build command to install the same dependency graph on every deploy. With npm, a typical build command is:
npm ci
Puppeteer normally downloads a compatible Chrome for Testing during installation. If package-manager install scripts were disabled, skipped, or interrupted, that download may never happen. Explicitly install the browser in the Render build instead:
npm ci && npx puppeteer browsers install chrome
The command must run in the build environment that produces the deployed service. Installing Chrome only in an interactive shell or on your workstation does not put it in the deploy artifact.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteSet the service’s start command separately, for example:
node server.js
If you use a different package manager, use its lockfile-aware install command and then run Puppeteer’s browser-install command through that package manager. Keep the Puppeteer version pinned so a dependency update cannot silently change the browser expected by your code.
3. Prefer Puppeteer’s own browser unless you deliberately manage another one
Puppeteer documents that compatibility is guaranteed for its bundled browser; an alternate binary is used at your own risk. Choosing the bundled download is usually the most reproducible option because Puppeteer selects the browser revision it was built to control.
| Choice | Version compatibility | Installation and path | Linux dependencies and upgrades |
|---|---|---|---|
| Puppeteer-downloaded Chrome for Testing | Matched to the installed Puppeteer release | Installed by Puppeteer during the build; omit executablePath unless you need to override it |
Reproducible when the lockfile and install step are stable; the browser download increases build size and time |
| System Chrome or Chromium | You must keep the browser compatible with your Puppeteer version | Install it in the image or build environment and set the path that exists there | You own package, library, permissions, and upgrade maintenance |
Do not mix a browser downloaded on one machine with a Puppeteer package from another without checking compatibility.
Recommended Free Tools
4. If you use a system browser, discover its real path in Render
Install the browser as part of the image or build, then print candidate paths in the build log:
command -v chromium || true
command -v chromium-browser || true
command -v google-chrome || true
ls -l /usr/bin/chromium /usr/bin/chromium-browser /usr/bin/google-chrome 2>/dev/null || true
Use the path that the deployed Linux environment actually reports. Set it as a Render environment variable such as PUPPETEER_EXECUTABLE_PATH, or set it directly in code. Never paste a local .app, .exe, or Windows path into Render.
5. Use a writable profile and a conditional executable path
Chrome needs a user-data directory. A service account may not be allowed to write to the application directory or to a changed home directory. Point the profile at a temporary writable location and only override Puppeteer’s browser when an environment variable is present:
Rank #3
const puppeteer = require('puppeteer');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
async function takeShot(url) {
const profile = fs.mkdtempSync(path.join(os.tmpdir(), 'puppeteer-'));
const launchOptions = {
headless: true,
userDataDir: profile
};
if (process.env.PUPPETEER_EXECUTABLE_PATH) {
launchOptions.executablePath = process.env.PUPPETEER_EXECUTABLE_PATH;
}
// Add --no-sandbox only when your deployment environment requires it.
if (process.env.CHROME_NO_SANDBOX === '1') {
launchOptions.args = ['--no-sandbox', '--disable-setuid-sandbox'];
}
const browser = await puppeteer.launch(launchOptions);
try {
const page = await browser.newPage();
await page.goto(url, {waitUntil: 'networkidle2', timeout: 60000});
await page.screenshot({path: '/tmp/page.png', fullPage: true});
} finally {
await browser.close();
fs.rmSync(profile, {recursive: true, force: true});
}
}
takeShot('https://example.com').catch((error) => {
console.error(error);
process.exitCode = 1;
});
The bundled browser is selected when PUPPETEER_EXECUTABLE_PATH is unset. The temporary profile is unique per process, writable, and removed after the browser closes.
6. Treat --no-sandbox as a last resort
Sandbox errors can occur when Chrome is launched as a restricted or unsuitable user. First run the service with a valid non-privileged user, verify that the browser and profile are accessible, and correct the image or permissions. Only then consider the environment-specific --no-sandbox workaround. It reduces Chrome’s isolation and should not be your default launch configuration.
7. Check shared libraries and the container base image
A browser file can exist and still fail immediately when required Linux libraries are absent. For Docker, use a base image with libraries compatible with the Chrome build, or install the required libraries explicitly as part of the image build. Ensure the image defines a valid CMD or ENTRYPOINT that starts your application; a correctly installed browser cannot help if the container never launches the Node process.
Alpine Linux needs extra care: Chrome does not support Alpine out of the box. If you choose Alpine, verify that the Chromium package and browser version are matched and that the compatibility layer and libraries are present. A Debian- or Ubuntu-family base with known Chrome dependencies can be simpler when you want Puppeteer’s downloaded browser.
8. Verify cache and home-directory assumptions
Puppeteer’s documented default browser cache is $HOME/.cache/puppeteer beginning with Puppeteer v19.0.0. A changed HOME, custom cache setting, packaging step, or blocked install script can make a browser appear to be missing even though installation reported no obvious application error. Print the relevant environment variables during the build, make sure the cache is available to the runtime user, and do not rely on a cache directory that exists only in a disposable build layer.
Rank #4
Render configuration checks that prevent launch failures
- Build command: installs Node dependencies and, when necessary, runs
npx puppeteer browsers install chrome. - Start command: launches the actual server or worker, such as
node server.js. - Environment variables: include every required application setting, and make sure
PUPPETEER_EXECUTABLE_PATHpoints to a path present in this service. - Runtime user: can execute the browser and write the temporary profile and any output files.
- Docker: contains the browser and libraries in the final image, not only in an intermediate build stage, and has a working
CMDorENTRYPOINT. - Filesystem: stores temporary profiles and screenshots in writable locations rather than a read-only application directory.
After changing one item, redeploy and compare the new build and runtime logs. Record the Puppeteer version, browser version, build command, start command, executable path, and relevant environment settings so the next upgrade is diagnosable.
Common Puppeteer-on-Render errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
Could not find Chrome |
Install script was skipped, browser was never downloaded, cache or HOME changed, or the configured path is wrong. |
Run npm ci and npx puppeteer browsers install chrome in the Render build; remove a stale executablePath or set the verified deployed path. |
Failed to launch the browser process |
Missing shared libraries, incompatible system browser, permissions, or sandbox restrictions. | Use Puppeteer’s bundled browser, install compatible libraries, run as a suitable non-root user, and inspect the first launch error before considering a sandbox workaround. |
ENOENT for Chrome |
The file does not exist in the runtime filesystem. | Print the path during the build and runtime, confirm the browser is in the final image or deploy artifact, and do not copy a local path. |
EACCES or profile lock errors |
The service user cannot write to the profile or cache directory. | Use a unique writable userDataDir under a temporary directory and check ownership and permissions. |
| Sandbox or setuid errors | Chrome is running with a user or container security setup it cannot use. | Correct the runtime user and container security first; use --no-sandbox only as an explicit, environment-specific fallback. |
| Build passes, startup crashes | Build and runtime differ, an environment variable is missing, or the start command is wrong. | Check the runtime log, verify the final filesystem and variables, and ensure Render’s start command or Docker CMD/ENTRYPOINT starts the app. |
| Alpine-only launch failures | Chrome is not supported on Alpine out of the box, or Chromium and its libraries do not match. | Match the Chromium package and browser versions carefully, or use a base image with compatible Chrome libraries. |
Browser download size, caching, and upgrade planning
Puppeteer’s documentation lists approximate Chrome for Testing download sizes of 170 MB on macOS, 282 MB on Linux, and 280 MB on Windows; these are documentation values and can change with releases. The Linux download therefore affects build transfer and storage considerations on Render.
From Puppeteer v21.6.0 onward, installation also downloads chrome-headless-shell. Keep the browser installation in the build, not in application request handling, so a request does not unexpectedly trigger a large download. Pin versions in the lockfile, review browser changes when upgrading Puppeteer, and verify that any custom cache path survives into the runtime image.
Or skip the browser setup
If your goal is a dependable website image or PDF rather than browser automation inside your Render service, ScreenshotNeo exposes a single HTTP request. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and lets you turn each cleanup step off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; every response identifies the page verdict and billing result with X-Page-Verdict and X-Billed headers.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsSee the ScreenshotNeo API documentation for all parameters. A cURL request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
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 also supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, 12 device presets and arbitrary viewports, retina scale, PDF paper sizes and page ranges, HTML/CSS-to-image, custom JavaScript and CSS, click-before-capture actions, hidden selectors, selector/delay/network-idle waits, ad and tracker blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, resizing, caller-selected cache TTLs, signed public-image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Best Value
| Plan | Included shots | Price |
|---|---|---|
| Free | 1,000 per month | No card required |
| Starter | 3,000 | $5 |
| Growth | 15,000 | $15 |
| Pro | 60,000 | $39 |
| Scale | 250,000 | $99 |
| Business | 1,000,000 | $249 |
Every feature is on every plan, and yearly billing gives two months free. You can start with 1,000 free screenshots a month with no card; paid plans start at $5 for 3,000 shots.
Final verification checklist
- The Render build log shows a successful dependency install and browser installation.
- The selected browser is Puppeteer’s compatible download, or the system binary path was discovered in Render itself.
- No local Windows or macOS executable path remains in production configuration.
- The runtime user can execute Chrome and write a temporary profile.
- Required Linux libraries are present, especially in Docker or Alpine-based images.
- The build command, start command, environment variables, and Docker entrypoint are all correct.
- The redeploy log confirms the same Puppeteer and browser versions you intend to run.
Frequently Asked Questions
Will switching Puppeteer to headful mode fix a missing Chrome error?
No. Headless or headful mode changes how an installed browser runs; it does not download a browser or repair an invalid executable path.
Can I keep a system Chrome path permanently without pinning versions?
You can, but you then own compatibility and upgrade maintenance. Pin the Puppeteer dependency and verify the system browser after image or package updates.
Why does a browser installed during a Docker build still disappear at runtime?
It may have been installed only in an intermediate image stage, or the final image may use a different user and filesystem. Confirm the binary and libraries exist in the image that actually runs and that its CMD or ENTRYPOINT starts the application.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

