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 matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallWeb fonts become part of a generated PDF only when the rendering browser can load and use the requested font face at capture time, and when the resulting PDF is allowed to contain and distribute that font. In Puppeteer, page.pdf() renders with print CSS and, by default, waits for document.fonts.ready. A missing font resource, mismatched family or weight, unsupported print path, or an unsuitable license can still produce a PDF that looks different from the web page or cannot legally be shared.
What “embedding a web font” means
CSS declares a font face with @font-face, including its family name, source files, weight, style, and optional descriptors. MDN describes @font-face as a way to load a custom font from a remote server or a font installed locally on the rendering computer. WOFF2 is generally a practical web-delivery default because it is compact and broadly supported by modern browsers.
During PDF generation, the browser lays out text, resolves each character to an available face, and produces PDF font data when its PDF pipeline supports doing so. If the requested face is unavailable, the browser can select another face from the CSS font-family fallback list. The PDF may therefore contain a fallback rather than the font you intended. A successful HTTP response for a font file does not by itself prove that the PDF used that face or that distribution is licensed.
Keep three decisions separate:
- Loading: can the renderer reach and decode the font resource?
- Rendering: does the browser use the requested family, weight, and style for print output?
- Rights: does the font license permit embedding and the planned sharing, editing, or commercial use?
How Puppeteer handles fonts when generating a PDF
Puppeteer’s PDF guide states: “By default, page.pdf() waits for fonts to be loaded.” Its API exposes a waitForFonts option that waits for document.fonts.ready. The method generates a PDF using print CSS by default, so print-only rules can change typography, visibility, colors, and layout. See the Puppeteer PDF generation guide and the Page.pdf() API reference.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Do not assume this behavior applies identically to every browser, wrapper, operating system, or PDF engine. If your code changes waitForFonts, starts capture in a custom lifecycle, or uses a different renderer, explicitly wait for the font-loading state before creating the PDF.
Minimal Puppeteer example
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com/invoice', { waitUntil: 'networkidle0' });
// Optional explicit check when your capture flow needs one.
await page.evaluate(async () => {
await document.fonts.ready;
});
await page.pdf({
path: 'invoice.pdf',
format: 'A4',
printBackground: true,
waitForFonts: true
});
await browser.close();
The explicit document.fonts.ready check is useful when other application code controls capture timing. It is not a substitute for making the font URL reachable or for checking the generated file.
Define the font face so the renderer can use it
Declare every face you actually use. A browser can synthesize a bold or italic style when a matching file is absent, but synthetic styling is not the same as loading the intended face.
@font-face {
font-family: 'Acme Sans';
src: url('https://cdn.example.com/fonts/acme-sans-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: block;
}
@font-face {
font-family: 'Acme Sans';
src: url('https://cdn.example.com/fonts/acme-sans-bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: block;
}
body { font-family: 'Acme Sans', Arial, sans-serif; }
strong { font-weight: 700; }
Use the same family spelling and numeric weight in your elements and in the face descriptors. If your page uses a relative font URL, confirm that the document URL resolves it correctly in the headless browser. For HTML generated in memory, an absolute URL or a data URL can avoid an unexpected base path.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Why is my custom font not showing in my generated PDF?
Work through the causes in this order:
1. The font request failed
Private network addresses, authentication requirements, certificate errors, content-security rules, DNS failures, and cross-origin restrictions can prevent the browser from obtaining the file. Inspect requests and browser console messages, and ensure the Puppeteer process has the same network access as a normal user. A font URL that works in your desktop browser may be inaccessible from a container or CI runner.
2. The family, weight, or style does not match
Check that the CSS uses the exact family name declared in @font-face, and that a requested font-weight or font-style has a corresponding face. A page requesting 600 while only 400 is declared can select another face or synthesize one.
Rank #2
3. Capture occurred before the face was ready
Wait for document.fonts.ready and retain Puppeteer’s waitForFonts: true. Also wait for the page’s data and layout to settle; font readiness does not mean images, client-rendered content, or late CSS have finished changing the page.
4. Print CSS selects a different rule
page.pdf() uses print media by default. A @media print rule may replace the family, hide text, alter size, or apply a different stylesheet. Use await page.emulateMediaType('screen') only when screen styling is intentionally required; otherwise design and test the print stylesheet.
5. The renderer does not support that face for printing
Adobe documents that unsupported web-font printing can use the declared fallback stack. A browser may display the web font on screen yet choose a fallback in its print/PDF path. Do not promise identical results across engines based only on Puppeteer documentation.
6. The PDF viewer substitutes a font
Open the file in the viewers your recipients use, not only in the browser that generated it. Check the actual language, accents, symbols, and weights in the document. A viewer can report a substitute when embedded data is missing, incomplete, or unusable.
How do I wait for fonts before Puppeteer generates a PDF?
The documented default is to wait, but an explicit wait makes custom workflows clear:
await page.goto(url, { waitUntil: 'networkidle0' });
await page.evaluate(async () => {
await document.fonts.ready;
// Optional: fail fast if a required face is not usable.
if (!document.fonts.check('400 16px "Acme Sans"')) {
throw new Error('Acme Sans regular face is not available');
}
});
await page.pdf({ path: 'output.pdf', waitForFonts: true, printBackground: true });
document.fonts.check() is a useful diagnostic, but it should be interpreted alongside network logs and the output PDF. It can confirm that the browser considers a face available; it does not establish licensing or guarantee every glyph in your content exists.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #3
How to verify the generated PDF before distribution
- Check the source: confirm the expected
@font-faceURL, family, weight, and style in the HTML delivered to Puppeteer. - Check readiness: record whether
document.fonts.readycompleted and whether required faces passdocument.fonts.check(). - Check print output: inspect print-media rules and compare a representative page with the intended design.
- Check real text: test every language, accented character, symbol, numeral, and bold/italic combination used in the document.
- Check multiple viewers: open the PDF in the target desktop and browser viewers and look for substitutions, missing glyphs, reflow, and changed line breaks.
- Check embedding information: use your PDF inspection tool to see whether the expected font data is embedded and whether subsets are present. Treat that as technical evidence, not legal clearance.
Can I distribute a PDF with a web font?
Only after checking the font’s actual license for the intended distribution. Technical embedding, metadata permissions, and contractual rights are different questions.
Adobe Fonts’ guidance, last updated July 11, 2023, says: “Printing a page that uses web fonts is allowed, provided the printout is for personal use only,” and directs users to licensing terms for PDFs and EPS files made available to users. That is Adobe’s policy guidance, not a universal rule for every foundry, subscription, country, or renderer.
Adobe’s developer guide cautions: “The policies presented in this document do not guarantee that font usage will be in legal compliance with font vendor license agreements.” The PDF 1.7 reference likewise explains that embedded font programs are subject to copyright-owner conditions and, absent contrary information, may be restricted to viewing and printing. Read the license supplied by the foundry or service for your exact font and planned audience. If recipients must edit the PDF, distribute source files, or extract text for a product, those uses may require permissions beyond ordinary viewing.
Relevant references are Adobe’s printing web fonts guidance, Adobe’s Font Embedding Guidelines, and the PDF 32000-1:2008 reference text.
Performance, reliability, and cost considerations
- Use WOFF2 where supported: its smaller transfer size can reduce startup time, while retaining a fallback for environments that cannot decode it.
- Limit faces and subsets: load only the weights, styles, and character ranges the document needs. Verify that required scripts and symbols are included.
- Cache stable font files: immutable, versioned URLs reduce repeated downloads in long-running workers.
- Control network waits:
networkidle0can be slow on pages with persistent connections. Combine a sensible navigation policy with an explicit font readiness check rather than waiting indefinitely. - Use deterministic assets: self-hosting or authenticated asset delivery can improve reproducibility, but it does not change the license terms.
- Fail visibly: if a required face is unavailable, log and stop rather than silently distributing a document with changed line breaks.
Common errors and fixes
“The PDF uses Arial even though the page looks correct”
Inspect print CSS, verify the font request in the capture environment, and check the requested weight/style. Then wait for document.fonts.ready before calling page.pdf().
“Fonts load locally but not in CI”
Compare DNS, certificates, proxy settings, credentials, container fonts, and file permissions. Capture browser console and request failures in CI; do not rely on your workstation’s network or installed fonts.
“Only bold text falls back”
Declare a 700 face (or the exact weight used), confirm its URL and format, and ensure the CSS does not request a weight outside the declared range.
“The PDF has boxes for characters”
The chosen face may lack those glyphs, or the fallback chain may not provide them. Test the actual text and add a licensed face covering the required script and symbols.
“The file renders, but sharing it is questioned”
Rendering success and embedding metadata do not prove distribution rights. Retrieve the font license and ask the vendor about PDF embedding, audience, editing, and commercial distribution when the terms are unclear.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo can return a screenshot or PDF from one GET request, useful when you need a rendered page without maintaining a Puppeteer worker. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the response identifying the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/invoice -o invoice.pdf
See the ScreenshotNeo API documentation for output and options. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Sign up free to try it.
FAQ
Does a WOFF2 file guarantee that the PDF embeds the font?
No. WOFF2 describes a web-delivery format. The renderer must load and use it, its PDF pipeline must preserve font data, and the license must permit the planned embedding and distribution.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsIs networkidle0 enough to guarantee correct typography?
No. It is a navigation wait condition, not a proof that the required face is usable. Check document.fonts.ready, required faces, print CSS, and the output file.
Best Value
Should I use screen or print media for PDF generation?
Use print media when the document is designed for printing, which is Puppeteer’s default. Emulate screen media only when reproducing screen styling is an intentional requirement.
Can a PDF contain a subset instead of the complete font?
PDF producers commonly embed only glyphs needed by the document, but the exact subset and permissions depend on the renderer and font. Inspect the file and consult the license rather than assuming a subset is unrestricted.
Frequently Asked Questions
Does a WOFF2 file guarantee that the PDF embeds the font?
No. WOFF2 describes a web-delivery format; loading, PDF support, and license terms still determine the result.
Is networkidle0 enough to guarantee correct typography?
No. Also wait for document.fonts.ready and verify faces, print CSS, and the output PDF.
Should I use screen or print media for PDF generation?
Use print media for print-oriented documents; Puppeteer uses it by default. Choose screen media only deliberately.
Can a PDF contain a subset instead of the complete font?
It can, depending on the producer, but inspect the file and license before relying on that behavior.
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.




