Chrome CDP Page.printToPDF A4 settings: paperWidth and paperHeight in inches
Sets A4 paper size in Chrome DevTools Protocol Page.printToPDF calls using paperWidth 8.2677 and paperHeight 11.6929 inches, explicit inch margins, and a page-box check in points to confirm the output. Use when a raw CDP, Puppeteer CDPSession, Playwright CDPSession, or chromedp print comes out as US Letter instead of A4, or at a huge size after millimetre values were passed. Not for the Puppeteer or Playwright page.pdf format option.
Chrome CDP Page.printToPDF A4 settings: paperWidth and paperHeight in inches
TL;DR
Chrome DevTools Protocol Page.printToPDF has no A4 preset and no format field. Its paperWidth and paperHeight parameters are numbers in inches, and the defaults are US Letter (8.5 by 11). For A4, pass paperWidth: 8.2677 and paperHeight: 11.6929 (210 by 297 mm divided by 25.4), set preferCSSPageSize: false, and set the four margins explicitly in inches too. Verify the result by reading the PDF page box: exact A4 measures 595.28 by 841.89 points.
The query
chrome cdp printtopdf paperwidth paperheight a4 settingsThe symptom behind it: a PDF produced over raw CDP (or through a CDP session in Puppeteer or Playwright) comes out at US Letter size, or at a wildly wrong size after millimetre values are passed, even though the caller asked for A4.
Fix: raw CDP call
- Navigate to the page and wait for load plus any async rendering to finish. Success check: the document title or a ready marker element is present before you print.
- Send
Page.printToPDFwith A4 dimensions in inches. A complete portrait A4 parameter set:
{
"landscape": false,
"printBackground": true,
"scale": 1,
"paperWidth": 8.2677,
"paperHeight": 11.6929,
"marginTop": 0.4,
"marginBottom": 0.4,
"marginLeft": 0.4,
"marginRight": 0.4,
"pageRanges": "",
"preferCSSPageSize": false
}Success check: the call returns without a protocol error. A parameter type error here almost always means a value was sent as a string or in millimetres.
- Save the returned payload. By default the response carries the PDF as base64 in its data field. Decode it to a .pdf file. Success check: the file starts with the %PDF- header bytes and opens in a PDF viewer.
- Verify the page box before shipping the file (step below). Never trust the request parameters alone.
Fix: Node with puppeteer-core CDPSession
const fs = require('fs');
// page is a puppeteer-core Page connected to Chrome or Chromium
const client = await page.createCDPSession();
const result = await client.send('Page.printToPDF', {
landscape: false,
printBackground: true,
scale: 1,
paperWidth: 8.2677,
paperHeight: 11.6929,
marginTop: 0.4,
marginBottom: 0.4,
marginLeft: 0.4,
marginRight: 0.4,
pageRanges: '',
preferCSSPageSize: false
});
fs.writeFileSync('out.pdf', Buffer.from(result.data, 'base64'));
console.log('wrote out.pdf');Expected output: wrote out.pdf, and the file passes the page-box check below.
Verify the output is really A4
PDF page boxes are measured in points (72 points per inch), so A4 is 595.28 by 841.89 pt and Letter is 612 by 792 pt.
- With poppler-utils: run
pdfinfo out.pdfand read the Page size line. Expected:Page size: 595.28 x 841.89 pts (A4). - Or with PyMuPDF in Python: open the file, read the first page rect, and print its width and height. Expected: about 595.3 by 841.9.
- If you see 612 by 792, the size parameters never took effect and Chrome fell back to its Letter default. If you see a page thousands of points wide, millimetres were passed where inches were expected.
Size reference (inches and points)
- A4 portrait: 210 by 297 mm, 8.2677 by 11.6929 in, 595.28 by 841.89 pt
- A4 landscape: swap width and height, and set landscape to true
- A5 portrait: 148 by 210 mm, 5.8268 by 8.2677 in, 419.53 by 595.28 pt
- US Letter portrait: 8.5 by 11 in, 612 by 792 pt (the CDP default)
- US Legal portrait: 8.5 by 14 in, 612 by 1008 pt
Note on precision: the rounded pair 8.27 by 11.69 is widely used and Chrome treats it as A4, but it yields a page box of about 595.44 by 841.68 pt. Use the full-precision pair 8.2677 by 11.6929 when a downstream system checks the page box exactly.
When to use this
- You call
Page.printToPDFdirectly over a DevTools Protocol websocket. - You print through a CDP session object (Puppeteer
createCDPSession, PlaywrightnewCDPSession, chromedp, chrome-remote-interface) and the output is Letter instead of A4. - A wrapper library forwards raw printToPDF parameters unchanged.
When not to use this
- Puppeteer high-level
page.pdf()calls: that wrapper has its ownformat: 'A4'option pluswidthandheightoptions that accept unit strings such as '8.27in'. Prefer those there; the raw names in this skill are the underlying CDP parameters the wrapper translates to. - Playwright high-level
page.pdf(): it also exposesformat: 'A4'and is Chromium-only. Use the raw parameters only when you dropped down to a CDP session yourself. - Pages that define their own print size in CSS and should keep it: set
preferCSSPageSize: trueinstead and fix the CSS size rule, because with that flag on, the CSS size wins over paperWidth and paperHeight.
Variant phrasings
printToPDF returns Letter instead of A4
Same fix. Omitting paperWidth and paperHeight silently keeps the 8.5 by 11 inch default regardless of system locale or printer settings.
paperWidth 210 paperHeight 297 gives a huge or clamped page
210 and 297 are millimetres. The protocol reads them as inches, so the requested sheet is over 17 feet tall and Chrome clamps or errors. Always convert: inches = millimetres / 25.4.
A4 pages but content is cut off at the edges
That is margins, not paper size. The default margins are 1 cm (about 0.4 in) each side. Set marginTop, marginBottom, marginLeft, and marginRight explicitly, in inches, and keep header and footer templates inside the top and bottom margins when displayHeaderFooter is on.
CSS page rule overrides the CDP paper size
If the document carries a CSS at-page size rule and preferCSSPageSize is true, Chrome uses the CSS size and ignores paperWidth and paperHeight. Either set the flag to false or change the CSS rule; do not fight it by changing both.
Why it happens
The CDP print API was designed around the US printing stack: dimensions and margins are plain numbers in inches, there is no named-format enum at the protocol level, and the defaults are Letter with 1 cm margins. Named sizes like A4 only exist in the higher-level wrappers (Puppeteer, Playwright) that translate a format name into these inch values before sending the command. Anyone working at the raw protocol layer has to do that translation themselves, and the two classic mistakes are passing millimetres and assuming the browser locale changes the default.
Edge cases
- Landscape: set landscape to true AND swap the dimensions (paperWidth 11.6929, paperHeight 8.2677). Setting only one of the two gives inconsistent results across Chrome versions.
- Scale does not change the paper box. Scale shrinks or grows the rendered content on the same sheet; a wrong Page size reading in pdfinfo is never a scale problem.
- Large PDFs: for big documents prefer the stream transfer mode in newer protocol versions and read the stream in chunks instead of one base64 string, which can hit message size limits.
- Header and footer templates are HTML strings rendered in an isolated context with their own inline styles; they do not inherit page CSS, and they only appear when displayHeaderFooter is true and the margins leave room for them.
- Chromium and Chrome behave the same here; the parameters are stable across current Chrome, Chromium, and headless shell builds. Very old Chrome versions (before roughly version 61) ignored printToPDF parameters entirely.
Compatibility
- Chrome DevTools Protocol, Page domain,
Page.printToPDF: current stable protocol (tot) and 1-3 branch. - Works from any CDP client: raw websocket, puppeteer-core CDPSession, Playwright CDPSession, chromedp (which exposes the same fields on its print params), chrome-remote-interface.
- Verification tools: pdfinfo (poppler-utils) or PyMuPDF, any recent version.