Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
browser automation

How to Run Multiple Puppeteer Instances at Once: Pages, Contexts, Browsers, and Safe Concurrency

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

Use the smallest isolation boundary that meets your job’s needs. Create several Page objects when tabs can share a session, create a BrowserContext per job when cookies and local storage must be separate, and call puppeteer.launch() multiple times when you need separate browser processes. For a browser managed by another service, use puppeteer.connect() instead of launching one.

Puppeteer’s documentation does not publish a universal maximum for concurrent pages, contexts, or browser processes. Treat concurrency as a capacity-setting exercise for your host and workload: start conservatively, measure CPU, memory, startup time, navigation failures, and queue latency, then adjust.

Choose the right Puppeteer unit

“Multiple Puppeteer instances” can mean three different things. The choice changes session isolation, cleanup behavior, startup cost, and failure scope.

Multiple pages: several tabs in one browser

A Browser can own many Page objects. Pages in the same browser context normally share that context’s cookies, local storage, cache, and other session state. This is the lightest option when jobs are intentionally part of one session, such as opening several product pages after one login.

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

Multiple browser contexts: separate sessions in one process

A context is a separate browser session inside one browser process. Cookies and local storage are not shared between contexts, and the context-creation API specifies that contexts do not share cache. This is usually the best default for parallel jobs that must not see one another’s authentication or site state.

The default browser context cannot be closed. Incognito-style contexts created with browser.createBrowserContext() can be closed, and closing one closes the pages it owns.

Multiple browsers: separate processes

Each puppeteer.launch() call starts a distinct browser process. This gives the strongest process boundary and limits some crashes or browser-level configuration conflicts to one group of jobs, but each process has its own startup and resource overhead. Use it when process-level separation is a requirement, not as a substitute for measuring capacity.

Connect to a browser you do not own

puppeteer.connect() attaches to an already running browser through its WebSocket endpoint. Calling browser.disconnect() only detaches Puppeteer; it does not shut down that browser or close its pages. This is useful when a browser pool, container, or another service owns the lifecycle.

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

Run parallel jobs with isolated browser contexts

The following complete example launches one browser, gives every URL its own context and page, and guarantees cleanup even when navigation fails.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option
import puppeteer from 'puppeteer';

const urls = [
  'https://example.com',
  'https://developer.mozilla.org/',
  'https://nodejs.org/'
];

const browser = await puppeteer.launch({
  headless: true
});

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

try {
  const results = await Promise.all(urls.map(runTask));
  console.log(results);
} finally {
  await browser.close();
}

Promise.all() starts every supplied task immediately and rejects when one task rejects. The finally block still closes the browser, while each task’s own finally closes its context and pages.

When pages alone are enough

If sharing cookies and local storage is intentional, create pages directly on one browser (or on one context) instead:

const browser = await puppeteer.launch();
try {
  const pages = await Promise.all([
    browser.newPage(),
    browser.newPage(),
    browser.newPage()
  ]);

  await Promise.all(pages.map(async (page, index) => {
    await page.goto(urls[index], { waitUntil: 'domcontentloaded' });
    console.log(await page.title());
  }));
} finally {
  await browser.close();
}

Do not use this pattern when one job could log another job out, overwrite shared storage, or expose account-specific data.

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.

Launch several independent browser processes

For process-level separation, launch and close one browser per job (or per worker group). The browser options include browser selection, executablePath, headless mode, userDataDir, startup timeout, and signal handling.

import puppeteer from 'puppeteer';

async function runInOwnBrowser(url) {
  const browser = await puppeteer.launch({
    headless: true,
    timeout: 30_000
  });
  try {
    const page = await browser.newPage();
    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
    return await page.title();
  } finally {
    await browser.close();
  }
}

const results = await Promise.all(urls.map(runInOwnBrowser));
console.log(results);

Puppeteer is guaranteed to work with its bundled browser. A custom executablePath is your responsibility: verify that the installed browser version, sandbox settings, and launch flags work together.

Do not confuse parallelism with an unlimited queue

Promise.all(urls.map(...)) is appropriate for a small, known set. For a large queue, use a bounded worker pattern so you can cap active jobs and observe the host. There is no documented Puppeteer concurrency number to copy into every deployment.

async function mapWithWorkers(items, workerCount, worker) {
  const output = new Array(items.length);
  let next = 0;

  async function consume() {
    while (true) {
      const index = next++;
      if (index >= items.length) return;
      output[index] = await worker(items[index], index);
    }
  }

  const workers = Array.from(
    { length: Math.min(workerCount, items.length) },
    consume
  );
  await Promise.all(workers);
  return output;
}

const results = await mapWithWorkers(urls, 3, runTask);
console.log(results);

The number 3 is an example policy, not a Puppeteer limit. Increase it only after measuring your actual workload. Track resident memory, CPU saturation, browser and context startup time, navigation timeouts, renderer crashes, and job retries. Also account for the target sites’ rate limits and your machine’s file-descriptor and process limits.

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

Lifecycle rules that prevent leaks

  • Close every context in a finally block. Closing a context closes its pages.
  • Call browser.close() when your script owns the browser and the work is complete. It gracefully closes the browser and its pages.
  • Call browser.disconnect() when you only want to detach from an externally managed browser. The remote browser remains running.
  • Do not close the default browser context; it cannot be closed.
  • Avoid sharing mutable application objects, files, credentials, or result buffers between concurrent tasks unless that sharing is deliberate and synchronized.

Configure each job deliberately

Navigation and readiness

Choose a navigation timeout and a readiness condition that match the site. domcontentloaded returns earlier than waiting for every resource; applications that render after hydration may need a selector wait or an explicit delay. Always handle timeouts and decide whether a retry is safe.

Session and identity

Use one context per identity when authentication must be isolated. Keep credentials out of shared globals, and never reuse a persistent userDataDir concurrently from multiple browser processes.

Headless and executable settings

Set headless mode explicitly for predictable deployments. If you select a system browser with executablePath, test it on the same operating system and container image used in production; Puppeteer’s bundled browser is the supported baseline.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Common failures and fixes

“Browser was not found” or launch fails

Use the bundled browser or verify the configured executable path exists and is executable. Check the startup timeout and inspect the process’s stderr. In containers, confirm required libraries and sandbox permissions are present.

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

Jobs unexpectedly share login state

You created several pages in one context. Create a new context for each isolated job, then close it after the job finishes.

Memory usage keeps growing

Look for pages or contexts that are not closed after errors. Replace an unbounded Promise.all with a worker queue, and measure whether one browser with contexts or several browser processes is more stable for your workload.

One failure cancels the whole batch

Promise.all rejects on the first rejection. Catch errors inside each worker and return a structured success/error result when the remaining jobs should continue.

Disconnecting did not stop Chrome

That is expected: disconnect() detaches only Puppeteer. Use browser.close() if your code owns the browser, or stop it through the service that launched it.

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

Pages hang or time out under load

Reduce active workers, set explicit navigation and operation timeouts, and inspect CPU, memory, network saturation, and the destination’s response behavior. There is no official universal “safe” concurrency value.

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

Which design should you use?

Design Isolation Lifecycle Best fit
Several pages in one context Shared session storage Close pages or the owning browser Tabs that intentionally share login and state
One context per job Separate cookies, local storage, and cache Close each context; then close the browser Most parallel, independently authenticated jobs
One browser per job or worker Separate browser processes Close each browser process Strong process boundaries or incompatible browser settings
puppeteer.connect() Defined by the remote browser service Disconnect without shutting down the remote browser Externally managed browser pools

Or skip the browser setup

If your goal is reliable website screenshots rather than browser automation itself, ScreenshotNeo provides a single HTTP request and an MCP server for AI clients such as Claude and Cursor. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those cleanup steps can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.

See the complete parameter reference in the ScreenshotNeo documentation. The same endpoint can return PNG, JPEG, WebP, or PDF.

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 supports full-page captures with lazy images, CSS-selector element shots, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification.

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

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account to try it.

Frequently Asked Questions

Can I share one Puppeteer browser across worker threads?

Share work through an explicit queue and give each job a page or context; do not assume arbitrary mutable objects are safe to share. The browser’s documented isolation boundary is the browser context.

Is a browser context the same as a separate Chrome process?

No. Contexts are separate sessions inside one browser process. Separate processes require separate launches or externally managed browser instances.

What should I measure before increasing concurrency?

Measure memory, CPU, startup and navigation latency, timeout and crash rates, queue delay, and destination-site responses on the exact host and workload you will operate.

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.

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
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

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.