The reliable fix is evidence-led: verify that the Google Fonts stylesheet and the subsequent font-file request both succeed inside the same browser and container that creates the PDF, confirm that the family and weights match your CSS, then wait for document.fonts.ready before calling page.pdf(). Also inspect print CSS, because Puppeteer generates PDFs with the print media type. A fallback font can keep text readable while hiding a failed Google Font request.
Start by proving what failed
Do not begin with a longer timeout or an arbitrary sleep. A PDF that looks different from the browser may be caused by a blocked request, an incorrect family name, a missing weight, a print-only rule, or a page that was never given time to finish loading.
- Record your Puppeteer version, bundled or system browser version, operating system, container image, and where the job runs.
- Open the target page with the same browser executable and network policy used by the PDF job.
- Save a copy of the generated PDF and compare it with a screenshot or normal browser view.
- Log failed requests, page errors, console errors, and the font state immediately before PDF generation.
The important distinction is that Google Fonts normally involves two network stages: a stylesheet response from the Google Fonts API, followed by one or more font-file responses selected for the requesting browser. A successful stylesheet request does not prove that a font file was downloaded.
Instrument both Google Fonts requests
Add request and response logging before navigation. The example below records failures without assuming that every request containing “font” is a Google request; this is useful when a site uses a CDN, a self-hosted fallback, or a CSS proxy.
#1 Best Overall
- INNOVATIVE CARTRIDGE-FREE PRINTING — No more dealing with lots of tiny ink cartridges; With this wireless document and photo printer each ink bottle set is equivalent to about 90 individual cartridges²
- LESS FREQUENT INK REPLACEMENT — Replacement ink bottles don't have to be changed nearly as often as ink cartridges¹; When you choose this combination printer, scanner and copier you can print up to 4,500 pages black/7,500 color³
- COLOR PRINTING — Up to 2 years of ink in the box4 (and with every replacement ink set) for fewer out-of-ink frustrations
- ZERO CARTRIDGE WASTE — By using an Epson EcoTank printer you can help reduce the amount of cartridge waste ending up in landfills
- HOME PRINTER DESIGNED FOR RELIABILITY — The Epson EcoTank ET-2800 All-in-One Supertank Color Printer creates vivid, detailed prints and documents thanks to Micro Piezo Heat-Free Technology; Fire off 10 ISO pages per minute1 to easily finish large jobs
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
page.on('requestfailed', request => {
console.error('REQUEST FAILED', request.url(), request.failure());
});
page.on('response', response => {
const url = response.url();
const type = response.request().resourceType();
if (type === 'stylesheet' || type === 'font' || /fonts.(googleapis|gstatic).com/i.test(url)) {
console.log('FONT RESPONSE', response.status(), type, url);
}
});
page.on('pageerror', error => console.error('PAGE ERROR', error));
page.on('console', message => console.log('BROWSER', message.type(), message.text()));
await page.goto('https://example.com', {waitUntil: 'networkidle2', timeout: 90000});
const state = await page.evaluate(() => ({
status: document.fonts.status,
faces: [...document.fonts].map(face => ({
family: face.family,
style: face.style,
weight: face.weight,
status: face.status
}))
}));
console.log(JSON.stringify(state, null, 2));
await browser.close();
})();
Look for an HTTP error, a failed request, a request that never appears, or a face whose status remains unloaded or error. A browser can display text using the generic fallback in your font stack even when the requested face failed, so visual legibility alone is not a success check.
Use a complete PDF sequence
Navigation idleness and font readiness solve different problems. networkidle2 waits for a period with few network connections; Puppeteer’s PDF API separately waits for fonts by default through its waitForFonts option, which waits for document.fonts.ready. Make both conditions explicit and inspect the faces you require.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage({
viewport: {width: 1440, height: 1000, deviceScaleFactor: 1}
});
page.on('requestfailed', request => {
console.error('Failed:', request.url(), request.failure()?.errorText);
});
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 90000
});
// Puppeteer documents this as useful when the page is in the background.
await page.bringToFront();
await page.evaluate(() => document.fonts.ready);
const required = await page.evaluate(() => {
const wanted = ['"Open Sans" 400', '"Open Sans" 700'];
return wanted.map(description => ({
description,
loaded: document.fonts.check(description)
}));
});
console.log(required);
if (required.some(item => !item.loaded)) {
throw new Error('Required font face is not loaded');
}
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
waitForFonts: true
});
await browser.close();
})();
Replace the family and weights in document.fonts.check() with the faces your page actually uses. If your Puppeteer version exposes waitForFonts, leave it enabled. If the page remains backgrounded in your environment, page.bringToFront() before the readiness check follows the documented guidance.
Check family names, styles, and weights
Google Fonts CSS is applied by the family name and weight requested in your stylesheet. These declarations must agree:
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap">
<style>
body { font-family: "Open Sans", Arial, sans-serif; font-weight: 400; }
h1 { font-family: "Open Sans", Arial, sans-serif; font-weight: 700; }
</style>
- Check spelling, capitalization, and quoting of the family name.
- Make sure every weight used by CSS is present in the Google Fonts URL. Requesting 700 while loading only 400 can produce synthetic bolding or fallback.
- Check italic usage separately; a normal face does not automatically provide a true italic face.
- Inspect the computed style of the affected element with
getComputedStyle(element).fontFamilyandfontWeight. - Keep a generic fallback such as
Arialorsans-seriffor graceful failure, but use request logs anddocument.fonts.check()to determine whether the intended face loaded.
Account for print media CSS
page.pdf() renders with the print media type. A rule inside @media print can replace your screen font family, weight, color, or visibility. Search your stylesheets for declarations such as:
Rank #2
- CARTRIDGE-FREE PRINTING — Print lab-quality photos, graphics and creative projects; Get vibrant colors and sharp text with Epson's high-accuracy printhead and Claria ET Premium 6-color inks
- INK BOTTLES — Save on photos1 and creative projects with affordable in-house printing; All-in-one printer allows you to print 4" x 6" photos for about 4 cents each vs. 40 cents with traditional ink cartridges1
- LESS FREQUENT INK REPLACEMENT — Replacement ink bottles don't have to be changed nearly as often as ink cartridges¹; Printer, scanner and copier lets you print up to 6,200 color pages³
- PRINT FOR LONGER — Up to 2 years of ink in the box² (and with every replacement ink set) for fewer out-of-ink frustrations with this wireless printer
- ZERO CARTRIDGE WASTE — Epson EcoTank printer helps reduce the amount of cartridge waste ending up in landfills; Cartridge-free printer uses high-yield ink bottles; Each replacement ink bottle set is equivalent to about 100 individual ink cartridges⁴
@media print {
body { font-family: Georgia, serif; }
.report-title { font-weight: 400; }
}
Compare the computed styles while using print media. As a diagnostic, you can temporarily run await page.emulateMediaType('screen') and generate a comparison PDF. If the screen version uses the expected face but the normal PDF does not, the difference is in print-specific CSS or print rendering—not necessarily in Google Fonts networking. Use screen emulation only when that is the design you intentionally want to print; otherwise fix the print stylesheet.
Bound every custom wait
A custom readiness check is useful when you need a named family or weight, but it must have a deadline and a useful error. Do not let a failed font request leave a worker hanging indefinitely.
async function waitForFont(page, description, timeoutMs = 15000) {
await page.waitForFunction(
desc => document.fonts.check(desc),
{timeout: timeoutMs},
description
);
}
Call it with a CSS font description such as '700 16px "Open Sans"'. If it times out, include the description and the logged font URLs in the job error. This turns an unexplained visual difference into an actionable failure.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
When outbound Google Fonts access is unreliable
Some build runners and production containers restrict outbound requests, require a proxy, or have DNS and TLS differences from a developer laptop. If the stylesheet or font-file request cannot reach Google from the rendering environment, self-hosting can remove that external dependency.
- Obtain a font file and confirm that your license permits serving it.
- Store the file where the PDF worker can reach it, preferably on the same origin or an allowed asset host.
- Declare it with
@font-face, using the correct family, weight, style, and URL. - Verify the asset response, MIME type, and path from inside the browser container.
- Run
document.fonts.check()and inspect the resulting PDF before switching production traffic.
@font-face {
font-family: "Report Sans";
src: url("/fonts/report-sans-regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
body { font-family: "Report Sans", sans-serif; }
Self-hosting adds update and licensing responsibility; it is an option when the rendering network cannot reliably reach Google, not a guarantee that every PDF font problem disappears.
Rank #3
- SET IT UP ONCE AND PRINT WITH CONFIDENCE. No complicated maintenance. Just easy, reliable printing you can count on.
- INK FOR YEARS. NOT MONTHS. Up to 2 years of ink included. Get thousands of pages of cartridge-free printing. More pages, less hassle
- KEEPS PRINTING WELL AFTER COMPETITORS HAVE QUIT. No complex maintenance. Sharper text, richer colors.[2] Only with HP Smart Tank
- PREMIUM SUPPORT - Strong technical expertise to solve issues faster
- THE LAST PRINTER YOU'LL EVER NEED. Enjoy years of refillable, cartridge-free printing.
Troubleshooting by symptom
The Google stylesheet returns an error
Check DNS, proxy settings, firewall rules, TLS certificates, container egress policy, and any request interception code. Test the URL from the same runtime, not from your desktop. If your application blocks third-party stylesheets, allow the stylesheet or replace it with a licensed self-hosted asset.
The stylesheet succeeds but the font file fails
Inspect the later fonts.gstatic.com (or equivalent) response. Check its status, redirects, certificate chain, content type, and whether an ad blocker or request filter removed font resources. A successful CSS response is not enough.
Free tools Windows power users keep installed
One-click scans. No signup required.
The face is loaded but the PDF still looks wrong
Check the element’s computed family, weight, and style, then inspect @media print rules. Confirm that the requested weight exists and that another more-specific selector is not overriding it.
The page works interactively but fails in headless mode
Compare browser and container versions, user agent, proxy credentials, viewport, and request headers. Google’s font stylesheet is tailored to the requesting user agent, so a different browser context can receive different CSS and font formats.
Waiting for document.fonts.ready changes nothing
Read the individual face statuses and request logs. Readiness only tells you what the document font set has settled on; it cannot download a blocked resource or correct a family-name mismatch. Bring the page to the front before the check, and use a bounded named-face wait when needed.
Rank #4
- Wireless Bluetooth Printer: Portable thermal printer compatible with iPhone, Android phones, iPad and tablet computers via Bluetooth. For smartphones, please download the "Nada Print" App. You can also connect to laptops and computers for printing using a USB-C cable. (Note: Laptops and computers can only be connected via USB and require the installation of a driver first. Bluetooth connection is not supported.)
- No-ink printing: Only supports US Letter and A4 size thermal paper.(Doesn't support regular paper) The no-ink portable thermal printer uses direct thermal technology, requiring no ink, toner or ribbons, making it environmentally friendly, cost-effective and time-saving. The thermal printer package comes with a roll of US Letter thermal printing paper. Note: When installing the paper, remember to switch the paper size switch on APP
- Clear Print: NDYIN N80 portable thermal printer adopts high-definition printing technology, with a 203DPI resolution to provide you with clear printing results. This mobile printer is compatible with roll paper, folded paper and tattoo transfer paper, supporting printing from your mobile phone PDF, Word, pictures and web pages anytime and anywhere. It is recommended to use our NDYIN thermal paper to achieve good printing quality
- Portable wireless printer for travel: The thermal printer is equipped with a built-in 1500mAh rechargeable battery, which can print 160 sheets of 8.5" x 11" thermal paper after being fully charged. It weighs only 1.5 pounds and is compact in size. This ink-free portable printer can be easily carried in a backpack or briefcase! It is perfect for business travel, cars, small offices, construction sites, schools and homes. You can print documents, contracts, invoices and boarding passes anytime and anywhere
- The N80 thermal printer has a wide range of uses. The package includes the N80 printer, a roll of US Letter paper(7m/roll), a user manual, a guide card, a type-C soft cable and a type C adapter. Note: The charging adapter is not included. Special thermal paper is required for use; ordinary paper cannot be used. This ink-free portable thermal printer is suitable for various scenarios such as home, school, travel, office, and outdoor, meeting the printing needs of different groups of people. This tattoo template printer is also compatible with tattoo transfer paper, making it an ideal choice for tattoo art
Only PDF headers or footers lose the font
Treat header and footer templates as a separate case. Their HTML and resource loading behavior can differ from the document body. Test the template independently and verify that its CSS and font URLs are available in the PDF context.
Performance and reliability practices
- Reuse a browser process where safe, but create a fresh page for each job to avoid leaked state.
- Set explicit navigation and font-wait timeouts and report which URL or face exceeded them.
- Capture request failures and response status codes in structured logs.
- Pin and record Puppeteer and browser versions so a rendering change is attributable.
- Use
networkidle2as a navigation aid, not as proof that fonts loaded. - Cache or serve approved font assets close to the worker when policy and licensing allow it.
- Generate a small diagnostic PDF containing regular, bold, and italic samples whenever you change CSS or browser versions.
Or skip the browser setup
For a URL where you need a rendered image or PDF without maintaining Puppeteer, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
One GET request is enough for an image capture:
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 documentation for PDF options, font and page waits, custom CSS and JavaScript, cookies, headers, device presets, bulk jobs, caching, and signed webhooks. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does networkidle2 guarantee that Google Fonts are ready?
No. It is a navigation-idleness condition. Check the stylesheet and font-file responses and wait for the required faces with document.fonts.
Should I always use page.emulateMediaType('screen') for PDFs?
No. PDFs normally use print media. Use screen emulation only to compare output or when screen styling is intentionally your print design.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC 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 & 11Is self-hosting Google Fonts always better?
No. It reduces dependence on outbound Google requests but adds licensing, storage, update, and deployment responsibilities.
What should a failed font job log?
Log the Puppeteer and browser versions, runtime environment, failed URLs and statuses, page errors, requested family/style/weight, and the individual document.fonts face statuses.
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.

