Skip to content
On this page

PDF like on screen: settings that just work

You want a PDF that looks like what you see in the browser: everything loaded, backgrounds and colors printed, no missing content. Here’s a ready-to-use request body that works in most cases. Copy it, replace the URL (and add your API key), and you’re good to go.

One body that does it all

  • Loads the page fully — waits until the network is idle (networkidle0).
  • Waits for your content — optional waitForSelector so SPAs and async content are ready.
  • Prints backgroundsprintBackground: true so CSS backgrounds and colors appear in the PDF.
  • Screen-like renderingemulateMediaType: "screen" so the PDF matches how the page looks on screen (not print CSS).

Use this with the PDF sync or PDF direct route.

json
{
  "page": {
    "goto": {
      "url": "https://your-page.com/your-document",
      "options": {
        "waitUntil": ["networkidle0"]
      }
    },
    "emulateMediaType": "screen",
    "waitForSelector": {
      "selector": "body",
      "options": { "timeout": 15000, "visible": true }
    },
    "pdf": {
      "printBackground": true,
      "format": "A4"
    }
  }
}
  • waitUntil: ["networkidle0"] — Doppio waits until there are no more than 0 network connections for 500ms. Your images, fonts and API calls have time to finish.
  • emulateMediaType: "screen" — The page is rendered with @media screen (and no @media print), so the PDF looks like the browser view.
  • waitForSelector — Waits for body to be visible (up to 15s). For SPAs or slow pages, replace "body" with a selector that appears when content is ready (e.g. "#app .loaded", ".report-ready").
  • printBackground: true — Backgrounds and box-shadows are included in the PDF.

When to tweak

SituationWhat to do
Content appears after JS (SPA, dashboard)Set waitForSelector.selector to an element that exists only when the main content is rendered (e.g. "#chart", "[data-ready]").
Page sets a “ready” flagUse waitForFunction instead of or after waitForSelector, e.g. "pageFunction": "() => window.__APP_READY__ === true".
You want print styles (margins, page breaks)Use "emulateMediaType": "print" so the browser uses @media print CSS.
Very long page / lazy-loaded sectionsKeep networkidle0; if some content only loads when in view, add a waitForSelector (or waitForFunction) that targets an element at the bottom or a “loading complete” indicator.

Minimal “no surprises” example

If you don’t need to wait for a specific selector, this is the smallest body that still loads the page fully and prints like the screen:

json
{
  "page": {
    "goto": {
      "url": "https://your-page.com/your-document",
      "options": { "waitUntil": ["networkidle0"] }
    },
    "emulateMediaType": "screen",
    "pdf": { "printBackground": true }
  }
}

For more options (margins, paper size, timeout, etc.) see Common params and PDF params.

Dark theme / background

Sites that use a class on html for dark mode (e.g. html.dark) or prefers-color-scheme often render in light mode in headless Chrome, because no theme is forced. So the PDF can have a white or light background even with printBackground: true. That’s the page’s behavior in that context, not an API bug. To get a dark PDF, the page would need to force dark mode (e.g. always add the class, or detect the render context).

All rights reserved