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 DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
browser automation

How to Fix Incorrect Fonts in Puppeteer Screenshots

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.

Incorrect fonts in a Puppeteer screenshot usually have one of two causes: Chrome cannot find the required font files in its runtime, or the page is captured before its web fonts finish loading. Fix the environment first, then add a bounded, application-specific font-readiness check before calling page.screenshot(). A successful document.fonts.ready promise does not prove that the preferred family is installed or that every character has a matching glyph.

What “incorrect fonts” means in Puppeteer

Font failures are often described as “Puppeteer doesn’t render default fonts,” but the screenshot symptom can come from several different states:

  • Chrome substitutes a fallback family because the requested family is absent from the machine or container.
  • The family exists, but the requested weight or italic style does not, so Chrome synthesizes or substitutes it.
  • A web font is declared in CSS but has not finished downloading when the screenshot is taken.
  • The font contains only some of the required glyphs. Latin text may look correct while Chinese, Japanese, Korean, emoji, symbols or another script falls back to a different face.
  • The screenshot is being compared across different operating systems, browser builds, viewport sizes or device scale factors, changing text metrics even when the CSS is identical.

These are different problems. Waiting longer cannot install a missing family, and installing a font cannot help if the page is captured before its font request completes.

Step 1: identify the exact runtime that renders the page

Before changing CSS, record the environment that actually launches Chrome. A local development shell may have fonts that are absent from a CI runner, Docker image, serverless function or remote browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
  • Operating system and distribution, including the container image tag.
  • CPU architecture.
  • Puppeteer package: puppeteer or puppeteer-core.
  • Browser executable path, channel and version.
  • Viewport, device scale factor and any emulation settings.
  • The exact font families, weights, styles and scripts required by the page.

puppeteer versus puppeteer-core

The puppeteer package downloads a compatible Chrome for Testing browser by default. Its downloaded browser runs with the fonts available in the host or image where your script executes. puppeteer-core does not download Chrome; it is intended for projects that manage the browser themselves or connect to a remote browser. In that setup, inspect the remote browser’s operating system and font installation, not just the machine running your Node.js process.

Log the browser version during diagnosis so two runs can be reproduced:

const browser = await puppeteer.launch({ headless: true });
console.log(await browser.version());

Keep the browser version, image digest, viewport and device scale factor fixed while comparing screenshots. Otherwise, a line wrap or different glyph metric can be mistaken for a font-loading bug.

Step 2: verify that the required font files exist

In Linux and Docker, Chrome can use only font files present in the runtime environment. Install the families and weights needed for the page through the target distribution’s current package manager, then rebuild the image. Package names differ between distributions and release versions, so check the repositories for the image you actually deploy rather than copying a package name from an unrelated operating system.

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

Check family, weight, style and glyph coverage

“The font is installed” is not a sufficient check. Confirm each combination your CSS requests: regular, medium, semibold, bold, italic and any variable-font range. Check the scripts and symbols in the screenshot as well. A family that covers Latin may not cover CJK characters, and a fallback glyph can change line height and wrapping.

For a controlled deployment, bake fonts into a pinned image instead of installing them during every startup. This makes builds reproducible and lets you review font-package updates alongside browser updates. Installing at deployment time can reduce image maintenance, but it introduces a moving dependency and may produce different screenshots after a base-image refresh.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
Font-supply approach Reproducibility Coverage control Maintenance trade-off
Fonts baked into a pinned image High when the image and packages are pinned Explicitly choose families, weights and scripts Rebuild the image when font packages need security or quality updates
Install during deployment Depends on repository state at deploy time Can vary if package dependencies change Less image preparation, more startup and drift risk
Separately managed or remote browser Depends on the browser provider’s image contract Must be verified on the browser host Centralized browser updates, but less local control

For Chinese, Japanese or Korean output, additional font files may be required. Puppeteer’s troubleshooting guidance gives a Heroku example using the puppeteer-heroku-buildpack; treat that as an example of supplying language fonts, not as a universal package choice for every platform.

Step 3: make the page wait for fonts and visual content

After navigation, injecting HTML, or inserting content dynamically, wait for the condition that makes your application visually ready. A navigation event alone says that a document reached a browser lifecycle state; it does not guarantee that custom fonts, late-rendered components or images have finished.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'capture.png', fullPage: true });

document.fonts.ready waits for the page’s font-loading set to settle from the page’s perspective. It does not verify that the preferred family exists on the host, that the CSS requested the intended family, or that every glyph is covered. Use it after the page has inserted the content whose fonts matter.

A complete, bounded Puppeteer example

const puppeteer = require('puppeteer');

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

    await page.goto('https://example.com', {
      waitUntil: 'domcontentloaded',
      timeout: 30000
    });

    // Wait for the component that determines the screenshot's layout.
    await page.waitForSelector('[data-page-ready]', { timeout: 15000 });

    // Wait for web-font loading after dynamic content is present.
    await page.evaluate(async () => {
      await document.fonts.ready;
    });

    // Optional diagnostic: inspect the families the browser reports for a sample.
    const fontState = await page.evaluate(() => ({
      status: document.fonts.status,
      bodyFamily: getComputedStyle(document.body).fontFamily,
      sampleLoaded: document.fonts.check('400 16px "Your Font Family"')
    }));
    console.log(fontState);

    await page.screenshot({
      path: 'capture.png',
      fullPage: true,
      type: 'png'
    });
  } finally {
    await browser.close();
  }
})();

Replace [data-page-ready] and the sample family with conditions from your application. If no reliable selector exists, wait for a specific state exposed by the page rather than adding an arbitrary multi-second sleep. Always set a timeout so a failed request cannot hold a worker indefinitely.

When injecting HTML or CSS

If you use page.setContent(), add styles and markup first, then wait for document.fonts.ready. If you inject a new stylesheet or append elements later, perform the font wait after that operation. For a font loaded with the Font Loading API, you can also explicitly load the face:

await page.evaluate(async () => {
  await document.fonts.load('600 20px "Your Font Family"');
  await document.fonts.ready;
});

This confirms that the browser attempted to load the requested face; it still cannot create a font file that is missing from the runtime or a glyph absent from that file.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Use a deterministic capture configuration

Once fonts are present and ready, remove unrelated sources of visual drift:

  • Pin the Chrome version and the operating-system or container image.
  • Use the same viewport width, height and device scale factor for every comparison.
  • Keep timezone, locale, color scheme and reduced-motion settings consistent when they affect layout or font selection.
  • Capture after application-specific content is present; lazy components can change line breaks after the first paint.
  • Use a full-page screenshot only when the page has reached its final vertical layout. A viewport screenshot can hide lower-page font failures.

Different text metrics between macOS, Windows and Linux are not automatically evidence of a Puppeteer defect. Compare like with like before altering the stylesheet.

Troubleshooting common symptoms

The whole page uses a generic fallback

Likely cause: the requested family is absent from the Chrome host, or the CSS family name does not match the installed face. Fix: inspect the runtime image, install the exact family and required weights, rebuild, and verify the computed font-family in the page. If the browser is remote, perform the check on that remote host.

Only bold or italic text looks wrong

Likely cause: that weight or style was not supplied, so Chrome synthesizes it or falls back. Fix: add the missing font file or adjust the CSS to a weight that actually exists. Check each @font-face declaration for its font-weight and font-style range.

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

Fonts are correct locally but wrong in Docker or CI

Likely cause: the local operating system has fonts that the image does not. Fix: add the required font packages to the image, rebuild it, and run the same diagnostic script inside the image. Do not assume a host-mounted font directory exists in production.

The first screenshot is wrong; a second screenshot is correct

Likely cause: the first capture raced the font request or late content. Fix: wait for the relevant selector or application state, then await document.fonts.ready immediately before capture. Keep the wait bounded.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

Latin text is correct but CJK or symbols are not

Likely cause: incomplete glyph coverage, not necessarily a missing primary family. Fix: install a font set covering the scripts in the output and test representative characters. Treat fallback glyphs as an expected coverage problem until proven otherwise.

The script hangs while waiting

Likely cause: a font request, selector or page dependency never resolves. Fix: add explicit timeouts, log the URL and readiness condition that failed, and capture the page state for diagnosis. Do not replace every wait with an unlimited promise or a universal fixed delay.

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

Text wraps differently after a browser update

Likely cause: changed font metrics, browser shaping or fallback behavior. Fix: compare the old and new browser versions in the same pinned image, then update visual baselines deliberately. Record the browser and environment with each baseline.

Performance, reliability and cost considerations

Font installation increases image size and may add build time, but it avoids repeated runtime setup and makes workers behave consistently. Waiting for a selector plus document.fonts.ready is generally cheaper than a long fixed sleep because it can finish as soon as the page is genuinely ready. Set navigation, selector and overall job timeouts so a broken font host does not consume a worker forever.

For high-volume jobs, keep browser processes warm only when your workload and isolation model permit it; otherwise, a fresh browser per capture gives stronger consistency at the cost of startup time. Cache immutable pages or rendered assets where your application allows it, but do not cache a screenshot produced before fonts are ready. Record whether a failure was a timeout, missing font, failed page load or an application readiness failure so retries target the real cause.

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

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you do not want to maintain a Puppeteer runtime. It accepts the cookie or consent banner like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and lets each cleanup step be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, with the result identifying the page verdict and billing status in X-Page-Verdict and X-Billed headers.

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

One GET request returns PNG, JPEG, WebP or PDF output. The API supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, clicks before capture, hidden selectors, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Parameter names used by other screenshot APIs also work to make migration easier.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

For AI workflows, its MCP server exposes take_screenshot, get_page_info and capture_pdf tools to Claude, Cursor and other MCP clients. Every plan includes every feature. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Yearly billing provides two months free.

cURL

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}`);

See the ScreenshotNeo API documentation for authentication, output and option names. If you need browser-level control, keep the Puppeteer method above; if you mainly need dependable page images or PDFs without packaging Chrome and fonts, the API removes that maintenance boundary.

Create a free ScreenshotNeo account to get 1,000 screenshots each month with no card.

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

Decision checklist

  • Need pixel control inside your own application? Pin the browser and image, install the required fonts, wait for your app’s visual-ready condition, then await document.fonts.ready.
  • Using puppeteer-core or a remote browser? Inspect the browser host’s fonts and version, not only your application server.
  • Supporting multiple writing systems? Test representative glyphs and provide coverage for every script and symbol in the screenshot.
  • Comparing screenshots? Keep OS, architecture, browser, viewport and device scale factor constant.
  • Want to avoid browser and font packaging? Use ScreenshotNeo’s API or MCP server and monitor its verdict and billing headers.

Frequently Asked Questions

Does document.fonts.ready install a missing font?

No. It waits for the page’s font-loading set to settle. The required family, weights and glyphs must already be available to Chrome.

Why does puppeteer-core show different fonts from puppeteer?

They may be launching different browsers or hosts. puppeteer downloads a compatible Chrome for Testing browser by default, while puppeteer-core relies on the browser you manage or connect to.

Should I solve a font mismatch with a longer sleep?

Use a selector or application state plus a bounded font wait instead. A fixed sleep can be either unnecessarily slow or still too short when a request fails.

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.

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.