Short answer: Treat the PDF as print output, not a screenshot. Put the paper size and margins in print CSS, call page.pdf({ preferCSSPageSize: true }), use modern break-before/break-inside rules on real in-flow elements, and wait for fonts, images, and application data before capture. You can make breaks deterministic for a fixed Chromium/Puppeteer build and stable content; CSS cannot guarantee one universal break when several legal break points exist.
What “match HTML exactly” means in Puppeteer
A browser lays out a screen as a continuous canvas. A PDF is paged media: the same boxes must be divided into discrete sheets. CSS fragmentation rules decide where a page may split, and the specification does not require a browser to choose one particular legal break when several are available. Therefore, “exact” means controlling every print input and validating the generated PDF, not expecting every browser version to make identical choices from loosely constrained HTML.
Puppeteer’s page.pdf() uses the print CSS media type. If your page normally relies on screen styles, those styles will not be the ones used unless you explicitly emulate screen media. For a print document, make print mode intentional:
await page.emulateMediaType('print');
Keep one source of truth for paper geometry. Define @page size and margins in CSS and set preferCSSPageSize: true; that gives the CSS page size priority over Puppeteer’s format, width, and height options.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errors#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.
A minimal, repeatable Puppeteer setup
The following example waits for application rendering, fonts, and images, then generates an A4 PDF using the CSS page box. Replace the URL and readiness hook with your own page.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com/report', {
waitUntil: 'networkidle0'
});
// If your application exposes a render promise or marker, await it here.
await page.waitForSelector('[data-report-ready]');
await page.evaluate(async () => {
await document.fonts.ready;
const images = Array.from(document.images);
await Promise.all(images.map(image => {
if (image.complete) return Promise.resolve();
return new Promise(resolve => {
image.addEventListener('load', resolve, { once: true });
image.addEventListener('error', resolve, { once: true });
});
}));
});
await page.emulateMediaType('print');
await page.pdf({
path: 'report.pdf',
preferCSSPageSize: true,
printBackground: true
});
await browser.close();
})();
networkidle0 only describes network activity. It does not prove that client-side data, fonts, or image dimensions are ready, so retain explicit application and asset checks.
Set paper size and margins in one place
Use a print stylesheet such as this:
@page {
size: A4 portrait;
margin: 16mm 14mm 18mm;
}
@media print {
body {
margin: 0;
color: #111;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.page-start {
break-before: page;
page-break-before: always; /* compatibility alias */
}
.keep-together {
break-inside: avoid;
page-break-inside: avoid; /* compatibility alias */
}
}
Do not combine an @page size with an unrelated format or fixed width in the PDF call unless you deliberately want Puppeteer’s paper option to win. With preferCSSPageSize: true, the CSS declaration is the authoritative geometry. Keep units explicit and test portrait and landscape as separate templates.
printBackground: true preserves background colors and images. The -webkit-print-color-adjust: exact declaration asks Chromium to retain specified colors when color fidelity matters; it does not change pagination.
Use the right break property for each job
Force a section onto a new page
Attach break-before: page to the heading, section wrapper, or other block that actually starts the next section:
<section class="chapter page-start">
<h2>Chapter 2</h2>
...
</section>
A forced break on a real block in normal flow is dependable. A rule on an empty element, a display: none node, or an element that generates no box is ignored because there is no box at which to fragment.
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.
Force a break after a section
Use break-after: page when the current element defines the end of a unit:
.invoice-page {
break-after: page;
}
Use one boundary rule, not several competing rules on adjacent wrappers, unless you have a specific reason. Extra forced breaks commonly create blank pages.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Keep a bounded component together
Cards, figures, callouts, signature blocks, and a heading with its short introduction can use:
.callout,
figure,
.signature-block,
.heading-intro {
break-inside: avoid;
}
page-break-inside: avoid is the older compatibility alias. Prefer break-inside in new stylesheets and keep the alias if an older rendering environment still needs it.
Understand precedence
At a potential break, the browser considers the preceding element’s break-after, the following element’s break-before, and the containing element’s break-inside. Forced values take precedence over avoid values according to the fragmentation rules. Inspect all three locations when a rule appears to be ignored; changing only the element you can see may not remove a conflicting ancestor or sibling declaration.
Why an “avoid” rule can still split
break-inside: avoid suppresses an eligible internal break; it cannot make an element shorter than a page. If a table, code listing, image, or card is taller than the printable page, the printer must emit as much as fits and continue on later pages. Do not use avoid as a guarantee that arbitrarily long content will remain intact.
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.
For long content, design intentional subdivision instead: split a report into bounded sections, allow paragraphs and tables to flow, and place page-start markers between known sections. A fixed-height container is not a solution; it can clip content or create overflow that fragments unpredictably.
Stabilize layout before calling page.pdf()
Wait for application data
After navigation, wait for the promise or DOM marker that means the final data has rendered. A network-idle event can occur while a client-side request, chart, or virtualized list is still being assembled.
Wait for fonts
Font metrics change line wrapping and therefore every later page boundary. Puppeteer’s PDF flow waits for fonts by default, but application fonts still need to be requested and selected before capture. Await document.fonts.ready and verify that your intended font-family is actually applied.
Wait for images and set dimensions
Late image dimensions reflow text. Wait for each image to load (or fail), and provide stable width/height or an aspect-ratio so layout is reserved before the asset arrives.
Keep printable content in normal flow
Flex and grid containers, transforms, absolute positioning, and overflow clipping can fragment differently from ordinary blocks. They are not forbidden, but test them in the exact Chromium version used in production. For the most predictable pagination, use block-flow wrappers around sections and avoid overflow: hidden, transforms, and fixed heights on the printable path unless they are part of a tested template.
Diagnose page-break drift systematically
| Symptom | Likely cause | Fix |
|---|---|---|
| The PDF uses the wrong paper size | @page conflicts with format, width, or height |
Declare size and margins in @page and enable preferCSSPageSize: true. |
| A forced break does nothing | The target is empty, hidden, or outside normal flow | Move the rule to a generated block wrapper that remains in flow. |
| A card still splits | The card is taller than the printable page, or an ancestor fragments it | Allow the long content to flow or split it into smaller bounded units; inspect ancestor break-inside. |
| Breaks move between runs | Fonts, images, or data are still changing layout | Await the render marker, document.fonts.ready, and image completion before PDF generation. |
| Colors disappear | Print backgrounds are disabled | Set printBackground: true and use print color-adjust rules where needed. |
| Unexpected blank pages appear | Forced breaks occur on adjacent sections or a trailing element | Inspect neighboring break-before/break-after declarations and remove duplicate boundaries. |
| Screen layout appears in the PDF | Screen emulation or screen-only CSS is active | Use page.emulateMediaType('print') and place pagination rules in @media print. |
| Content is clipped | Fixed height or overflow clipping on a printable container | Remove the constraint, use auto height, and let the element fragment. |
When investigating one boundary, inspect the element immediately before and after it, then walk up through ancestors. Record their computed break-before, break-after, break-inside, display mode, height, and overflow. This is faster than adding random page-break-before declarations.
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
Make output reproducible in production
- Pin the Chromium and Puppeteer versions used for generation. Font rasterization, layout fixes, and fragmentation behavior can change between browser builds.
- Keep print CSS, font files, images, and data deterministic. A changing timestamp, rotating ad, or locale-dependent string can alter line wrapping.
- Compare generated PDFs by page count and boundary locations, not only by a screen preview. A visual diff of rendered pages catches one-line shifts that page count misses.
- Use a stable viewport and timezone when your template includes responsive or date-sensitive content.
- Generate one document at a time while debugging. Parallel captures can expose race conditions in shared data or temporary assets.
Pagination has a practical cost: each navigation, font load, image decode, and PDF render consumes time and memory. Waiting for readiness adds latency, but skipping those waits produces documents that are visually inconsistent and harder to retry. For large reports, split genuinely independent documents rather than forcing one enormous element to remain together.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Complete CSS pattern for a report
@page {
size: A4 portrait;
margin: 16mm 14mm 18mm;
}
@media print {
html, body {
margin: 0;
padding: 0;
}
.report-section {
break-before: auto;
}
.report-section + .report-section {
break-before: page;
}
.figure,
.metric-card,
.signature-block {
break-inside: avoid;
}
.long-table,
.long-code {
break-inside: auto;
}
.screen-only {
display: none !important;
}
}
This pattern forces a new page between sibling report sections, keeps bounded components intact, and deliberately permits long tables and code blocks to continue across pages. Adjust the selectors to your document’s semantic structure instead of applying avoid globally.
Recommended Free Tools
Or skip the browser setup
If you need a clean capture of a URL rather than maintaining Chromium, Puppeteer launch code, and print-readiness checks, ScreenshotNeo provides a website screenshot API and MCP server. A single GET request returns an image (PNG, JPEG, or WebP) or a PDF; the API accepts full-page capture, viewport and device settings, custom CSS and JavaScript, waiting rules, cookies and headers, and other capture controls. The API documentation is at https://screenshotneo.com/docs/.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers identify the page verdict and billing status. Its MCP server includes take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots each month with no card, and paid plans start at $5 for 3,000 shots. Sign up for the free plan.
FAQ
Should I set emulateMediaType('print') if page.pdf() already prints?
Yes when you want the intent to be explicit and the script may later capture screenshots or change media modes. It also makes debugging easier because the chosen media type is visible in the capture code.
Can CSS guarantee identical breaks across Chromium versions?
No. It can constrain legal break points, but the browser may choose differently among remaining legal points. Pin the browser build and compare output in continuous integration.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →What is the safest way to handle a very long table?
Allow it to fragment naturally, reserve stable column widths, and avoid wrapping the entire table in break-inside: avoid. Keeping a table taller than a page cannot succeed without clipping or continuation.
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.
Why does changing a font weight alter later page breaks?
Different font metrics change line widths and line counts. That changes block heights, so every subsequent fragmentation opportunity can move even when the break CSS is unchanged.
Frequently Asked Questions
Should I set emulateMediaType('print') if page.pdf() already prints?
Yes when you want the intent to be explicit and the script may later capture screenshots or change media modes. It also makes debugging easier because the chosen media type is visible in the capture code.
Can CSS guarantee identical breaks across Chromium versions?
No. It can constrain legal break points, but the browser may choose differently among remaining legal points. Pin the browser build and compare output in continuous integration.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →What is the safest way to handle a very long table?
Allow it to fragment naturally, reserve stable column widths, and avoid wrapping the entire table in break-inside: avoid. Keeping a table taller than a page cannot succeed without clipping or continuation.
Why does changing a font weight alter later page breaks?
Different font metrics change line widths and line counts. That changes block heights, so every subsequent fragmentation opportunity can move even when the break CSS is unchanged.
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.

