Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Call page.pdf() after the page has reached the state you want to print. Pass path to save a file, or omit it and use the returned Uint8Array in an HTTP response, object store, or other application flow.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({
path: 'current-page.pdf',
format: 'A4',
printBackground: true,
});
await browser.close();
This creates current-page.pdf in the process’s current working directory. The rest of this guide covers rendered-state timing, print versus screen CSS, fonts, paper sizing, API downloads, and the failure cases that make a PDF differ from the visible page.
What “current page” means in Puppeteer
A Puppeteer Page represents a browser tab, including its URL, DOM, styles, and the state produced by JavaScript interactions. “Current page” therefore means the rendered state held by that object when page.pdf() runs. If you start from a URL, navigate first. If your script has already clicked controls, filled a form, expanded an accordion, or changed the route, call page.pdf() after those actions to print that resulting state.
Recommended Free Tools
The navigation option waitUntil: 'networkidle2' is a useful starting point: it waits for a period with no more than two active network connections. It is not proof that every chart, data request, animation, or delayed component has finished. Add a readiness check that represents your application, such as waiting for a report container or a “loaded” marker.
#1 Best Overall
Wait for application content explicitly
await page.goto('https://example.com/report', {
waitUntil: 'networkidle2',
});
await page.waitForSelector('[data-report-ready]', {
visible: true,
timeout: 30_000,
});
await page.pdf({ path: 'report.pdf', format: 'A4' });
For a page that renders after a user action, perform the action and wait for its result before printing:
await page.click('#show-details');
await page.waitForSelector('#details-panel.is-ready');
await page.pdf({ path: 'details.pdf', printBackground: true });
Save the PDF to a file
The path option makes Puppeteer write the generated document. Relative paths are resolved from the Node.js process’s current working directory; use an absolute path when a service’s working directory is not predictable.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({
path: '/tmp/example-page.pdf',
format: 'A4',
printBackground: true,
margin: { top: '16mm', right: '16mm', bottom: '16mm', left: '16mm' },
});
} finally {
await browser.close();
}
Use try/finally in long-running jobs so the browser closes even if navigation or PDF generation fails.
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 matchReturn a PDF from an HTTP endpoint
Omit path to keep the bytes in memory. page.pdf() returns a Promise<Uint8Array>. The framework-specific response method varies, but the response must use the PDF media type and a download disposition.
import express from 'express';
import puppeteer from 'puppeteer';
const app = express();
app.get('/download.pdf', async (req, res) => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const pdfBytes = await page.pdf({
format: 'A4',
printBackground: true,
});
res.set({
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="current-page.pdf"',
});
res.send(Buffer.from(pdfBytes));
} catch (error) {
if (!res.headersSent) res.status(500).send('PDF generation failed');
} finally {
await browser.close();
}
});
app.listen(3000);
Keep browser launch and page creation inside your resource-management strategy. In a production service, a reusable browser with carefully managed pages can reduce launch overhead, while isolating jobs and closing pages prevents state leaking between requests.
Rank #2
Download the endpoint with cURL
curl -fL http://localhost:3000/download.pdf -o current-page.pdf
Download it with Python
import requests
response = requests.get('http://localhost:3000/download.pdf', timeout=90)
response.raise_for_status()
with open('current-page.pdf', 'wb') as output:
output.write(response.content)
Print CSS versus screen CSS
Puppeteer generates PDFs using the print CSS media type by default. Print rules can hide navigation, change colors, or alter layout, so a PDF may not match what you saw on screen.
Make the PDF follow screen styles
await page.emulateMediaType('screen');
await page.pdf({
path: 'screen-styled.pdf',
format: 'A4',
printBackground: true,
});
Use this when the on-screen design, rather than a print-specific layout, is the intended result. If you want print styles, leave the media type at its default and define them with @media print.
Free tools Windows power users keep installed
One-click scans. No signup required.
Preserve colors and backgrounds
Background graphics are disabled by default. Set printBackground: true to include background images and colors. Browsers may still adjust colors for printing; add this CSS when exact colors matter:
*, *::before, *::after {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
Use this selectively: forcing every color can increase ink-heavy output and may override intentional print contrast choices.
Paper size, margins, and CSS page rules
format selects a standard paper size; the documented default is letter. Common alternatives include A4. When format is set, it takes priority over width and height.
await page.pdf({
path: 'invoice.pdf',
format: 'A4',
landscape: false,
margin: {
top: '12mm',
right: '12mm',
bottom: '14mm',
left: '12mm',
},
printBackground: true,
});
If the document defines its own paper dimensions with CSS @page, use preferCSSPageSize: true. Otherwise Puppeteer scales the content to fit the selected paper dimensions.
@page {
size: 210mm 297mm;
margin: 10mm;
}
await page.pdf({
path: 'css-sized.pdf',
preferCSSPageSize: true,
printBackground: true,
});
Fonts and rendering readiness
Puppeteer waits for document.fonts.ready by default through waitForFonts: true. This helps prevent fallback fonts from changing line wraps and page counts. A background page can prevent that wait from resolving; bring it to the front before PDF generation when necessary:
await page.bringToFront();
await page.pdf({
path: 'font-complete.pdf',
waitForFonts: true,
});
Font readiness does not replace application readiness. Wait separately for data-driven components, images, or charts that your page creates after navigation.
Important page.pdf() options
| Option | Use | Default or constraint |
|---|---|---|
path |
Write the PDF to disk. | Omit for returned bytes; relative paths use the current working directory. |
format |
Select paper such as A4 or letter. |
letter is documented as the default; it overrides width and height. |
printBackground |
Include background graphics. | false. |
preferCSSPageSize |
Honor CSS @page dimensions. |
false; otherwise content is fitted to the selected paper. |
landscape |
Use horizontal orientation. | false. |
margin |
Set top, right, bottom, and left margins. | Specify CSS length strings. |
pageRanges |
Print selected pages, for example 1-5, 8, 11-13. |
Empty value prints all pages. |
scale |
Adjust rendered size. | Range 0.1–2; default 1. |
timeout |
Limit PDF generation time. | 30,000 ms; 0 disables the timeout. |
waitForFonts |
Wait for document fonts. | true. |
tagged |
Generate a tagged/accessibility PDF. | Experimental; default true. |
outline |
Generate a document outline. | Experimental; default false. |
Troubleshoot PDFs that look wrong
Content is missing
Cause: the page was printed before an asynchronous component finished. Fix: wait for a specific selector or application-ready signal after navigation, rather than relying only on networkidle2.
Colors or hero images are absent
Cause: print backgrounds are disabled or print CSS removes the element. Fix: set printBackground: true, inspect print rules, and use emulateMediaType('screen') when screen styling is required.
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
Text wraps differently or uses a fallback font
Cause: web fonts were not ready when layout was captured. Fix: retain waitForFonts: true, wait for the font-loading state, and call bringToFront() for a background page if the font wait stalls.
The paper size is unexpected
Cause: format overrides width and height, or CSS @page is being ignored. Fix: remove conflicting dimensions and set preferCSSPageSize: true when CSS owns the page size.
The job times out
Cause: a slow page, unresolved font promise, or a PDF that takes longer than the 30-second default. Fix: correct the readiness condition first; then set a suitable timeout or use 0 only when your surrounding job timeout provides the safety limit.
The API response is corrupt or opens as text
Cause: the server sent a string representation instead of the binary bytes, or omitted the content type. Fix: convert the Uint8Array to the runtime’s binary buffer, send Content-Type: application/pdf, and use a download filename in Content-Disposition.
Performance and reliability choices
- Navigate with an explicit readiness condition so you do not print incomplete pages or wait indefinitely for analytics connections.
- Set a PDF timeout and an outer request timeout; they protect different stages of the operation.
- Close each page and browser in cleanup code. Reusing a browser can reduce launch cost, but isolate cookies, local storage, and authentication state between unrelated jobs.
- Use
pageRangesfor large documents when only selected pages are needed. - Keep
scaleat1unless you have a measured layout reason to change it; scaling can alter readability and pagination.
Or skip the browser setup
ScreenshotNeo provides a website screenshot and PDF API when you want a hosted capture rather than managing Chromium. Its PDF endpoint accepts the target URL and options, and the documentation lists the complete parameter set.
Best Value
- Used Book in Good Condition
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For a PDF, request the PDF output option described in the documentation. ScreenshotNeo removes cookie-consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf through Claude, Cursor, or another MCP client.
The Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Sign up for the free ScreenshotNeo plan.
Frequently Asked Questions
Can I print the page after clicking or filling controls?
Yes. Perform the interaction on the same Page object, wait for the resulting UI state, and then call page.pdf().
How do I print only selected pages?
Pass a range string such as pageRanges: '1-5, 8, 11-13'. An empty range prints the complete document.
Which Puppeteer option creates an accessible PDF?
The tagged option controls tagged PDF generation; Puppeteer documents it as experimental and enabled by default.
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.

