Free tools Windows power users keep installed
One-click scans. No signup required.
“Unable to get browser page” is usually a startup or worker error, not a selector problem. Puppeteer Cluster must launch (or reuse) Chrome, create a worker and obtain a page before your task can run. A missing browser binary, an invalid executablePath, sandbox or shared-library failure, an unwritable profile directory, exhausted memory or process limits, and an over-aggressive concurrency setting can all fail at that stage. Navigation errors and exceptions inside your task can surface through the same Cluster error path.
Fix it by identifying the failing layer first, running one worker with full diagnostics, verifying the browser and Linux environment, then increasing concurrency and timeouts gradually. The sequence below covers local Node.js, Docker and Cloud Run deployments.
1. Identify where the failure occurs
Capture the complete original error, stack trace, URL or job payload, worker number and the operation that was running. The distinction determines the fix:
- Cluster launch: no browser or worker starts. Suspect installation, executable selection, sandbox, shared libraries, permissions or resource limits.
- Worker/page creation: Chrome starts but a page or context cannot be created. Suspect memory, process limits,
/dev/shm, profile paths or concurrency. - Task execution: your callback runs and throws, a request fails, or a timeout is reached. Cluster documents network errors, thrown code and timeouts as task errors.
- Navigation:
page.gotocannot load the target, commonly because of DNS, TLS, proxy, authentication or an application-level timeout.
Cluster’s maintainers explicitly note that the underlying problem may be Puppeteer itself. Reproduce the same URL with plain Puppeteer before changing Cluster-specific code.
#1 Best Overall
2. Turn on Cluster diagnostics before changing settings
Run the process with Cluster’s debug namespace and enable its monitor:
DEBUG='puppeteer-cluster:*' node app.js
In PowerShell, use $env:DEBUG='puppeteer-cluster:*' before starting Node. Configure a finite retry policy so logs show whether a job is being requeued:
const { Cluster } = require('puppeteer-cluster');
(async () => {
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_CONTEXT,
maxConcurrency: 1,
monitor: true,
retryLimit: 1,
retryDelay: 2000,
timeout: 60000,
puppeteerOptions: {
dumpio: true,
headless: true
}
});
cluster.on('taskerror', (error, data, willRetry) => {
console.error({
message: error.message,
stack: error.stack,
data,
willRetry
});
});
await cluster.task(async ({ page, data }) => {
await page.goto(data, { waitUntil: 'domcontentloaded', timeout: 45000 });
console.log(await page.title());
});
await cluster.execute('https://example.com');
await cluster.idle();
await cluster.close();
})();
The taskerror event supplies the error, job data and whether another attempt will occur. A job submitted with execute rejects its promise instead of emitting taskerror, so wrap that call in try/catch when you need the rejection details.
3. Reduce concurrency and choose a model explicitly
Start with one worker. Cluster’s default maxConcurrency is 1, but making it explicit prevents an environment or configuration change from hiding the cause. The concurrency model controls isolation and resource use:
| Model | Isolation | When to use | Cost and risk |
|---|---|---|---|
CONCURRENCY_PAGE |
Jobs share a page, cookies and localStorage. | Only when shared session state is intentional. | Lowest isolation; state leakage can make failures appear random. |
CONCURRENCY_CONTEXT |
Each job receives an incognito browser context. | General-purpose parallel work; this is the default. | Better isolation while sharing a browser process. |
CONCURRENCY_BROWSER |
Each URL gets a separate browser process. | When a crash in one job must not affect others. | Highest CPU, memory and process consumption. |
Use CONCURRENCY_CONTEXT or CONCURRENCY_PAGE explicitly while diagnosing:
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_CONTEXT,
maxConcurrency: 1,
workerCreationDelay: 250
});
workerCreationDelay spaces out launches and can prevent a startup spike when many workers would otherwise initialize simultaneously. Increase maxConcurrency only after one worker can repeatedly complete the job. Every additional worker or browser consumes CPU, RAM, process slots and temporary storage; a setting that works on a laptop may fail in a small container.
Rank #2
4. Verify that Chrome exists and that Puppeteer can execute it
Bundled Puppeteer
The puppeteer package normally downloads a compatible Chrome during installation. If your package manager disabled install scripts, the JavaScript package can be present while the browser is absent. Install it explicitly:
npx puppeteer browsers install
Run that command in the same image or machine that will execute the application, and make sure the runtime user can execute the resulting binary.
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 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchpuppeteer-core or system Chrome
puppeteer-core does not download a browser. Supply an absolute executable path to an installed Chrome or Chromium and verify it inside the deployment environment:
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_CONTEXT,
maxConcurrency: 1,
puppeteerOptions: {
executablePath: '/absolute/path/to/chrome',
timeout: 60000,
dumpio: true
}
});
Puppeteer’s API treats executablePath as a caller-selected browser, so the path, version compatibility and permissions are your responsibility. A path that exists during image build may not exist at runtime if a later stage uses a different filesystem.
5. Make the profile, cache and temporary directories writable
Chrome writes profile, configuration and cache files during startup. Read-only containers commonly fail before Puppeteer can connect. In a container with writable /tmp, set temporary XDG locations and a profile directory:
process.env.XDG_CONFIG_HOME = '/tmp/.chromium';
process.env.XDG_CACHE_HOME = '/tmp/.chromium';
const cluster = await Cluster.launch({
puppeteerOptions: {
userDataDir: '/tmp/.puppeteer-profile',
dumpio: true
}
});
Create those directories if your base image does not create them, and check ownership as the actual runtime user. Also verify that the system temporary directory and any mounted volume have free space. A full disk can look like a browser-page failure even when the executable is correct.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #3
6. Check Linux libraries and sandbox permissions in Docker
Chrome requires shared libraries supplied by the operating system. Minimal images often omit them, causing Chrome to exit immediately. Install the libraries required by the Chrome build you selected, or use a base image that includes them, then run the application as the same user used in production.
Sandbox errors require special care. Prefer configuring a working Chrome sandbox and suitable user permissions. Treat --no-sandbox only as an environment-specific workaround when you understand the isolation trade-off; disabling the sandbox is not a general fix.
Useful checks inside the running container include:
- Confirm the browser path is executable by the runtime UID.
- Check free RAM, process limits and
/dev/shmcapacity. - Check write access to
/tmp, the XDG directories anduserDataDir. - Run the browser command directly to expose missing-library messages before Cluster is involved.
7. Distinguish launch timeout from task and navigation timeout
Cluster’s task timeout defaults to 30,000 ms, and Puppeteer’s launch timeout also defaults to 30,000 ms. They measure different operations:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Setting | Controls | Example diagnostic value |
|---|---|---|
Cluster timeout |
Total time allowed for a task. | 60000 milliseconds |
Puppeteer launch timeout |
Time allowed to start and connect to Chrome. | 60000 milliseconds |
page.goto timeout |
Time allowed for one navigation. | 45000 milliseconds |
Increase the relevant value only after correcting installation and resource problems. A longer launch timeout cannot make a missing binary, unwritable profile or denied sandbox start successfully. Keep navigation timeout separate so a slow website does not conceal a browser-startup defect.
8. Inspect Chrome and DevTools protocol logs
Set dumpio: true in puppeteerOptions to forward Chrome’s stdout and stderr. Messages such as missing shared objects, sandbox denial or profile-lock failures usually appear there.
Rank #4
For protocol-level investigation, run with NODE_DEBUG='puppeteer:*'. After a failure, inspect browser.debugInfo.pendingProtocolErrors for unresolved calls. If you have a desktop-capable environment, temporarily use:
puppeteerOptions: {
headless: false,
slowMo: 250,
dumpio: true
}
Headful mode makes an early crash, certificate prompt or unexpected redirect visible. Do not use it on a server without a display.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →9. Account for Cloud Run execution semantics
Cloud Run can stop allocating CPU after an HTTP response is written unless the service is configured for CPU to remain allocated. Launch and await the browser before sending the response, or enable the platform’s “CPU always” setting when background work must continue after the response.
Use a custom container image containing the Linux packages Chrome needs. Keep the browser launch, Cluster task and cluster.close() within the request lifetime unless you have deliberately configured CPU allocation and shutdown behavior. A process that starts locally but dies after responding on Cloud Run is an execution-lifecycle issue, not a Cluster page selector issue.
10. Retries, recovery and reliability
Set a finite retryLimit and, where useful, a retryDelay. Retries can absorb transient DNS, proxy or remote-server failures. They cannot repair deterministic conditions such as a missing browser, incorrect executable path, denied permissions, absent libraries or a broken sandbox; those failures simply repeat and waste time.
For production jobs:
- Record the URL or job identifier, attempt number, worker and original stack.
- Use idempotent task logic so a retry cannot duplicate an external side effect.
- Keep browser launch and navigation metrics separate.
- Close the cluster in a
finallypath so a failed batch does not leave orphaned processes. - Increase concurrency in small steps while watching memory, CPU, process count and temporary storage.
11. A practical decision tree
- Does plain Puppeteer launch? If not, fix the browser installation, executable path, libraries, sandbox or writable directories first.
- Does one Cluster worker succeed? Set
maxConcurrency: 1, chooseCONCURRENCY_CONTEXT, enablemonitorand debug logging. - Does the task begin? If no, investigate worker creation and resources. If yes, inspect your callback, request and navigation timeout.
- Does adding workers cause failure? Reduce parallelism, add
workerCreationDelay, increase container resources or evaluate browser-per-job isolation. - Does it fail only in Docker or Cloud Run? Compare filesystem permissions, libraries,
/dev/shm, runtime user and CPU lifecycle with local execution.
Or skip the browser setup
If your goal is a reliable website image rather than maintaining Chrome workers, ScreenshotNeo provides a single HTTP request. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; those steps can be disabled individually. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots.
See the ScreenshotNeo API documentation for all options, including full-page and element capture, device presets, dark mode, retina scale, PDF settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture and usage reporting.
Best Value
cURL
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}`);
Start with a free account at ScreenshotNeo to get 1,000 screenshots each month with no card.
Common errors and targeted fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| “Failed to launch the browser process” | Missing binary, libraries, permissions or sandbox. | Run npx puppeteer browsers install, verify executablePath, install libraries and inspect dumpio. |
| Works locally, fails in Docker | Read-only paths, different UID, minimal image or small shared memory. | Use writable XDG and profile paths, install dependencies and check /dev/shm. |
| Only high concurrency fails | CPU, RAM, process or temporary-storage exhaustion. | Return to one worker, add launch delay and raise resources gradually. |
| Repeated retries never succeed | Deterministic setup error. | Stop retries and correct the browser, path, permission or sandbox condition. |
| Task times out after the page opens | Navigation, network or callback timeout. | Set a task-specific page.goto timeout and inspect the callback separately from launch logs. |
| Cloud Run works until the response is sent | CPU is no longer allocated. | Await all browser work before responding or enable CPU always. |
Frequently Asked Questions
Should I use a bundled browser or system Chrome?
Use bundled Puppeteer Chrome when your build can run its install script. Choose system Chrome with an explicit absolute executable path when your image or security policy manages browser versions.
When is CONCURRENCY_BROWSER worth the extra cost?
Use it when isolating browser crashes is more important than CPU, memory and process efficiency. Validate that the deployment has capacity for one browser per active job.
Can increasing every timeout solve this error?
No. Timeouts only help a slow but functioning launch or navigation. They do not fix missing executables, permissions, libraries, sandbox failures or exhausted resources.
What information should I include in a bug report?
Include the full stack, package versions, launch options, runtime image, executable path, worker and concurrency settings, URL, relevant dumpio output and whether plain Puppeteer succeeds.
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.

