Set timeout in the options passed to page.pdf(). The value is milliseconds, so a two-minute limit is timeout: 120000. Puppeteer’s current PDFOptions reference documents 30,000 ms (30 seconds) as the default; use timeout: 0 to remove that limit.
Increase the timeout for one PDF export
A per-call timeout is the safest fix when only one report, invoice, or long page is slow. It changes the maximum wait for that PDF operation without changing timeout behavior for the rest of the page.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com/report', { waitUntil: 'networkidle0' });
await page.pdf({
path: 'report.pdf',
format: 'A4',
printBackground: true,
timeout: 120000
});
} finally {
await browser.close();
}
The unit is milliseconds: 60000 is one minute, 120000 is two minutes, and 300000 is five minutes. Choose a limit that fits your document and runtime rather than treating any value as a universal recommendation; the official references do not publish a workload benchmark for selecting one.
Disable the PDF timeout
await page.pdf({
path: 'report.pdf',
timeout: 0
});
Puppeteer documents 0 as disabling the timeout. That lets a hung page wait forever, so a production worker should still have an outer job deadline or process watchdog. Disabling the PDF limit does not repair a page that never finishes loading, a broken font request, or a browser process that has stopped responding.
#1 Best Overall
Change the page-wide default
If many PDF calls on the same page need the same longer limit, set the page default once and omit timeout from each PDF call:
page.setDefaultTimeout(120000);
await page.pdf({ path: 'report.pdf' });
Puppeteer’s PDFOptions reference says the PDF timeout default can be changed with page.setDefaultTimeout(). This setting has broader scope than a per-call value, so it can also change the maximum wait for other page operations that use the page default. Prefer the local page.pdf() option when different documents have different requirements.
| Setting | Scope | Use it when | Behavior |
|---|---|---|---|
page.pdf({ timeout: milliseconds }) |
One PDF operation | A single document is unusually slow or needs a distinct limit | Finite maximum for that call |
page.setDefaultTimeout(milliseconds) |
Page-wide default | Several operations on one page share the same ceiling | Broader default used when an operation does not provide its own value |
page.pdf({ timeout: 0 }) |
One PDF operation | You intentionally want no Puppeteer PDF timeout | Unlimited wait; protect the worker with an external deadline |
protocolTimeout |
Individual Chrome DevTools Protocol calls | The error specifically identifies a protocol-call timeout | Separate connection or launch setting; not the PDFOptions timeout |
Do not confuse PDF, navigation, and protocol timeouts
The PDFOptions timeout
The timeout inside page.pdf() controls the PDF generation call itself. A timeout error from that call is the signal to raise this value, use a per-call limit, or deliberately pass 0.
The page default timeout
page.setDefaultTimeout() supplies a wider page-level default. It is convenient for a batch of similar exports, but a large value can make unrelated waits take longer before failing.
Crashes, 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 minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #2
The protocol timeout
protocolTimeout belongs to the browser connection or launch configuration and limits individual protocol calls. The currently documented ConnectOptions reference lists 180,000 ms (three minutes) as its default in documentation reported as version 25.12.0. Raising page.pdf({ timeout }) does not automatically raise that protocol ceiling. Change protocolTimeout only when the error points to a protocol call, and keep the two settings conceptually separate.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
protocolTimeout: 240000
});
const page = await browser.newPage();
await page.pdf({
path: 'report.pdf',
timeout: 120000
});
await browser.close();
Use this combination only when both limits are relevant. If the PDF call is failing at 30 seconds, changing protocol settings first adds scope without addressing the immediate limit.
A complete export with diagnostics
Logging the elapsed time and preserving the original error makes it easier to distinguish a genuinely slow export from a page that is stuck.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
const started = Date.now();
try {
await page.goto('https://example.com/report', {
waitUntil: 'networkidle0',
timeout: 90000
});
await page.pdf({
path: 'report.pdf',
format: 'A4',
printBackground: true,
timeout: 180000,
waitForFonts: true
});
console.log(`PDF created in ${Date.now() - started} ms`);
} catch (error) {
console.error(`PDF failed after ${Date.now() - started} ms`);
console.error(error);
process.exitCode = 1;
} finally {
await browser.close();
}
The PDF guide and PDFOptions reference document print CSS media for PDF generation. They also list waitForFonts: true as the default. Consequently, a page whose web view looks finished can still spend time waiting for fonts or resolving print-specific styles. Increasing the limit gives those steps more time; it does not change the media type or make a missing font available.
How to choose a practical value
- Start with the smallest useful increase. Move from the 30-second documented default to 60 or 120 seconds when the document is known to be slow.
- Measure your own workload. Record navigation time and PDF time separately. A slow
page.goto()is not fixed by a larger PDF timeout. - Keep a finite ceiling for services. A finite value lets a queue retry or report failure. If you pass
0, add an application-level deadline so a stuck job cannot consume a worker indefinitely. - Use a local override for outliers. Keep a normal page default and give only unusually large documents a larger per-call value.
- Account for concurrency. Several simultaneous Chromium exports can compete for CPU and memory, increasing elapsed time without changing the document. Limit parallel jobs before setting an extremely large timeout.
Troubleshooting PDF timeout errors
It still fails at about 30 seconds
Check that the value is inside the object passed to page.pdf(), not inside page.goto() or puppeteer.launch(). For example, page.pdf({ path: 'report.pdf', timeout: 120000 }) is the relevant placement. Confirm that the code path producing the error is the one you changed and that the running process uses the expected Puppeteer package.
The error names a protocol call
This is a different failure class. Inspect the browser connection’s protocolTimeout and raise it only if necessary. A larger PDFOptions timeout cannot extend a protocol call that has already reached its own ceiling.
Navigation times out before PDF generation starts
page.goto() has its own navigation wait. Set an appropriate navigation timeout for the page load and diagnose the URL separately. The PDF timeout begins only when PDF generation is invoked.
The page is blank or incomplete
A longer wait cannot supply data that the page failed to load. Check failed requests, authentication, redirects, client-side rendering, and the condition your application uses to decide that the report is ready. If the page depends on a specific element, wait for that application state before calling page.pdf() rather than relying only on elapsed time.
Rank #4
Fonts make the export slow
Because Puppeteer waits for fonts by default, a font host that is slow or unreachable can delay the export. Verify that the browser can reach the font URL and that the page is not repeatedly retrying it. Keep waitForFonts: true when correct typography matters; changing the timeout only changes how long Puppeteer waits.
Disabling the timeout causes workers to hang
Replace an unbounded PDF call with a finite limit, or wrap the job in an application-level timer that closes the browser and marks the job failed. An unlimited Puppeteer timeout is not an unlimited guarantee of progress.
The export is slow only under load
Inspect CPU, memory, browser count, and concurrent exports. Reduce parallelism, reuse a controlled browser strategy, and capture timing data before increasing limits across every job. The official API references provide defaults, not a guaranteed throughput or latency target.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Version and documentation context
The current PDFOptions and ConnectOptions references cited for these defaults were reported as documentation version 25.12.0; the Page.setDefaultTimeout reference was reported as version 25.10.0. Treat those labels as documentation context, not proof that every installed Puppeteer release has identical defaults. Check the API reference that matches your package when upgrading or debugging a deployment-specific difference.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteBest Value
- Used Book in Good Condition
Or skip the browser setup
If your goal is simply to obtain a clean image or PDF of a URL rather than control Chromium from application code, ScreenshotNeo provides a website screenshot API. One GET request returns PNG, JPEG, WebP, or PDF, and the API accepts options for full-page capture, lazy-loaded images, CSS-selector element capture, print settings, custom JavaScript and CSS, waits, headers, cookies, user agents, geolocation, request blocking, caching, signed links, asynchronous jobs, and bulk capture.
Use the documentation at https://screenshotneo.com/docs/ for the complete parameter list. A basic 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
The same call from 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)
And from 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}`);
- Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; more than 60 known consent platforms are handled.
- Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers identify the page verdict and whether the request was billed.
- An MCP server exposes
take_screenshot,get_page_info, andcapture_pdffor Claude, Cursor, and other MCP clients. - The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; Growth is $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan.
Start with 1,000 free screenshots a month—no card required.
Frequently Asked Questions
Does timeout accept seconds or milliseconds?
Milliseconds. For example, timeout: 60000 represents 60 seconds.
Can I set a different timeout for each PDF?
Yes. Put a different timeout value in each call to page.pdf(); that per-call value is more specific than the page-wide default.
What should I change if the PDF error says protocol timeout?
Inspect the browser connection’s protocolTimeout. It is separate from the PDFOptions timeout and must be adjusted only when the error identifies a protocol-call limit.
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.

