October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
browser automation

How to Fix Puppeteer Hanging at newPage()

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If await browser.newPage() never resolves, do not begin by increasing a test timeout. First prove which Puppeteer operation is stalled, then verify that Chromium is alive, connected, supported by the host, and able to write its profile and cache. A hang at page creation can be a symptom of a crashed browser, a broken connection, missing Linux dependencies, sandbox failure, an unwritable filesystem, an incompatible Alpine setup, or resource exhaustion after long-running reuse.

What browser.newPage() actually does

Puppeteer documents Browser.newPage() as creating a page in the browser’s default browser context and returning a Promise<Page>. The API reference does not define a per-call timeout or a universal cause for an unresolved promise. Navigation, application-level test timeouts, and browser cleanup are separate operations, so a message that appears to point at newPage() may actually be reporting a neighboring await.

Use a minimal program to identify the exact boundary:

const puppeteer = require('puppeteer');

(async () => {
  let browser;
  try {
    console.log('before launch');
    browser = await puppeteer.launch({
      headless: true,
      dumpio: true
    });
    console.log('after launch');

    console.log('before newPage');
    const page = await browser.newPage();
    console.log('after newPage');

    console.log('before navigation');
    await page.goto('https://example.com', {waitUntil: 'domcontentloaded', timeout: 30000});
    console.log('after navigation');
  } catch (error) {
    console.error(error);
  } finally {
    if (browser) {
      console.log('before close');
      await browser.close();
      console.log('after close');
    }
  }
})();

If “after launch” never prints, investigate browser startup rather than page creation. If “after newPage” never prints, inspect Chromium health, the DevTools connection, and the host environment. If it prints but navigation does not, debug the URL, network, navigation wait condition, or page-level timeout instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Check whether Chromium crashed or disconnected

A successful launch() call does not guarantee a healthy browser process. Keep Chromium’s stderr visible with dumpio: true, capture the process exit status, and watch for messages such as a sandbox error, missing shared library, out-of-memory termination, or an immediate crash.

GitHub reports have described both newPage() and pages() remaining unresolved while the author observed Chromium crashes, and another report described an eventual unresolved newPage() after hours of repeated use. Those reports are clues, not proof of a universal Puppeteer defect or a generally effective workaround.

For a service, record browser connection state and restart a browser that has closed. Do not silently reuse a failed instance:

browser.on('disconnected', () => {
  console.error('Puppeteer disconnected from Chromium');
  // Mark this worker unhealthy and create a fresh browser in your supervisor.
});

Also compare a fresh browser with a fresh context. Browser contexts isolate cookies and local storage; closing a context closes its pages. browser.disconnect() only detaches Puppeteer and leaves the browser and pages running, whereas browser.close() shuts the browser down.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Verify the executable and browser installation

Missing download or blocked install scripts

Puppeteer normally needs a compatible browser binary. Package-manager policies that disable install scripts can prevent the browser download, producing a launch problem that may later be misread as a page-creation hang. Verify which executable Puppeteer is using and install the supported browser with the current command:

npx puppeteer browsers install

If your package manager blocks lifecycle scripts, allow the Puppeteer install script according to that manager’s policy, or install a compatible browser explicitly and pass its path with executablePath. Record the Puppeteer version, browser version, Node.js version, operating system, and whether the binary is bundled or system-installed before changing anything.

Linux shared libraries

Chrome can start incorrectly or crash when a required shared library is absent. On Linux, inspect the browser binary and look for unresolved dependencies:

ldd /path/to/chrome | grep not

Install the dependencies listed for your distribution, then rerun the minimal reproducer. Use the dependency list for your current Puppeteer and browser versions; old package lists can be incomplete.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Fix sandbox and container restrictions safely

Sandbox failures

In a restricted host, Chromium may emit No usable sandbox! and exit. Configure a working sandbox rather than treating --no-sandbox as the default. Puppeteer’s troubleshooting guidance states: “Running without a sandbox is strongly discouraged. Consider configuring a sandbox instead.”

Only consider --no-sandbox for content you absolutely trust and after understanding the security trade-off. It can make a diagnostic run start, but it is not a general production fix and does not repair unrelated filesystem or browser-version problems.

Read-only containers

Chromium writes a user profile, configuration, and cache data. A read-only container or a directory owned by another user can cause crashes or stalled behavior. Point XDG directories and Puppeteer’s user-data directory at writable locations, or mount writable volumes owned by the browser user:

const browser = await puppeteer.launch({
  userDataDir: '/tmp/puppeteer-profile',
  env: {
    ...process.env,
    XDG_CONFIG_HOME: '/tmp/xdg-config',
    XDG_CACHE_HOME: '/tmp/xdg-cache'
  },
  dumpio: true
});

Ensure those paths exist, have sufficient space, and are writable by the process UID. In a container, test the same image and user that run your application, not an interactive shell as root.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Ubuntu AppArmor

The current Puppeteer troubleshooting guide describes an AppArmor restriction affecting Chrome for Testing user namespaces on Ubuntu 23.10 and later. Check the actual Chrome binary, kernel logs, and host profile before applying any workaround; do not copy a rule intended for a different binary or release.

4. Treat Alpine as a compatibility project

Chrome is not supported on Alpine out of the box. Alpine’s libraries and packaging differ from the environments used by many Puppeteer examples. Install compatible dependencies and pair the installed Chromium with a Puppeteer-supported browser version. Version-specific timeout examples age quickly, so check current compatibility guidance rather than transplanting an old Dockerfile. If you need the shortest diagnostic path, reproduce first on a supported Debian- or Ubuntu-based image, then return to Alpine once the application behavior is understood.

5. Separate lifecycle stages in long-running services

Repeated page creation can expose leaks or a browser that becomes unhealthy over time. Log every launch, context creation, page creation, navigation, page close, context close, and browser close with a request or job identifier. Limit concurrency, close pages in a finally block, and periodically replace the browser as an operational control when your workload cannot tolerate a wedged process.

async function runJob(browser, url) {
  const context = await browser.createBrowserContext();
  try {
    const page = await context.newPage();
    await page.goto(url, {waitUntil: 'domcontentloaded', timeout: 30000});
    return await page.title();
  } finally {
    await context.close();
  }
}

Using a fresh context is a controlled comparison, not a guaranteed cure. If a fresh browser works while an old browser does not, investigate accumulated pages, memory pressure, file descriptors, and application hooks before increasing timeouts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition

6. Cloud Run and delayed background work

If Puppeteer starts after your HTTP handler has already returned a response on Cloud Run, CPU allocation behavior can leave the browser with little or no CPU. The result may look like a hang. Keep CPU allocated while the browser work runs, or move the work into a request or job model whose execution window includes the Puppeteer operation. This branch applies only to that serverless execution pattern.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

7. A disciplined one-variable troubleshooting sequence

  1. Capture versions and the reproducer. Record Puppeteer, Chromium, Node.js, OS or container image, launch arguments, executable path, and the smallest script that stalls.
  2. Mark operation boundaries. Add logs before and after launch or connect, newPage(), navigation, and cleanup.
  3. Inspect browser output. Preserve stderr/stdout and process-exit information; look for crashes, sandbox errors, missing libraries, and permission failures.
  4. Verify the binary. Confirm the executable exists, is runnable by the application user, and matches a Puppeteer-supported version.
  5. Test writable paths. Set temporary XDG and user-data directories and verify free space and ownership.
  6. Test the sandbox correctly. Fix host sandbox configuration; use --no-sandbox only as a narrowly scoped, trusted-content diagnostic.
  7. Reduce lifecycle complexity. Run one browser, one context, one page, and one URL with no application concurrency or hooks.
  8. Change one condition. Do not simultaneously upgrade Puppeteer, switch images, add flags, and raise test timeouts; you will lose the evidence that identifies the cause.

A Jest or application timeout can stop a test from waiting forever, but it cannot make an unresolved browser promise complete. Treat timeout changes as observability and failure containment, not as a browser repair.

Or skip the browser setup

If your goal is simply to obtain a clean website screenshot, ScreenshotNeo provides a hosted API and MCP server instead of requiring you to operate Chromium. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

One GET request returns PNG, JPEG, WebP, or a PDF. See the ScreenshotNeo documentation for all options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every plan includes its features: 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Common symptoms and targeted fixes

Symptom Most relevant check Next action
launch() never completes Executable, dependencies, sandbox, install scripts Verify the binary, inspect stderr, install browsers and libraries
launch() completes; newPage() stalls Crash, disconnected protocol, writable profile Use dumpio, check process status, test a fresh browser and writable directories
newPage() completes; goto() stalls Navigation and network Set an explicit navigation timeout and wait condition; inspect the target site and network policy
Works locally, fails in a container UID, libraries, sandbox, filesystem Run the reproducer as the production user in the production image
Fails only after hours Accumulated resources or unhealthy browser Close contexts, cap concurrency, monitor exits, and replace the browser under supervision
Fails on Cloud Run background work CPU allocation Keep CPU allocated while Puppeteer runs

What not to conclude

  • There is no documented universal timeout or single fix for Browser.newPage().
  • An issue report is not a controlled reproduction and does not establish prevalence.
  • Raising a test timeout does not repair a stalled browser connection.
  • --no-sandbox is not a safe default.
  • Changing several versions and flags at once prevents reliable diagnosis.

Frequently Asked Questions

Does Puppeteer expose a timeout specifically for browser.newPage()?

The API documents a promise that resolves to a page but does not specify a per-call timeout. Add your own watchdog for observability and recovery, while diagnosing the underlying browser or host problem.

Should I switch to browser.pages() to avoid the hang?

No. A report describing both methods hanging points toward browser health or the connection, not a reliable alternative page-creation API.

Is Alpine Linux unsupported by Puppeteer?

Chrome is not supported on Alpine out of the box. Alpine can work only with compatible dependencies and a browser version supported by your Puppeteer release; verify current guidance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.