ScreenshotNeo

BlogComparisons

Puppeteer Screenshot vs PDF Output for an HTML Report

Choose Puppeteer screenshots for fixed visual captures and PDFs for paginated reports. Learn how screen and print CSS, page options, and styling affect the result.

By the ScreenshotNeo team4 October 20267 min read

Use Puppeteer’s page.screenshot() when your HTML report should become an image of a viewport, full page, clipped area, or individual element. Use page.pdf() when it should become a paginated document with paper size, orientation, margins, page ranges, or print headers and footers. Puppeteer uses print CSS for PDFs by default; select screen media explicitly if the PDF should match the on-screen layout.

The choice is about the deliverable and its layout rules. Puppeteer’s documentation does not establish that either format is universally faster, smaller, or higher quality.

1. Choose the output for the report’s use

Need Start with Why
A visual snapshot of a chosen screen state Screenshot Capture the viewport, full page, a clipped rectangle, or an element.
One report component as an image Element screenshot An element screenshot scrolls the element into view when needed.
A document for printing or sharing across pages PDF PDF options include paper format, orientation, margins, page ranges, and optional headers and footers.
A PDF that follows the site’s screen styles PDF after selecting screen media PDF generation uses print media by default; call page.emulateMediaType('screen') first.
Print-accurate colors PDF with print color CSS Print color adjustment may change colors unless you request exact color adjustment in CSS.

Official references: screenshot API, PDF API, PDF options, and element screenshot API.

2. Install Puppeteer and prepare the page

The examples below use Node.js. Install Puppeteer in your project:

npm install puppeteer

Navigate to the report before capturing it. Choose a wait condition that matches how the page loads: networkidle0 can be useful for mostly static reports, while pages with continuous requests may need a selector or a deliberate delay instead. Make sure the report data is present before writing the output.

3. Capture the report as a screenshot

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage({
      viewport: { width: 1440, height: 1000 },
      deviceScaleFactor: 1,
    });

    await page.goto('https://example.com/report', {
      waitUntil: 'networkidle0',
    });

    // Capture the full page as PNG.
    await page.screenshot({ path: 'report.png', fullPage: true });

    // For a viewport-only JPEG, use:
    // await page.screenshot({ path: 'report.jpg', type: 'jpeg', quality: 85 });

    // To capture a clipped rectangle instead:
    // await page.screenshot({
    //   path: 'report-section.png',
    //   clip: { x: 0, y: 400, width: 900, height: 600 },
    // });
  } finally {
    await browser.close();
  }
})();

fullPage captures the full page; omit it for the current viewport. clip selects a rectangle. Screenshot options also include the image type and background handling. JPEG quality applies to JPEG output, not PNG. Check the screenshot API and options for the Puppeteer version installed in your project.

Capture one report element

const report = await page.$('#report-summary');
if (!report) throw new Error('Report summary element was not found');
await report.screenshot({ path: 'summary.png' });

Puppeteer scrolls an element into view if needed and captures it through the page screenshot mechanism. Select a stable element and ensure it has loaded before capturing.

4. Generate a paginated PDF

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com/report', {
      waitUntil: 'networkidle0',
    });

    await page.pdf({
      path: 'report.pdf',
      format: 'A4',
      landscape: false,
      printBackground: true,
      margin: {
        top: '16mm',
        right: '14mm',
        bottom: '16mm',
        left: '14mm',
      },
      displayHeaderFooter: false,
      preferCSSPageSize: true,
      waitForFonts: true,
    });
  } finally {
    await browser.close();
  }
})();

For PDFs, the documented default paper format is Letter. Specify a format or CSS page size deliberately when output must be consistent across environments. PDF options include landscape, margin, pageRanges, printBackground, displayHeaderFooter, and preferCSSPageSize. With preferCSSPageSize, CSS @page sizing takes priority; otherwise content is scaled to fit the selected paper size. waitForFonts defaults to true and waits for document.fonts.ready. See the PDF options reference for supported values.

Use screen CSS in the PDF

await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-layout.pdf', format: 'A4' });

Call emulateMediaType('screen') before page.pdf(). Without it, print media styles apply. Switching media type can alter layout, visibility, colors, and spacing because the page’s CSS may define separate screen and print rules.

Preserve print colors

Puppeteer notes that PDF colors are modified for printing by default. For elements whose colors must remain exact, add print CSS such as:

.report-chart {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

Also set printBackground: true when PDF backgrounds should be included. Color adjustment and background inclusion solve different parts of print rendering, so check both when colors or shaded sections are missing.

5. Make the report deterministic

  1. Set the viewport and device scale before navigation when producing screenshots with a known layout.
  2. Wait for the report’s actual readiness condition: a report root selector, required data marker, or a suitable navigation condition.
  3. Confirm images, charts, fonts, and asynchronous report data are ready before capture.
  4. Choose screen or print media intentionally for PDFs and keep the corresponding CSS rules in the report.
  5. Set paper size, margins, orientation, backgrounds, and page ranges explicitly if they matter to downstream readers.
  6. Close the browser in a finally block so errors do not leave browser processes running.

Very tall pages and large viewport captures can produce large images and consume more memory. Paginated output may be more suitable when the reader needs paper-like pages. These are practical format considerations, not a documented universal performance comparison.

6. Troubleshoot common output problems

Symptom Likely cause Fix
PDF layout differs from the browser PDF generation uses print CSS by default. Use page.emulateMediaType('screen') before PDF generation, or adjust the report’s print styles.
Backgrounds or chart colors are absent PDF backgrounds may be excluded, or print color adjustment changes colors. Set printBackground: true and use print-color-adjust: exact for the relevant print styles.
PDF content is unexpectedly scaled CSS page sizing and the selected paper format differ. Set the intended paper format and margins; use preferCSSPageSize: true when CSS @page should control sizing.
Screenshot misses content below the fold The capture is viewport-only. Use fullPage: true, or capture a specific element.
Element screenshot fails or is empty The selector did not match, or the element was not ready. Wait for the selector, check for a missing element, and ensure report content has rendered.
Text or charts look incomplete Fonts or asynchronous content had not finished loading. Wait for the relevant content; PDF font waiting defaults to true, but report data and chart rendering may need their own readiness condition.
Capture waits indefinitely The chosen navigation condition may not complete on pages with persistent network activity. Wait for a report-specific selector or another bounded readiness condition rather than requiring the network to become idle.

7. Cost and reliability considerations

With a self-hosted Puppeteer workflow, account for the browser runtime and the infrastructure that launches it; the cited Puppeteer documentation does not provide a per-capture price or comparative cost figures. Reuse browser processes thoughtfully in a service, isolate jobs as your operational needs require, and close pages and browsers when finished. Set timeouts around navigation and report readiness in production so one slow page does not stall a job queue.

For reliability, make captures reproducible: control viewport and output options, use explicit readiness checks, and keep screen and print styles intentional. Retain enough diagnostic context to identify the URL, chosen media type, and capture options when a job fails. No universal speed or file-size winner is established by the cited documentation.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF; the API supports PDF page settings as well as screenshot options. See the API documentation.

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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', image);

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up and start with 1,000 free screenshots per month.

9. FAQ

Can a PDF include only selected pages?

Yes. The PDF options include pageRanges; consult the version-matched Puppeteer reference for its accepted range syntax.

Should I use PNG or JPEG for a screenshot?

Choose based on the image output you need. Puppeteer’s screenshot quality option applies to JPEG, not PNG; the documentation does not claim one is always preferable.

Does an element screenshot capture the whole page?

No. It captures the selected element; use a full-page screenshot when the entire document is the desired image.

Will screenshot and PDF output have the same dimensions?

They represent different output models: screenshots use pixels and a capture area, while PDFs use pages and print settings. Choose settings for the intended consumer.

References