Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
CentOS

How to Fix Puppeteer PDF Differences Between Windows and CentOS

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If the same Puppeteer job produces different PDFs on Windows and CentOS, first make the rendering inputs identical: pin the Puppeteer package and the actual Chromium build, use the same HTML, assets and data, set print media and every PDF option explicitly, install the document’s real fonts on CentOS, and wait for those fonts to finish loading. Only after those controls match should you investigate font hinting or other launch flags.

Why identical Puppeteer code can produce different PDFs

A PDF is the result of several layers, not just your JavaScript. The operating-system font files and text libraries, Chromium build, Puppeteer version, launch arguments, CSS media mode, page data and network-loaded assets can all change the output. A different font fallback changes glyph widths; changed widths alter line wrapping, element heights and page breaks. Browser updates can also change layout or print behavior.

Therefore, “same HTML” is not enough to establish identical rendering. Treat Windows and CentOS as two separate rendering environments and record the complete environment for every comparison.

  • Operating-system release, architecture and locale.
  • Puppeteer package version and the executable path.
  • Actual Chromium version, including whether the browser is bundled or system-installed.
  • Launch arguments, sandbox configuration and headless/headful mode.
  • HTML, CSS, JavaScript, data and every loaded asset.
  • Viewport, device scale factor, timezone and any emulated settings.

1. Pin and verify the browser runtime

Pin Puppeteer in your lockfile, but also log the browser that actually runs. A package version does not by itself prove that both machines use the same Chromium executable.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: true,
    // Keep the sandbox enabled unless your deployment has a documented reason not to.
    args: []
  });
  const version = await browser.version();
  console.log({ puppeteer: require('puppeteer/package.json').version, browser: version });
  await browser.close();
})();

Run this diagnostic on both systems and save the output with the generated PDF. Also record the path to the executable if you set executablePath. If one host uses a system Chrome and the other uses Puppeteer’s downloaded browser, align those choices before changing CSS.

2. Make page inputs identical

Use byte-identical HTML, stylesheets, data and assets. A remote image, API response, feature flag or current timestamp can create a genuine content difference that looks like a rendering bug. Archive the HTML sent to each browser and check the network responses when a mismatch appears.

Set the viewport and other environment assumptions explicitly:

await page.setViewport({
  width: 1280,
  height: 900,
  deviceScaleFactor: 1
});
await page.emulateTimezone('UTC');
await page.setContent(html, { waitUntil: 'networkidle0' });

If you use page.goto(), choose the same URL, navigation timeout and waitUntil condition on both hosts. “Network idle” is not a guarantee that a web font succeeded; inspect font readiness separately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Choose print or screen CSS deliberately

Page.pdf() renders with the print CSS media type by default. Rules inside @media print, hidden navigation, changed colors and print-specific layout can therefore make the PDF differ from what you see in a browser window. If the intended design is the screen version, switch media before generating:

await page.emulateMediaType('screen');
const pdf = await page.pdf({ path: 'screen-style.pdf' });

If the intended design is print, leave the default in place but make that choice part of the test contract. Do not compare a Windows screen capture with a CentOS print PDF.

4. Set every PDF layout option

Defaults are a frequent source of “almost the same” output. Set paper, dimensions, orientation, margins, scale, backgrounds and CSS page-size handling explicitly in both runs.

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

The documented default paper format is Letter. preferCSSPageSize defaults to false, which can scale content to fit the selected paper, and printBackground defaults to false. Relying on those defaults can change page breaks, background colors and apparent dimensions. If you use CSS @page, decide whether it should control the physical page and set preferCSSPageSize accordingly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For exact colors in print output, CSS can request color preservation:

html {
  -webkit-print-color-adjust: exact;
}

This addresses print color adjustment; it does not make fonts or geometry identical across operating systems.

5. Audit fonts on CentOS

Font substitution is the most common explanation for text that is wider, wraps differently or has different glyph shapes. Compare the actual CSS font stack, family names, weights and styles with the files installed on CentOS. Check non-Latin pages for missing glyph coverage as well as Latin metrics.

Puppeteer’s CentOS troubleshooting guidance lists packages such as ipa-gothic-fonts, X font packages and Pango libraries among browser dependencies. Package names and availability vary by CentOS release, so treat that list as a starting point, not proof that your document’s fonts are present.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Inspect the computed font-family, font-weight and font-style for the elements that differ.
  • Verify that each required family and weight exists in the running CentOS image, including fonts used by web pages and embedded documents.
  • Check that font files are readable by the account launching Chromium and that the font cache is current after installation.
  • For web fonts, verify the request succeeded and that the response is not blocked by CORS, an offline build or an incorrect URL.
  • Compare a diagnostic page containing representative characters, numbers, punctuation and the scripts your production document uses.

When Chromium fails to start, inspect unresolved shared libraries with the troubleshooting command:

ldd /path/to/chrome | grep not

An unresolved library is a launch/dependency problem. A successful launch still does not prove that the required font family is available.

6. Wait for fonts before creating the PDF

Current Puppeteer documentation defines waitForFonts as waiting for document.fonts.ready, and its default is true. Keep it enabled unless you have a specific, measured reason not to. Make web-font loading visible in your own diagnostic code:

await page.evaluate(async () => {
  await document.fonts.ready;
  const required = ['16px "Inter"', '700 16px "Inter"'];
  for (const face of required) {
    if (!document.fonts.check(face)) {
      throw new Error(`Font is not available: ${face}`);
    }
  }
});

await page.pdf({
  path: 'report.pdf',
  format: 'A4',
  waitForFonts: true
});

If the page is running in a background tab, font readiness may not resolve as expected; bring the page to the foreground in that controlled test or generate from a normally active page. A successful document.fonts.ready promise means loading has settled, not that every requested family was found, so use document.fonts.check() and browser logs as well.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

7. Compare the output on defined axes

Do not judge two PDFs only by opening them side by side. Compare one category at a time and change one variable per run.

Axis What to inspect Typical cause
Font selection Family, weight, style and glyph coverage Missing CentOS font, fallback or failed web-font request
Text metrics Character widths, line wrapping and baseline position Different font files, Chromium build or shaping libraries
Geometry Element coordinates, heights and page breaks Text reflow, viewport mismatch or CSS media rules
Page setup Paper, margins, scale, orientation and CSS page size Implicit PDF defaults or different options
Color and backgrounds Background fills, images and print colors printBackground or print color adjustment

Save the input HTML, a JSON record of options and runtime versions, and the resulting PDF for each run. This turns a visual complaint into a reproducible case.

8. Try font hinting only as a controlled experiment

A Puppeteer issue about differing font widths across Windows and Linux includes a contributor suggestion to launch Chromium with --font-render-hinting=medium. That comment concerns a particular report and is not a current API guarantee or a cross-version fix. Test it only after versions, fonts, media and PDF options match:

const browser = await puppeteer.launch({
  headless: true,
  args: ['--font-render-hinting=medium']
});

Generate paired PDFs with and without the flag on the exact Chromium and OS versions you deploy. Keep the flag only if your own acceptance tests show a repeatable improvement. It cannot compensate for a missing font or different page content.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common failures and fixes

Fonts are wider on CentOS

Confirm the computed family and weight, install the exact font files, refresh the font cache and verify web-font responses. Then wait for document.fonts.ready. Do not begin with hinting flags.

Line breaks and page counts differ

Compare paper format, margins, scale, viewport, preferCSSPageSize and print media. A one-pixel metric change can legitimately move a heading or table row to the next page.

Colors or backgrounds are missing

Set printBackground: true and use -webkit-print-color-adjust: exact where exact print colors are required. Check that the asset itself loaded.

Chromium fails to launch on CentOS

Install dependencies appropriate to the CentOS release, inspect ldd /path/to/chrome | grep not, and review sandbox permissions. Running without a sandbox is strongly discouraged and is a security workaround, not a PDF consistency fix.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fonts never become ready

Check the page’s font requests, CORS policy, file permissions and background-page behavior. Bring the page forward for the diagnostic run and fail fast when document.fonts.check() reports a required face as unavailable.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you need a rendered image or PDF without maintaining a Windows/CentOS browser pair. Its cleanup step accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup action can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response reports the page verdict and billing status in headers.

For a one-call image, see the API documentation and use:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in Python:

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)

And in Node.js:

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 also supports PDF capture, full-page and selector captures, device and retina settings, custom CSS and JavaScript, waits, request blocking, headers, cookies, authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous webhooks and bulk capture of up to 100 URLs per call. Its MCP tools—take_screenshot, get_page_info and capture_pdf—let Claude, Cursor and other MCP clients operate the capture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan. Create a free ScreenshotNeo account to try it.

FAQ

Does matching Puppeteer versions guarantee identical PDFs?

No. The actual Chromium build, operating system libraries, fonts, assets and PDF options must also match.

Should I disable waitForFonts to speed up jobs?

Usually no. It is true by default because font readiness affects layout. Measure a documented exception rather than trading deterministic output for a small timing change.

Is --font-render-hinting=medium a supported universal fix?

No. It is an issue-level suggestion for one reported case. Treat it as an experiment on your exact deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does matching Puppeteer versions guarantee identical PDFs?

No. The actual Chromium build, operating system libraries, fonts, assets and PDF options must also match.

Should I disable waitForFonts to speed up jobs?

Usually no. It is true by default because font readiness affects layout. Measure a documented exception rather than trading deterministic output for a small timing change.

Is –font-render-hinting=medium a supported universal fix?

No. It is an issue-level suggestion for one reported case. Treat it as an experiment on your exact deployment.

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.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.