October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Chrome

How to Fix Puppeteer Font Cache Issues on Ubuntu

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

Most Puppeteer “font-cache” problems on Ubuntu are not caused by Puppeteer’s browser cache. Missing glyphs and unexpected fallback fonts usually mean that Fontconfig cannot see the required font files. Rebuild Fontconfig with fc-cache -f -v after confirming the fonts are installed. A missing Chrome executable, a sandbox error, a Docker library failure, or an unwritable cache directory requires a different fix.

This guide separates those failure stages, gives commands for desktop Ubuntu, CI, Docker, and read-only environments, and shows how to verify the result in the same Puppeteer job that produces your screenshots or PDFs.

First identify which “cache” is failing

Two unrelated caches are often confused:

Component What it stores Typical symptom Relevant action
Puppeteer browser cache Downloaded browser executables. Puppeteer’s configuration documentation says the default location is ~/.cache/puppeteer from version 19.0.0. Could not find Chrome, an install that did not download a browser, or a packaged app that cannot locate its executable. Install or configure the browser separately; do not delete it as a routine font repair.
Fontconfig cache Font metadata generated by scanning configured font directories. Missing glyphs, a substituted typeface, boxes instead of characters, or a screenshot/PDF that differs from the desktop. Install readable font files, then run fc-cache and test the actual render.

Launch failures are a third category. No usable sandbox!, missing shared libraries, and unwritable user-data or XDG directories happen before page rendering and are not evidence of stale font metadata.

Use the symptom to choose the path

Missing glyphs or fallback text

Check the target script first. Latin, Cyrillic, Arabic, Chinese, Japanese, Korean, emoji, and specialist symbols can require different font families and packages. A cache rebuild cannot create a font file that is not installed.

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.

“Could not find Chrome” or a missing executable

This points to browser installation, a changed cache location, or a packaging step that omitted ~/.cache/puppeteer. It does not identify a font problem.

No usable sandbox! or an early browser crash

On Ubuntu 23.10 and newer, Puppeteer documents an AppArmor interaction that can stop downloaded Chrome for Testing from using user namespaces. Docker images can also lack required shared libraries. Resolve those launch conditions before investigating rendered text. Do not add --no-sandbox as a font workaround; Puppeteer’s troubleshooting guidance strongly discourages running without the browser sandbox.

Step 1: confirm the font files exist and are readable

Inspect the directories Fontconfig knows about:

fc-list | head -n 20

To search for a family by name:

fc-match "Noto Sans CJK JP"
fc-match "DejaVu Sans"
fc-match "Noto Color Emoji"

fc-match reports the font Fontconfig would select for a request. If it returns an unexpected family, or no usable result, install a package that covers the script you need. Package names and availability vary by Ubuntu release, so select the package for that release and language rather than assuming one universal package. Puppeteer’s Linux and Docker guidance specifically notes that extra Chinese, Japanese, and Korean font files may be necessary.

For a per-user font, place the file in a user font directory, such as ~/.local/share/fonts, and ensure the account running Puppeteer can read it. For system-wide use, install it in an appropriate system font directory with administrator permissions. Avoid copying fonts into a directory that is not included in the runtime container or that the service account cannot access.

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

Step 2: rebuild Fontconfig’s metadata

Run the force-and-verbose form first:

fc-cache -f -v

Ubuntu’s Jammy manual describes fc-cache as scanning font directories and building font-information cache files for applications using Fontconfig. The -f option forces regeneration and -v prints status so you can see which directories were scanned.

If the normal rebuild does not remove stale entries, use the more disruptive erase-and-rescan operation:

fc-cache -r -v

Here -r erases existing cache files before rescanning. Use it when the diagnostic points to corrupted or obsolete metadata, not as a first response to every rendering difference. Check the command status:

fc-cache -f -v
status=$?
printf 'fc-cache exit status: %sn' "$status"
test "$status" -eq 0

After rebuilding, run fc-match again and then render through Puppeteer. Fontconfig results in an interactive shell are not sufficient if your service runs as another user, inside a container, or with a different HOME.

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

Step 3: verify the fix in Puppeteer

Use a small, repeatable Node.js script that requests the exact family and characters your production page uses:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.setContent(`
      <style>
        body { font-family: "Noto Sans", sans-serif; font-size: 32px; }
      </style>
      <div>Latin — العربية — 中文 — 日本語 — 한국어 — 😀</div>
    `, { waitUntil: 'networkidle0' });
    await page.screenshot({ path: 'font-check.png', fullPage: true });
    const selected = await page.evaluate(() => {
      const el = document.querySelector('div');
      return { requested: getComputedStyle(el).fontFamily, text: el.textContent };
    });
    console.log(selected);
  } finally {
    await browser.close();
  }
})();

Inspect the image or PDF, not just the CSS value: browsers can report the requested family while falling back for characters that family does not contain. Compare the same script under the same Unix account and container image used by your application.

Keep browser installation separate

Puppeteer normally downloads a compatible Chrome for Testing during installation. If a package manager or security policy blocked the postinstall script, install the browser explicitly:

npx puppeteer browsers install

Alternatively, allow the package’s postinstall step according to your package manager’s policy, then reinstall Puppeteer. If you intentionally manage Chrome yourself, configure Puppeteer to use that executable and document the path; changing the Fontconfig cache will not make an absent executable appear.

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

When packaging an application, remember that the browser cache under ~/.cache/puppeteer belongs to the user and environment that installed it. A build-stage download can be invisible to a different runtime user unless you copy it or configure a shared location with suitable permissions.

Ubuntu, CI, Docker, and read-only environments

Desktop Ubuntu

  • Install the required typeface packages for every script your pages contain.
  • Run fc-cache -f -v as the account that will run Puppeteer, or ensure system caches and font directories are readable by that account.
  • Close and recreate long-running browser processes after changing fonts; a process may retain font state from before the installation.

Continuous integration

  • Install fonts in the image or runner before the Puppeteer test starts.
  • Rebuild the cache during image creation and verify it at runtime with fc-match.
  • Pin the same Ubuntu, browser, and Puppeteer versions when comparing screenshots; rolling changes can alter fallback selection.

Docker

Puppeteer’s Linux troubleshooting documentation notes that Docker needs the browser’s shared libraries and suitable font coverage. A minimal image can therefore fail in two independent ways: the browser may not launch, or it may launch with missing glyphs. Install the libraries and fonts required by your chosen Ubuntu base image, run fc-cache -f -v after fonts are added, and test as the non-root runtime user.

Read-only containers

The browser may need writable XDG configuration/cache locations and a writable user-data directory. If the filesystem is read-only, provide writable mounted paths and set the relevant environment variables or Puppeteer launch options. A permission error in those paths is not repaired by erasing Fontconfig caches.

Troubleshooting by error and cause

What you see Likely cause What to do
Boxes, tofu, or missing characters The required glyph is absent from installed fonts, or Fontconfig metadata is stale. Install a font covering the script, confirm it with fc-match, run fc-cache -f -v, and rerun the Puppeteer render.
Unexpected fallback family The requested family lacks particular glyphs, is not readable, or is unavailable to the runtime user. Check family selection and file permissions; compare fc-match under the service account.
Could not find Chrome Puppeteer’s browser download was skipped, misplaced, or inaccessible. Run npx puppeteer browsers install, allow the postinstall script, or configure a managed executable.
No usable sandbox! Ubuntu AppArmor/user-namespace interaction or an incompatible launch environment. Follow Puppeteer’s Ubuntu sandbox guidance and correct the environment; do not treat it as a font-cache issue or casually disable the sandbox.
Browser starts locally but fails in Docker Missing shared libraries, permissions, or writable user-data/XDG paths. Install image dependencies, provide writable paths, and test with the same runtime user.
fc-cache reports permission errors The command cannot read a font directory or write its cache location. Fix ownership/permissions or run it in the intended user context; do not delete unrelated Puppeteer files.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost considerations

Font-cache rebuilding is normally an installation or image-build step, not something to run before every screenshot. Repeating it in a request handler adds filesystem work and can create race conditions when several workers update the same cache. Bake fonts and the rebuilt cache into a container image, or run a controlled initialization step before workers start.

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

For deterministic visual tests, keep the font files, Ubuntu release, Puppeteer version, and Chrome version stable. A cache hit in one environment does not guarantee identical rendering in another because fallback depends on the installed families and browser text shaping. Record the runtime user and the output of fc-match when diagnosing a regression.

Or skip the browser setup

If your goal is a reliable website screenshot or PDF rather than maintaining Chromium on Ubuntu, ScreenshotNeo provides an HTTP screenshot API and MCP server. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status.

One call is enough to try it (see the ScreenshotNeo documentation):

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

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)

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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
require('fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It supports full-page and element captures, lazy-image loading, device and viewport settings, dark mode, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameters used by other screenshot APIs are accepted to ease migration.

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

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start without a card.

Frequently Asked Questions

Should I delete ~/.cache/puppeteer to fix missing glyphs?

No. That directory stores downloaded browser binaries by default from Puppeteer 19.0.0; missing glyphs generally require font installation and a Fontconfig rebuild.

Will fc-cache -r -v install a missing font?

No. It erases and rescans metadata. Install a font package that contains the required script first.

Why does the CSS family look correct but characters still fall back?

A family can lack individual glyphs. Use fc-match and inspect the rendered output for the specific characters.

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

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.

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
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair 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.