Free tools Windows power users keep installed
One-click scans. No signup required.
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.
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 problems#1 Best Overall
- 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:
puppeteerorpuppeteer-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.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →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
- 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.
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.
Rank #3
- 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.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →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
- 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.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteText 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.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.
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
- 【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.
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-coreor 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.
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.




