If a Puppeteer PDF made in Docker shows blank squares, missing characters, or unexpected glyph shapes, first check whether the container has a font that covers the exact characters. A CSS font-family declaration names a preference; it does not install that font in the image. Identify the affected script and test the precise text before changing packages. Font fallback, print CSS, and font loading can also cause trouble, so work through them separately.
Diagnose the exact characters before changing Docker
Create a small HTML page containing the failing text, including punctuation, accents, and any mixed-script text that appears in the real document. Use the same HTML, Puppeteer version, and container image as the failing job. Compare a browser screenshot with the PDF produced in that container.
- Record the characters and script. For example, note whether the problem is Japanese, Chinese, Thai, Arabic, Hebrew, or a particular symbol. “Unicode” covers many scripts; no single font package guarantees every character.
- Inspect the CSS family. Check the element’s computed
font-family, including stylesheets loaded by the page. A family requested by CSS may not be installed in Linux. - Check the runtime image. Fonts installed on a developer’s host are not automatically available in the Docker container that launches Chrome.
- Compare screenshot and PDF. If both show missing glyphs, suspect font availability or coverage first. If the screenshot looks right but the PDF does not, check print media styles and font readiness.
Puppeteer’s Linux and Docker troubleshooting guide specifically notes that CJK rendering may require additional font files. It distinguishes browser system dependencies from font coverage: a missing shared library can prevent Chrome from launching, while missing glyph coverage can leave Chrome running but render placeholders or substitutions.
Install fonts for the affected script in the runtime image
Add suitable font packages to the Docker image that actually runs Puppeteer, then rebuild and rerun the minimal test. Choose packages for the base distribution and the glyphs you need; package names and contents differ between distributions.
#1 Best Overall
- BEST FOR SMALL BUSINESSES – Engineered for extraordinary productivity, the Brother DCP-L2640DW Monochrome (Black & White) 3-in-1 combines laser printer, scanner, copier in one compact footprint and delivers high-quality black & white prints
- FAST PRINTER WITH EFFICIENT SCANNING – Produces documents quickly with print speeds up to 36 ppm(2) and scan speeds up to 23.6/7.9 ipm(3) (black/color). A 50-page auto document feeder(4) allows for convenient, time saving multi-page scanning and copying
- FLEXIBLE CONNECTION OPTIONS – Easily navigate the changing demands of your business with secure multi-device connectivity via built-in dual-band wireless (2.4GHz / 5GHz) and Ethernet. Or connect locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Print, scan, and manage your wireless printer anytime, from almost anywhere from your mobile device. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(5)
- CHOOSE BROTHER GENUINE TONER – When it’s time to replace your toner, be sure to choose Brother Genuine TN830 or TN830XL replacement toner. And with Refresh EZ Print Subscription Service, you’ll never worry about running out of toner again and you’ll enjoy savings of up to 50%(6) on Brother Genuine Toner. Get started with Refresh today with a Free Trial(1)
Puppeteer’s maintained Dockerfile uses a Node Bookworm base and includes examples such as fonts-ipafont-gothic for Japanese, fonts-wqy-zenhei for Chinese, fonts-thai-tlwg for Thai, fonts-khmeros for Khmer, fonts-kacst for Arabic, and fonts-freefont-ttf. The troubleshooting guide also names charset-oriented packages. These are useful starting points, not a promise of full Unicode coverage or a package list to copy blindly.
For a Debian-based image, a Dockerfile pattern can look like this; replace the example packages with those available and appropriate for your chosen base image and script:
FROM node:bookworm-slim
ENV LANG=en_US.UTF-8
RUN apt-get update && apt-get install -y --no-install-recommends
fonts-ipafont-gothic
fonts-wqy-zenhei
fonts-thai-tlwg
fonts-khmeros
fonts-kacst
fonts-freefont-ttf
&& rm -rf /var/lib/apt/lists/*
This example reflects the kinds of packages in Puppeteer’s Dockerfile; it is not a minimal universal font set. Install only what your document needs when image size matters, and verify package availability for the precise distribution and release. A font package added to a build stage that is discarded will not help the final runtime image.
Rank #2
- BEST FOR HOMES & HOME OFFICES – Engineered for consistent, premium print quality, the Brother HL-L2405W Monochrome (Black & White) Laser Printer delivers sharp, crisp prints at an affordable price. Prints one-sided documents at speeds up to 30ppm(2)
- COMPACT, CONNECTED PRINTER – Flexible connection options make this an ideal printer for home use and at-home offices. Securely connect to multiple devices with built-in dual-band wireless (2.4GHz/5GHz) or locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Manage your printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Enjoy seamless, reliable everyday printing with the 250-sheet paper tray(4) and a manual feed slot that enables printing on envelopes and specialty pape
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
Locale is a separate setting. Puppeteer’s Dockerfile sets LANG=en_US.UTF-8, but that does not supply font files or ensure a font contains the affected glyphs. Likewise, install Chrome’s Linux dependencies as required by the image, but do not treat browser-launch dependencies as a substitute for script coverage. Puppeteer discusses --no-sandbox separately and strongly discourages disabling the sandbox; it does not fix missing fonts.
Recommended Free Tools
Check font fallback when characters render with the wrong appearance
A missing exact font does not always produce an empty square. Linux font matching may substitute another available face. If that fallback lacks the needed glyph, characters may disappear; if it contains them, their shape, weight, spacing, or alignment may differ from the intended design.
Confirm that the requested face exists in the runtime container and has coverage for the exact text. If it does not, install a suitable fallback and make the fallback explicit in CSS where appropriate, for example:
Rank #3
- FAST PRINT SPEEDS: Print up to 19 pages per minute.
- COMPACT DESIGN: Space-saving, compact design fits anywhere in your home, school or small office.
- WIRELESS CONNECTIVITY: Print from almost anywhere in your workspace using your compatible mobile device.
- PAPER CAPACITY: Up to 150 sheets.
- SUSTAINABILITY: Uses less than 2 watts in Energy Saver mode.
body {
font-family: "Your Installed Font", "Suitable Fallback", sans-serif;
}
Those family names must correspond to fonts actually available to Chromium in the image. Chromium’s Linux PDF font helper source provides implementation context for handing substitution to fontconfig when an exact font is unavailable. Substitution behavior can depend on the installed fonts and distribution, so validate the output in your own image.
Check web-font loading and print-specific CSS
page.pdf() uses print CSS media, so a stylesheet can select a different family for PDF output than for a normal screen capture. Inspect @media print rules and any @font-face declarations, and make sure remote font requests succeed from inside the container.
In Puppeteer 25.12.0, PDF generation waits for fonts by default. The PDFOptions documentation describes waitForFonts as waiting for document.fonts.ready; the Page.pdf() documentation describes the print-media behavior. Check the documentation for the version pinned in your project before relying on version-specific options.
Rank #4
- BEST FOR HOME OFFICES & SMALL TEAMS – Engineered for consistent, premium print quality, the Brother HL-L2460DW Monochrome (Black & White) Laser Printer produces documents that are clear, crisp, and easy to review and share, all at an affordable price
- COMPACT, CONNECTED, EXCEPTIONALLY EFFICIENT– Connect with built-in dual-band wireless (2.4GHz/5GHz), Ethernet, or to a single computer via USB interface. Prints at speeds up to 36ppm(2), plus automatic duplex printing saves time and reduces paper waste
- BROTHER MOBILE CONNECT APP – Manage your wireless printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Tackle high-volume black & white printing with the 250-sheet capacity paper tray.(4) The manual feed slot enables printing on envelopes and specialty paper
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
With a current version, a simple capture can be written as:
await page.goto("https://example.com", { waitUntil: "networkidle0" });
await page.pdf({ path: "output.pdf", format: "A4" });
Replace the URL with your page. Network-idle navigation is not proof that a remote font loaded successfully, and arbitrary extra sleeps should not be the first fix when the PDF API already waits for fonts by default. Check the font request, font coverage, and print styles first. If you use an explicit waitForFonts option, confirm its behavior against your installed Puppeteer version; the documentation notes that bringing a background page to the foreground may be needed for the wait to resolve.
Validate the rebuilt PDF and isolate viewer differences
- Rebuild the image after changing its font packages; do not test against an old container layer or a different runtime image.
- Run the same minimal HTML and capture again with the same pinned Puppeteer version.
- Inspect the resulting PDF in more than one viewer if glyphs differ between applications. A historical Puppeteer issue report describes one user seeing different font display across Windows systems. It is an anecdotal report, not evidence that every viewer discrepancy has the same cause.
- Keep the minimal test in your project if PDFs are generated in CI, so image or font changes can be checked against the affected text.
Troubleshooting by symptom
| Symptom | Likely area to check | Next step |
|---|---|---|
| Blank squares or missing characters in both screenshot and PDF | Font absent from runtime image, or installed font lacks the glyphs | Identify the script and exact characters; install a suitable font package in the final image and retest. |
| Characters appear, but look different from the intended design | Font matching substituted another face | Check that the requested family is installed and covers the text; provide a suitable fallback. |
| Screenshot is correct, PDF is not | Print media CSS or PDF-time font loading | Inspect print-specific family rules and web-font requests; verify the pinned Puppeteer PDF behavior. |
| Chrome fails to launch | Linux browser dependencies or image configuration | Follow Puppeteer’s Linux dependency guidance for the image. Treat this separately from glyph coverage. |
| PDF differs between viewers or operating systems | Viewer or platform font handling may differ | Compare the same artifact in multiple viewers and retain the exact reproduction sample; a single discrepancy does not identify a universal cause. |
| Adding a delay appears to change the result inconsistently | Font requests, asynchronous page state, or version-specific readiness behavior | Check whether font requests succeed and whether the intended font is selected under print media before adding timing workarounds. |
Or skip the browser setup
If the goal is simply to capture a web page rather than debug a Puppeteer PDF pipeline, ScreenshotNeo provides a screenshot API and MCP server for developers. One GET request returns an image or PDF, and its response identifies outcomes such as clean captures, bot checks, blank pages, timeouts, failed loads, and cache hits. Cookie banners, popups, and chat widgets are removed before capture; those cleanup steps can be turned off.
For a PDF from a URL, use the API’s PDF option as documented; for an image response, this runnable cURL example saves a WebP screenshot:
Best Value
- FROM AMERICA'S MOST TRUSTED PRINTER BRAND – Perfect for small teams printing professional-quality black & white documents and reports. Perfect for 1-3 people
- WORLD'S SMALLEST LASER IN ITS CLASS – Precision laser printing that fits anywhere
- FAST PRINT SPEEDS – Up to 21 black-and-white pages per minute single-sided
- WIRELESS WITH SELF-RESET – Helps you stay connected
- PRINT FROM ANY DEVICE – Wireless printing from any mobile device, PC or tablet. Works with Microsoft, Mac, AirPrint, Android, Chromebook and more
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for authentication and PDF parameters. Only clean shots are billed; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with the outcome reported in response headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up free for 1,000 screenshots a month—no card required.
Frequently Asked Questions
Does setting LANG=en_US.UTF-8 fix missing Unicode glyphs?
No. It sets the locale but does not install fonts or add glyph coverage.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsShould I add a longer delay before calling page.pdf()?
Not as the first step in Puppeteer 25.12.0, where font waiting is enabled by default. Verify that the font loads and print CSS selects it; check version-specific behavior if using an older release.
Is --no-sandbox a fix for missing characters?
No. It changes browser sandboxing, not font availability or glyph coverage, and Puppeteer strongly discourages running without a sandbox.
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.




