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 reinstallUse Roboto in a Puppeteer PDF by making the required Roboto files available through CSS, applying that family in the print styles that page.pdf() uses, and waiting for the document’s used fonts to finish loading before you print. Current Puppeteer documentation says PDF generation waits for fonts by default with waitForFonts: true, which waits for document.fonts.ready. That default helps, but it does not prove that the intended file loaded, that the correct weight was selected, or that the resulting PDF embeds Roboto. Verify those separately when they matter.
What Puppeteer needs before printing
A browser can use Roboto only when the page can download a Roboto face and the printed elements request the same family name. A complete setup has three parts:
- Font files, either self-hosted or delivered by a font provider.
- An
@font-facedeclaration for every weight and style the page uses. - A print stylesheet that assigns
font-family: "Roboto", sans-serifto the intended content.
page.pdf() uses print CSS by default. A screen-only rule can therefore be ignored during PDF generation unless you explicitly choose screen media.
Self-host Roboto in your page
Declare the faces you actually ship
Place the files in a location reachable by the browser process, then reference them with CSS. The paths below are examples; replace them with files that exist in your deployment.
Recommended Free Tools
#1 Best Overall
@font-face {
font-family: "Roboto";
src: url("/fonts/Roboto-Regular.woff2") format("woff2");
font-style: normal;
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: "Roboto";
src: url("/fonts/Roboto-Bold.woff2") format("woff2");
font-style: normal;
font-weight: 700;
font-display: swap;
}
body {
font-family: "Roboto", sans-serif;
}
@media print {
body,
.invoice,
.report {
font-family: "Roboto", sans-serif;
}
}
The family string is case-sensitive in practice for matching your declarations consistently: use the same Roboto value in the elements you print. If your CSS requests weight 500 or italic text, provide a matching face or deliberately define how the browser should synthesize it. Declaring only regular and bold does not make every other weight a real Roboto file.
Google Fonts or another hosted stylesheet
A hosted stylesheet normally returns CSS first; the browser then downloads the font files appropriate for its request. This can reduce file-management work, but your render now depends on that external resource being reachable from the machine running Chromium. Self-hosting gives you an explicit resource location and lets you control deployment and caching. Neither approach is established as universally faster or more reliable; choose according to your network and operational constraints.
Complete Puppeteer example
Navigate, verify readiness, and create the PDF
The following Node.js program assumes your page already includes the CSS above. The explicit font wait is useful for diagnostics and for code that must sequence work around font loading. Current Puppeteer documentation already waits for fonts by default when page.pdf() runs.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true
});
try {
const page = await browser.newPage();
await page.goto('https://example.com/report', {
waitUntil: 'networkidle2'
});
// Diagnostic/explicit readiness check. This covers fonts used by the document.
await page.evaluate(() => document.fonts.ready);
// Confirm that the family is available for the text you care about.
const robotoAvailable = await page.evaluate(() =>
document.fonts.check('16px "Roboto"')
);
if (!robotoAvailable) {
throw new Error('Roboto is not available to the document');
}
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
waitForFonts: true
});
} finally {
await browser.close();
}
})();
networkidle2 means the navigation reached a low-activity network state; it is not proof that Roboto was selected successfully. document.fonts.ready resolves after used fonts have loaded and layout has completed. It does not require every declared but unused face to download.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →When the page is populated by JavaScript
Insert the data, wait for the final content, and then await the font promise. If a specific component is the trigger, wait for that selector before the font check.
Rank #2
await page.goto('https://example.com/report', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('.report-ready');
await page.evaluate(() => document.fonts.ready);
await page.pdf({ path: 'output.pdf', waitForFonts: true });
If the page is backgrounded and font waiting does not progress, Puppeteer’s API documentation recommends bringing it to the foreground:
await page.bringToFront();
await page.evaluate(() => document.fonts.ready);
await page.pdf({ path: 'output.pdf', waitForFonts: true });
Print CSS, screen CSS, and PDF options
Use print media (the default)
Put PDF-specific typography in @media print. This is the least surprising option because page.pdf() renders with print media unless you change it.
Use screen media intentionally
If the PDF must match the screen stylesheet, select screen media before printing:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-styled.pdf', printBackground: true });
Do not mix this with an assumption that print rules will still apply. Decide which media model is authoritative, then test the resulting file.
Keep layout stable
- Use explicit font weights that have corresponding faces.
- Set a predictable page size and margins in
page.pdf()when line wrapping matters. - Use
printBackground: truewhen backgrounds are part of the design. - Load images and other layout-affecting assets before the font readiness check if they can change line breaks.
Self-hosted files versus hosted font CSS
| Consideration | Self-hosted Roboto | Hosted stylesheet |
|---|---|---|
| Operational control | You control file versions, URLs, deployment, and cache headers. | The provider controls CSS and file delivery; your page depends on its response. |
| Render-time network dependency | Still depends on your application’s font URL being reachable, but no third-party request is required. | Requires access to the stylesheet and subsequent font-file requests from the Chromium environment. |
| Failure handling | You can package the files with the app or serve them from an internal origin. | Plan for blocked, unavailable, or slow external resources and provide a fallback family. |
| Performance or reliability winner | Not established universally. | Not established universally. |
Whichever route you choose, make the browser’s request path explicit and test from the same network environment used in production.
How to confirm Roboto really reached the PDF
Check the page before printing
const fontState = await page.evaluate(async () => {
await document.fonts.ready;
return {
check: document.fonts.check('400 16px "Roboto"'),
status: document.fonts.status,
loadedFaces: [...document.fonts]
.filter(face => face.status === 'loaded')
.map(face => ({ family: face.family, weight: face.weight, style: face.style }))
};
});
console.log(fontState);
This reports browser-side availability for used faces. It is not a PDF-embedding report.
Inspect the generated file when embedding matters
Open the PDF visually to catch fallback fonts, unexpected wrapping, or missing glyphs. If your requirement is that Roboto be embedded, run a suitable PDF font-inspection utility against the output and verify the embedded or subsetted font records. CSS declarations and a resolved font promise alone cannot guarantee the exact embedding behavior of every Chrome and Puppeteer combination.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Troubleshooting Roboto in Puppeteer PDFs
The PDF uses a fallback font
- Check that the printed element requests exactly the family declared by
@font-face. - Check the browser’s response for each WOFF/WOFF2 URL and confirm the file is reachable from the render machine.
- Check that the requested weight and style have a matching declaration.
- Await
document.fonts.readyand usedocument.fonts.check()before printing.
Bold text is not Roboto Bold
Define a 700 face and apply font-weight: 700. If only a 400 file exists, the browser may synthesize bold rather than use an actual bold face.
The font works on screen but not in the PDF
Inspect @media print rules and computed styles under print media. A screen rule may be overridden, or the PDF may be using a different selector. Alternatively, call page.emulateMediaType('screen') deliberately.
document.fonts.ready resolves, but the output is wrong
The promise covers fonts used by the document and layout completion, not every declared face, and it does not certify PDF embedding. Check the selected weight, computed family, network responses, and the PDF’s font records separately.
Rank #4
PDF generation stalls while waiting for fonts
Verify that font URLs do not hang or require credentials unavailable to Chromium. If the page is in the background, call page.bringToFront() before awaiting readiness, as documented by Puppeteer.
Characters are missing
Confirm that the Roboto file you distribute contains the required Unicode glyphs. A successful load does not mean every language or symbol is covered by that particular file.
Version and deployment notes
The current Puppeteer documentation identified for this guide is for Puppeteer 25.12.0 and pairs it with Chrome for Testing 154.0.8037.57. Pin the Puppeteer and browser versions used by your deployment and re-check the compatibility matrix when upgrading; defaults and browser behavior can change. This guide targets Chromium-backed Puppeteer PDF output.
Also review the license that accompanies the Roboto files you distribute. The implementation details here do not establish licensing terms for a particular download or packaging source.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your actual task is obtaining a clean image or PDF of a URL rather than controlling Puppeteer typography yourself, ScreenshotNeo provides a single-call website screenshot API and an MCP server for AI agents. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemscurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for all options, including PDF output, device and viewport settings, custom CSS and JavaScript, waits, cookies, headers, geolocation, caching, signed links, asynchronous jobs, bulk capture, and the usage API. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.
Best Value
- Used Book in Good Condition
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account.
Frequently asked questions
Does Puppeteer automatically embed Roboto?
No universal guarantee is established. Puppeteer waits for fonts by default, but embedding and subsetting depend on the Chromium/Puppeteer combination and the generated file. Inspect the PDF when embedding is a requirement.
Should I wait for networkidle2 or document.fonts.ready?
They answer different questions. The former describes navigation network activity; the latter concerns used-font loading and layout. Use the font promise when font readiness matters.
Do unused @font-face declarations download?
Not necessarily. The font-loading API concerns fonts used in the document, so a declared face that no element selects may remain unloaded.
Can I use a different Roboto file format?
Yes, provided the browser can fetch and decode it and your src declaration identifies the format accurately. Test the exact files and browser version used in production.
Frequently Asked Questions
Does Puppeteer automatically embed Roboto?
No universal guarantee is established. Puppeteer waits for fonts by default, but embedding and subsetting depend on the Chromium/Puppeteer combination and the generated file. Inspect the PDF when embedding is a requirement.
Should I wait for networkidle2 or document.fonts.ready?
They answer different questions. networkidle2 describes navigation network activity; document.fonts.ready concerns used-font loading and layout.
Do unused @font-face declarations download?
Not necessarily. The font-loading API concerns fonts used in the document, so a declared face that no element selects may remain unloaded.
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.

