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

Install the fonts Chrome needs in the Docker image that runs Puppeteer. The right packages depend on your Linux distribution and the scripts you need to render; there is no universal package list. If you use Puppeteer’s official Docker image, it includes Chrome for Testing and Puppeteer, while a custom image means you must manage browser dependencies and font coverage yourself.

What “downloading fonts” means in a Puppeteer container

Puppeteer does not bundle every font a page might need. Chrome renders text using fonts available in the operating-system environment where the browser runs. If a font is absent, Chrome may substitute another installed font. That can change line breaks, element sizes, alignment, and the appearance of screenshots and PDFs.

The practical fix is to install the required font packages while building the Docker image, not to rely on fonts present on your development machine. The Puppeteer troubleshooting guide describes installing fonts in the image and gives charset-oriented examples, including IPA Gothic, WenQuanYi Zen Hei, Thai TLWG, KACST, and FreeFont. Those are examples, not a complete or universal package list; package names and availability depend on the image’s Linux distribution and repositories. Puppeteer’s troubleshooting guide does not establish one current package recipe for every base image.

Choose an image before choosing fonts

Use the official Puppeteer image

The official image includes Chrome for Testing, its required dependencies, and Puppeteer. It is the more direct route if you do not need to control the underlying operating system beyond your application and font requirements. Check the official Docker guide for the image and its usage instructions. The guide identifies version 25.12.0; the matching system-requirements page says Node 22.12+ for that documented version. Treat those as version-scoped documentation, not timeless requirements: check the documentation for the version you actually deploy.

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

Build on a custom base image

A custom image gives you more control over installed packages and deployment conventions, but you are responsible for supplying both Chrome’s operating-system dependencies and the fonts it needs. Puppeteer recommends treating its project Dockerfile as a starting point when building on another base image. A custom image is a good fit when your organization standardizes on a base distribution or needs a specific set of system packages; it also means more work to keep browser dependencies and font coverage aligned.

Install fonts during the image build

First identify the distribution and package manager used by the image you have selected. Then check that distribution’s current repositories for packages covering the characters your pages actually render. A package name that works in one distribution or image version may not exist under the same name elsewhere. The examples in Puppeteer’s troubleshooting guide are useful pointers for scripts such as Japanese, Chinese, Korean, Thai, Arabic, and broader Unicode coverage, but they are not a copy-and-paste list for every Docker base image. Check the guide alongside your base image’s package documentation.

Keep the installation in the Dockerfile so every built image has the same font environment. The pattern is:

  1. Choose the Puppeteer image or custom base image that matches your deployment.
  2. Use that image’s package manager to install the distribution’s packages for the required scripts.
  3. Build and run the image in the same environment used for the actual capture or PDF job.
  4. Test representative text from each script you need before promoting the image.

Puppeteer’s troubleshooting guide does not verify a current package command for every Linux distribution, so a single universal install command would be misleading. Do not paste package names from an example for a different base image without confirming that they exist in your selected image’s current repositories.

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

Match font coverage to the content

Start with the pages or documents your job must render, rather than installing an arbitrary large font collection. Latin-only content has different needs from mixed-script content; CJK pages in particular can show missing glyphs or substitute fonts if their coverage is absent. Puppeteer’s troubleshooting guidance specifically calls out additional font files for Chinese, Japanese, and Korean characters. Its examples also include IPA Gothic, WenQuanYi Zen Hei, Thai TLWG, KACST, and FreeFont. Use these as leads for identifying coverage, then verify the actual package names and available glyphs for your distribution.

For a multi-language service, create a small test fixture containing representative characters from every supported script, punctuation marks, and symbols your users rely on. Render that fixture in the container and inspect the result. A successful browser launch does not prove that every glyph has an appropriate font, and a missing character may be less obvious than a completely blank page: it can appear as a replacement box or as text in a visibly different typeface.

Check fonts before producing a PDF

Puppeteer’s PDF generation guide says Page.pdf() waits for fonts by default. The PDFOptions API specifies that waitForFonts defaults to true and waits for document.fonts.ready. This waits for fonts the page is loading; it does not install a missing operating-system font. If the necessary font is not available in the container, waiting cannot supply it.

Here is a small Node.js example for a project that already has Puppeteer installed and configured to launch its browser. It waits for page font loading, creates a PDF, and makes the output path explicit:

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 });
  try {
    const page = await browser.newPage();
    await page.setContent(`
      <!doctype html>
      <html>
        <meta charset="utf-8">
        <body>
          <p>Font check: English, 日本語, 中文, 한국어, ภาษาไทย</p>
        </body>
      </html>`,
      { waitUntil: 'load' }
    );
    await page.pdf({
      path: '/tmp/font-check.pdf',
      format: 'A4',
      waitForFonts: true
    });
    console.log('Wrote /tmp/font-check.pdf');
  } finally {
    await browser.close();
  }
})();

This checks whether the job completes and gives you a file to inspect; it is not an automated proof that every character used the intended font. Compare the PDF output with a known-good rendering, especially for scripts and symbols important to your application. If the page is in the background, the PDF API notes that it may be necessary to call page.bringToFront() before generating the PDF. See the PDFOptions API.

Keep the browser installation aligned with Puppeteer

Font problems can be confused with browser installation problems. The installation guide describes puppeteer as downloading a compatible Chrome by default. puppeteer-core is the option when you manage the browser separately or connect to a remote browser. Puppeteer configuration supports a cache directory, an executable path, and skipping browser downloads. Review the installation guide and the configuration API for the version in your project.

In a custom image, ensure the executable Puppeteer launches is the browser you intend to run, and that it has the libraries it needs. Installing fonts into one container will not affect a remote browser running elsewhere: install them where Chrome actually renders the page. Similarly, changing a local development machine does not change a built container image unless the image itself is rebuilt with the change.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make the container writable where Chrome needs it

Chrome writes profile, configuration, and cache files during startup. Puppeteer’s troubleshooting guide warns that a read-only container can therefore fail even when the browser and fonts are installed. If your deployment uses a read-only filesystem, provide writable locations for those files; the guide gives /tmp as an example when it is available. Confirm that the path is writable by the process running Chrome and that your deployment does not remove it before the job completes. See Puppeteer’s troubleshooting guidance.

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

Troubleshoot missing or incorrect fonts

  • Text appears in a fallback font or as missing-glyph boxes: the image may not include a font with the needed script coverage. Identify the distribution, check its package repositories, add the appropriate package during the image build, rebuild, and inspect a representative output.
  • The install command cannot find a package: package names vary by distribution and may change. Verify the base image and its current repositories rather than copying an example meant for a different system.
  • The PDF is created before page fonts finish loading: check that the call uses the documented waitForFonts behavior (default true) and that the page’s font-loading work can complete. Remember that waiting does not provide fonts absent from the image.
  • PDF creation fails in a read-only deployment: make Chrome’s required profile, configuration, and cache locations writable, using a path such as /tmp only if your container provides it.
  • The browser fails to launch after switching images: revisit the browser dependencies and the Puppeteer/browser pairing for the selected setup. A custom base image has to supply the relevant dependencies; the official image is the lower-maintenance starting point when its environment fits.
  • Local output differs from container output: test in the actual built image. The host’s fonts are not a substitute for fonts installed in the environment where the container’s Chrome runs.

Or skip the browser setup

If your goal is to receive a website screenshot or PDF rather than operate your own Puppeteer browser, ScreenshotNeo offers a screenshot API and MCP server. A single request can capture a URL without you installing Chrome or fonts in your own container. It is not a drop-in replacement for a Puppeteer application that needs custom browser code or a controlled local font environment.

Example cURL request:

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 the request options. Its clean-shot steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the page verdict and billing status in headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools 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 for 1,000 free screenshots a month, with no card required.

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.

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