Recommended Free Tools
Edit the rendered page in Puppeteer’s browser context, wait for every asynchronous change your page requires, and only then call page.pdf(). Puppeteer uses print CSS by default; switch to screen CSS explicitly when the PDF should match the on-screen design.
The reliable edit-then-PDF workflow
A PDF captures the page state that exists when page.pdf() runs. The dependable sequence is therefore:
- Create a page and either navigate to a URL with
page.goto()or load supplied markup withpage.setContent(). - Make the content, attribute, or style changes inside the page with
page.evaluate(),$eval(), or$$eval(). - Await application rendering, data loading, font readiness, or other work that must finish before printing.
- Choose print or screen media and configure the PDF options.
- Call
page.pdf()and close the browser after the file has been written.
page.evaluate() runs in the browser context. If its callback returns a promise, Puppeteer waits for that promise, so an asynchronous callback is the right place to wait for an edit that your own code triggers.
A complete Node.js example
The following script navigates to a page, changes its heading and introductory text, removes a promotional element when it exists, waits for a page-specific readiness marker, and creates a PDF. Replace the URL and selectors with those from your page.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 90000
});
await page.evaluate(async () => {
const heading = document.querySelector('h1');
if (heading) heading.textContent = 'Updated heading';
const intro = document.querySelector('.intro');
if (intro) {
intro.textContent = 'Text prepared for the PDF.';
}
const promotion = document.querySelector('[data-promotion]');
if (promotion) promotion.remove();
// Await application-specific work here if your edit starts any.
// For example, wait for a readiness marker set by page code:
await new Promise(resolve => {
if (document.documentElement.dataset.pdfReady === 'true') {
resolve();
return;
}
const observer = new MutationObserver(() => {
if (document.documentElement.dataset.pdfReady === 'true') {
observer.disconnect();
resolve();
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-pdf-ready']
});
});
});
// page.pdf() uses print CSS unless you select another media type.
// await page.emulateMediaType('screen');
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
waitForFonts: true,
margin: {
top: '18mm',
right: '16mm',
bottom: '18mm',
left: '16mm'
}
});
} finally {
await browser.close();
}
})();
The readiness example is deliberately page-specific. If your page has no asynchronous work after the edit, do not add an artificial wait. If a selector is optional, test the result of querySelector() as shown. By contrast, $eval() is useful when the selector must exist and you want a callback for the first match; a missing selector produces an error, which can be desirable when a missing element means the page is invalid.
Editing content safely in the page context
Change text without rebuilding the document
Use textContent for plain text. It treats the value as text rather than interpreting it as markup.
await page.evaluate(() => {
const title = document.querySelector('[data-pdf-title]');
if (!title) throw new Error('Required title element was not found');
title.textContent = 'Quarterly operations report';
});
Use innerHTML only when you intentionally control the markup being inserted. For a collection of elements, $$eval() receives all matching nodes in one callback:
await page.$$eval('.temporary-note', notes => {
for (const note of notes) note.remove();
});
Change attributes, classes, and visibility
await page.evaluate(() => {
const logo = document.querySelector('img.logo');
if (logo) {
logo.setAttribute('alt', 'Company logo');
logo.classList.add('pdf-logo');
}
document.querySelectorAll('[data-hide-in-pdf]').forEach(node => {
node.remove();
});
});
Removing a node is usually more deterministic than relying on a later stylesheet rule. If the element must remain in the document for layout or scripts, add a class instead and define the corresponding print rule.
Inject a focused style change
page.addStyleTag() can add CSS without changing the site’s source files. This is useful for a one-off print treatment:
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
await page.addStyleTag({
content: `
.pdf-only-banner { display: block !important; }
.screen-only-control { display: none !important; }
h1 { color: #111 !important; }
`
});
Apply the style before generating the PDF. Remember that the final result still depends on whether the page is using print or screen media at that moment.
Wait for application updates, not just navigation
waitUntil: 'networkidle2' helps navigation settle, but it cannot know when your application has finished a client-side render, an API-driven replacement, or a chart update. Put the relevant wait in an asynchronous page.evaluate() callback, or wait for a page condition that identifies completion. A fixed delay can be useful for a known animation, but a readiness condition is less likely to capture an intermediate state.
await page.evaluate(async () => {
await window.renderReportForPdf();
const report = document.querySelector('#report');
if (!report || report.getAttribute('data-rendered') !== 'true') {
throw new Error('Report did not reach its PDF-ready state');
}
});
The callback’s returned promise must represent all work that matters. Starting an asynchronous task without awaiting it lets page.pdf() run too soon.
Printing navigated pages versus supplied HTML
| Starting point | Use | Important consideration |
|---|---|---|
| Existing website | await page.goto(url, options) |
Wait for navigation and then for application-specific rendering before editing. |
| HTML you generate | await page.setContent(html) |
Include the styles, fonts, images, and markup required by the supplied document before editing. |
Choose navigation when the page’s own scripts and assets are part of the document. Choose setContent() when your program already owns the HTML and wants a controlled starting document.
Control the PDF’s media, paper, and pagination
page.pdf() uses the print CSS media type by default. That means a stylesheet’s @media print rules can hide navigation, change colors, or rearrange content. If the PDF should follow the screen stylesheet instead, select screen media immediately before creating the file:
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-styled.pdf', printBackground: true });
The principal PDF controls are:
| Option or method | What it controls | Default or caveat |
|---|---|---|
emulateMediaType('screen') |
Selects screen CSS rather than print CSS. | Print media is used by default. |
printBackground |
Includes background colors and images. | Defaults to false; set true when those graphics matter. |
waitForFonts |
Waits for fonts before output. | Font waiting is enabled by default. |
format |
Named paper size such as Letter or A4. | Letter is the default when no other size is selected. |
width and height |
Explicit paper dimensions. | Use when a named format does not match the required sheet. |
margin |
Top, right, bottom, and left printable margins. | Specify units such as mm, in, or px. |
landscape |
Rotates the page orientation. | Useful for wide tables and dashboards. |
scale |
Scales rendered content on the sheet. | Changing it affects how much content fits on each page. |
pageRanges |
Limits output to selected page ranges. | Useful after you have verified the full document’s pagination. |
preferCSSPageSize |
Lets CSS @page sizing take precedence. |
Use when the document’s stylesheet defines the authoritative paper size. |
timeout |
Sets the PDF operation’s timeout. | Increase it only when slow rendering is expected and diagnosed. |
Browsers may adjust colors for print. When exact color reproduction is important, the PDF documentation points to the CSS property -webkit-print-color-adjust. Set it in the stylesheet that is active for the selected media type, and still enable printBackground when backgrounds must be emitted.
CSS page sizing and layout decisions
There are two independent decisions: which CSS media rules apply and which source defines the paper dimensions. Let the PDF options define the size when the calling program owns the output contract. Let @page define it when the document’s CSS is designed for a particular paper size, and enable preferCSSPageSize so that definition wins.
Windows 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 reinstallOutdated 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 matchFor wide content, test landscape, a suitable format or explicit width, and a deliberate scale together. Shrinking everything until it fits can make text unreadable; changing orientation or removing nonessential columns is often a better edit.
Troubleshooting common failures
The PDF contains the old text
Most often, the edit ran against the wrong selector or an asynchronous render replaced it afterward. Verify the selector inside page.evaluate(), perform the edit after the page’s own render, and await the readiness condition that represents the final DOM.
An optional element causes the script to fail
$eval() expects a match. Use document.querySelector() and an explicit null check when absence is valid, or use $$eval() when zero or more matches are expected.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
The PDF looks different from the browser
Check media first: print CSS is the default. Call await page.emulateMediaType('screen') when screen rules are intended. Then check printBackground, print-only selectors, color adjustment, margins, and scale.
Fonts or icons are missing
Keep waitForFonts: true (the default), make sure the page has reached the state in which the font is requested, and avoid generating the PDF while the application is still replacing fallback text or icons. If a custom readiness signal exists, await it before page.pdf().
The output is blank or incomplete
Confirm that navigation or setContent() completed, that the edit did not remove the main container, and that your asynchronous callback actually awaits its work. A navigation-idle event alone does not guarantee that client-side data has been rendered.
Background artwork is absent
Set printBackground: true. If the artwork is still missing, inspect the active print stylesheet and verify that the resource has loaded before PDF generation.
Pages break in awkward places
Adjust margins, scale, orientation, and the relevant print CSS. If only a known subset is needed, use pageRanges after checking the full document. For a document with deliberate CSS paper sizing, use preferCSSPageSize.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Performance and reliability practices
- Use a specific readiness condition instead of an unnecessarily long fixed delay.
- Keep DOM edits in one evaluation block when they belong to the same state transition, then generate the PDF once.
- Fail explicitly for required selectors and handle optional selectors without exceptions.
- Choose
networkidle2or another navigation wait appropriate to the page, then add the application-level wait that navigation cannot provide. - Set a PDF timeout that reflects the page’s real asset and rendering time; increasing it does not fix a selector or readiness bug.
- Record the media type, paper settings, margins, scale, and page ranges with the job so that a later run can reproduce the same layout.
Puppeteer itself does not impose a per-document PDF price in this workflow; your practical costs are the browser runtime and the infrastructure that runs it. Measure rendering time and memory in your own environment rather than assuming that a network-idle event predicts total completion.
Or skip the browser setup
For a clean capture without maintaining a Puppeteer browser workflow, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
The API supports PNG, JPEG, WebP, or PDF output, plus options such as full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, paper and PDF controls, custom CSS and JavaScript, clicks, selector waits, delays, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL-based caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification.
One-call cURL example
See the ScreenshotNeo documentation for the current request options.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to get started.
Final production checklist
- Confirm the page source: navigation or
setContent(). - Confirm required selectors before editing.
- Await all application-specific rendering started by the page or by your edit.
- Select print or screen media deliberately.
- Choose paper size, margins, orientation, scale, and CSS page sizing intentionally.
- Enable backgrounds when the design depends on them and keep font waiting enabled.
- Generate the PDF only after the final DOM and styles are ready.
Frequently Asked Questions
Can I use both DOM edits and injected CSS in one PDF job?
Yes. Apply the DOM changes in the page context, add any temporary stylesheet, wait for the resulting state, and then call page.pdf(). The order matters because the PDF reflects the page as it exists at print time.
When should CSS @page control the paper size?
Use it when the document stylesheet is the authoritative layout definition, and set preferCSSPageSize so that CSS sizing takes precedence over the PDF format or dimensions.
What does Puppeteer wait for automatically before printing?
Fonts are awaited by default. Other application work is not inferred automatically; navigation and your own asynchronous rendering still need an explicit readiness strategy.
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.

