To run multiple Puppeteer jobs at once, use a bounded pool of Node.js worker_threads and give each worker its own Puppeteer browser. Within that browser, use a fresh BrowserContext per independent job when cookies and cache must be isolated, or reuse a page when jobs are meant to share state. “Multithreaded” here means concurrent job orchestration: it does not make one Chromium page render across several Node.js threads.
What “multithreaded Puppeteer” means
Node.js worker threads run JavaScript in separate execution contexts. They are useful for distributing orchestration and job handling, but a Puppeteer Page and its Browser belong to the browser instance that created them. Do not try to pass a live page or browser object to another worker. Pass serializable inputs such as URLs and options through workerData or messages, then create and use Puppeteer objects inside the worker that owns them.
Concurrency can improve throughput when you have independent pages to process, but it also increases demand for CPU, memory, and browser processes. There is no universal safe number of workers or pages per browser: the official documentation does not publish a general maximum, memory-per-instance figure, or throughput benchmark. Choose a limit by measuring your own workload and host.
Choose the right isolation boundary
| Approach | Isolation and sharing | When to use it | Trade-off |
|---|---|---|---|
| Several pages in one context | Pages share the context’s browser state. | Jobs intentionally share a session or state. | Lowest isolation; state changes from one job may affect another. |
| One context per job in one browser | Contexts do not share cookies or cache; closing a context closes its pages. | Default for unrelated jobs, including jobs that need separate sessions. | Separates context state without launching a browser process for every job. |
| One browser per worker | Separate browser instances provide stronger separation between workers. | When you want a worker-level browser boundary or simpler ownership. | More Chromium processes and memory use; measure before increasing the pool. |
| Separate OS processes or containers | Deployment-level separation can contain failures or enforce resource boundaries. | Untrusted jobs or requirements for hard resource quotas and crash containment. | More deployment and orchestration complexity; this is not a Puppeteer API guarantee. |
Puppeteer specifically recommends BrowserContexts when automation tasks need isolation. Avoid launching a fresh Chromium process for each small task unless the stronger boundary is worth its startup and resource cost. Reuse a browser within its intended lifetime, and close each page or context when its job is done.
#1 Best Overall
- ADJUSTABLE HEIGHT DESIGN: The mobile standing desk promotes a healthier workstyle by allowing quick transitions between sitting and standing. The gas spring lift smoothly adjusts the height from 28.3in to 44in, supporting better posture and reducing neck and back strain during long working hours. This portable desk improves daily comfort and productivity across different environments.
- SUPERIOR STABILITY AND DURABILITY: The rolling desk adjustable height model stands out with its sturdy H shaped steel base and reinforced structure, providing stability even at maximum extension. The waterproof and scratch resistant MDF desktop ensures long lasting use, while the retractable keyboard tray and hook create organized storage for accessories. This unique design differentiates the desk from standard folding table or rolling podium options on the market.
- ERGONOMIC AND FUNCTIONAL DESIGN: The portable standing desk offers a spacious 25.6 x 17.7in surface to accommodate a laptop, monitor, or books. A dedicated slot holds phones and tablets, while the 23.6 x 11.8in keyboard tray supports a full size keyboard and mouse. The thoughtful structure allows the small standing desk to serve as a side table, study cart, or computer desk with keyboard tray in living rooms, bedrooms, and offices.
- EASY MOBILITY WITH LOCKABLE WHEELS: The adjustable rolling desk includes four caster wheels that allow smooth movement between rooms. The lockable function secures the desk in place when needed, creating flexibility for use as a rolling laptop desk, classroom furniture, or teacher standing desk. The compact rolling table design makes the desk on wheels easy to move, while maintaining stability during presentations or study sessions.
- EASY OPERATION AND LOW MAINTENANCE: The sit stand desk is operated with a simple hand lever that activates the gas spring for smooth upward adjustment, while gentle pressure lowers the surface. The mobile desk workstation requires minimal maintenance, as the MDF board is waterproof, scratch resistant, and easy to clean with a damp cloth. This reliable raising desk minimizes user effort and ensures long term durability without complex upkeep.
Build a bounded worker pool
The example below uses ES modules and distributes a fixed set of URLs round-robin across a fixed number of workers. Each worker launches one headless browser, processes its assigned jobs one at a time, creates a fresh context per URL, reports success or failure to the parent, and closes the browser on shutdown. The workers run concurrently, while each worker avoids running multiple jobs simultaneously against its own browser.
1. Install Puppeteer
Use puppeteer if you want Puppeteer to download and manage its browser. The installation guide describes its download as a recent Chrome for Testing binary. Use puppeteer-core instead when you manage the browser yourself; in that case configure an executablePath or channel. Pin the package and browser source in CI or deployment, and make the executable choice explicit when using an externally managed browser.
npm init -y
npm install puppeteer
Save the following files together as main.mjs and worker.mjs. Running node main.mjs starts the pool.
2. Start a limited number of workers
// main.mjs
import { Worker } from 'node:worker_threads';
const jobs = [
{ id: 'a', url: 'https://example.com/a' },
{ id: 'b', url: 'https://example.com/b' },
{ id: 'c', url: 'https://example.com/c' },
{ id: 'd', url: 'https://example.com/d' },
];
// Set this from measurements of your host and workload, not a universal rule.
const concurrency = Math.min(2, jobs.length);
const assignments = Array.from({ length: concurrency }, () => []);
jobs.forEach((job, index) => assignments[index % concurrency].push(job));
const results = [];
function runWorker(workerIndex, workerJobs) {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL('./worker.mjs', import.meta.url), {
workerData: { workerIndex, jobs: workerJobs },
name: `puppeteer-${workerIndex}`,
// Limits the worker's V8 old-generation heap, not Chromium's total memory.
resourceLimits: { maxOldGenerationSizeMb: 512 },
});
worker.on('message', message => {
if (message.type === 'result') results.push(message);
if (message.type === 'fatal') {
reject(new Error(`Worker ${workerIndex}: ${message.error}`));
}
});
worker.once('error', reject);
worker.once('exit', code => {
if (code === 0) resolve();
else reject(new Error(`Worker ${workerIndex} exited with code ${code}`));
});
});
}
try {
await Promise.all(assignments.map((list, index) => runWorker(index, list)));
console.log(results);
} catch (error) {
console.error('Worker pool failed:', error);
process.exitCode = 1;
}
resourceLimits is optional. Its heap limit applies to the worker’s JavaScript engine, not to Chromium’s overall memory consumption, so it is not a substitute for setting an appropriate worker count or container/host limits.
Recommended Free Tools
Rank #2
- 【32” x 19” Perfect for Small Spaces & Corner】 Specially designed with a compact 32" x 19" desktop, this small electric standing desk seamlessly fits into limited areas like apartments, bedrooms, and cozy home office corners without crowding your room. It is the ultimate space-saving, height-adjustable solution to pair with under-desk treadmills and walking pads for remote workers, freelancers, and students
- 【4 Memory Presets & DIY Wheel Ready】 This adjustable desk features a smart control panel with 4 programmable memory presets for effortless one-touch height adjustment (28.3" to 46.5"). Plus, built-in universal M8 screw holes on the desk feet allow you to easily install your own casters/wheels to DIY it into a mobile rolling desk.
- 【176 lbs Max Load & Rounded Safety Corners】 Constructed with heavy-duty steel rails and a solid desktop, this small stand up desk supports up to 176 lbs with exceptional stability while transitioning. The tabletop features smooth rounded corners to protect you, your family, or pets from accidental bumps in tight, compact spaces.
- 【Rigorously Tested for Long-Lasting Use】 Engineered for daily reliability, our motor and lifting system have been rigorously tested to withstand up to 50,000 lift cycles under full capacity. Enjoy a whisper-quiet, smooth sit-to-stand transition that keeps you focused and productive all day.
- 【Easy Assembly & Budget-Friendly Choice】 Comes with detailed instructions and all hardware included for a hassle-free, quick setup. Get premium electric sit-stand functionality at an unbeatable, budget-friendly price. Risk-free purchase with dedicated customer support ready to help.
3. Run each job inside its worker
// worker.mjs
import puppeteer from 'puppeteer';
import { parentPort, workerData } from 'node:worker_threads';
let browser;
try {
browser = await puppeteer.launch({
headless: true,
// Navigation timeouts are explicit so a stalled target cannot hold a worker forever.
protocolTimeout: 60_000,
});
for (const job of workerData.jobs) {
let context;
try {
context = await browser.createBrowserContext();
const page = await context.newPage();
page.setDefaultNavigationTimeout(30_000);
await page.goto(job.url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
parentPort.postMessage({
type: 'result',
workerIndex: workerData.workerIndex,
id: job.id,
url: job.url,
title: await page.title(),
});
} catch (error) {
parentPort.postMessage({
type: 'result',
workerIndex: workerData.workerIndex,
id: job.id,
url: job.url,
error: error instanceof Error ? error.message : String(error),
});
} finally {
if (context) await context.close();
}
}
} catch (error) {
parentPort.postMessage({
type: 'fatal',
error: error instanceof Error ? error.message : String(error),
});
process.exitCode = 1;
} finally {
if (browser) await browser.close();
}
The pool size is set to two only as a small runnable example, not as a recommended production count. Increase it gradually while measuring CPU, memory, queue wait, navigation duration, and failure rates on the machines and targets you actually use. When a job needs to share cookies or cache with another, replace per-job contexts with a deliberately shared context; do so only when that state sharing is intended.
Headless mode and browser selection
Puppeteer runs headless by default. headless: true selects the current “new” headless mode. headless: 'shell' uses the separate chrome-headless-shell binary; Puppeteer describes it as an option for cases where performance matters more than having the complete Chrome feature set. Use headless: false to show a visible browser while debugging.
For repeatable CI or container deployments, configure the browser download/cache and executable deliberately instead of relying on an accidental machine-local setup. Puppeteer’s configuration supports settings including cacheDirectory, temporaryDirectory, and skipDownload; when the browser is managed outside Puppeteer, provide its executable path or channel.
Reliability, safety, and resource management
- Bound every layer. Limit active workers, contexts, and pages according to observed host capacity. Adding workers beyond available CPU or memory can increase contention rather than useful throughput.
- Keep browser objects local. Send serializable job data through
workerDataor messages. Create pages and contexts in the worker that owns the browser; do not attempt to transfer live Puppeteer objects. - Always clean up. Close a context or page after each job and close the browser during worker shutdown. Put cleanup in
finallyblocks so navigation and evaluation errors do not leak sessions. - Set operation timeouts. Configure navigation and other potentially long-running operations with explicit timeouts. A stuck target should fail as a job rather than occupy a worker indefinitely.
- Keep Chromium’s sandbox enabled where possible. Puppeteer documents multiple sandboxing layers.
--no-sandboxis a workaround for environments without a usable sandbox, and should be reserved for trusted content in those circumstances. - Observe failures and queue health. Record worker errors and non-zero exits, browser disconnects, navigation failures, job duration, and queue latency. These measurements help distinguish a slow target from a saturated host.
- Plan failure boundaries deliberately. A browser per worker is an engineering trade-off, not a guarantee of crash isolation. If jobs are untrusted or need hard quotas, use OS processes or containers as part of the deployment design.
Common problems and fixes
Workers start, but Chromium will not launch
Check that the installed Puppeteer package and browser binary match the deployment. If using puppeteer-core, configure a valid executablePath or channel; it does not manage the browser download for you. In constrained environments, check whether a usable sandbox is available before considering --no-sandbox, and do not apply that workaround to untrusted pages.
Rank #3
- [INTEL POWERED CONTENT] - Built with a 8th Generation Hexa-Core Intel i5 and 32GB of DDR4 RAM; Modern, Windows 11 ready, with 4K support, Executive multitasking, media streaming and smooth, multi-tab web browsing; Perfect as an all-purpose multimedia computer; built for content creators; Plenty of RAM and Mass storage for photo and video editing powered by Intel HD 630
- [LATEST WIRELESS TECH] - This Dell Desktop Computer easily connects to the internet through the Built In WiFi / Bluetooth
- [SOLID STATE STORAGE] - This Dell Computer setup comes with an ultra-fast 1TB Solid State Drive (SSD); Setup as the primary boot device; Boot and load programs with lightning speed ; Additional expansion available
- [BUY & OWN WITH CONFIDENCE] - From the world's largest Microsoft Authorized Refurbisher; Quality Guarantee and Free Tech Support; Award-winning Customer Service; | Support Sustainable Business
- [MODERN HI-SPEED PORTS] - USB 3.0 (x4) | USB 2.0 (x4) | DisplayPort (x1) | HDMI Port (x1) | Audio Combo Jack (x1) | Audio Out (x1) | RJ-45 Ethernet (x1) | Internal SATA (x3)
The process runs out of memory or slows as concurrency rises
Reduce the worker count and measure again. A worker heap limit such as maxOldGenerationSizeMb only constrains V8’s old-generation heap; it does not cap the browser process. Also check whether contexts and browsers are closed after each job and whether your design accidentally launches a browser per task.
Jobs time out or a worker never becomes available
Set explicit navigation and operation timeouts, capture the error per job, and make sure cleanup runs even after a failed navigation. If navigation consistently stalls, investigate the target and its loading behavior rather than simply increasing the pool, which may reserve more resources for stuck work.
One job sees another job’s cookies or cached state
Use a new BrowserContext for each independent task. Separate pages in one shared context are not the right boundary when jobs require isolated cookies and cache.
The parent process reports a non-zero worker exit
Handle both the worker’s error event and its exit code, as in the example. Log the worker identity and assigned job IDs so you can distinguish a launch failure from a job-level navigation error. Decide whether a failed worker should fail the whole batch or be replaced and its uncompleted jobs requeued.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #4
- Create Instant Active Standing - VIVO’s desk riser provides on-demand standing throughout the day for the freedom to get out of your chair and relieve muscle tension, reduce stress, and increase productivity. --Patented--
- Space Efficient 31.5" Surface - The top surface measures 31.5” x 15.7”, which maximizes space while still providing room for dual monitors. The 31.3" x 11.8" (10.5" in center) keyboard tray raises in sync with the top surface to create a comfortable workstation.
- Strong 33 lbs Lift Assist - Go from sitting to standing in one smooth motion using the innovative simple touch height locking mechanism (Adjustment Range: 4.5" to 20"). Lift design elevates straight upwards.
- Very Minimal Assembly - This riser is almost ready to go right out of the box! Place on your existing desk, attach the keyboard tray, and start organizing your workstation.
- We've Got You Covered - Sturdy, high-grade steel design is backed with a 3-Year Manufacturer Warranty and friendly tech support to help with any questions or concerns.
Performance and cost decisions
Concurrency is a capacity decision, not a fixed Puppeteer setting. The sources do not establish a universal safe worker count, maximum pages per browser, memory figure, or throughput number, so avoid sizing a service from a generic online rule. Benchmark with representative pages and record both successful work and failure behavior. Compare the cost of reusing a browser with the extra CPU and memory of launching more browser instances; also include operational complexity when choosing between worker-local browsers and stronger OS-level isolation.
If your task is specifically to capture screenshots or PDFs from URLs and you do not need Puppeteer to interact with a live page, a capture API can remove browser installation and worker-pool management from your application. ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo; it is a capture alternative, not a replacement for general Puppeteer automation or arbitrary page scripting.
Or skip the browser setup
For a URL screenshot, make one request instead of managing Chromium workers:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for parameters and response details. Cookie banners are accepted and removed before the shot, along with supported consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers indicate the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo free: 1,000 screenshots a month, no card required.
Free tools Windows power users keep installed
One-click scans. No signup required.
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.




