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

In Playwright, wait for the page’s document.fonts.ready promise before capturing. Then use fullPage: true to capture the full scrollable page:

await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'page.png', fullPage: true });

This lets the fonts currently needed by the document and their layout work settle before the screenshot. It does not guarantee that every font declared in CSS has loaded.

# Preview Product Price
1 The 138 Best Chrome Extensions The 138 Best Chrome Extensions $2.99

Wait for page content, then fonts, then capture

A font wait cannot account for content that has not yet been inserted or rendered. For a single-page app, first wait for the page-specific content that affects the screenshot. If relevant content appears only after scrolling or another interaction, trigger that rendering before waiting for fonts.

const url = 'https://example.com';

await page.goto(url);
// Replace this with a condition specific to the page under test.
await page.locator('main').waitFor({ state: 'visible' });

await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'page.png', fullPage: true });

The content selector is illustrative: choose a condition that means the important content has actually appeared. If scrolling or interaction causes more content or fonts to be used, trigger it first and then await document.fonts.ready again.

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

What document.fonts.ready does—and does not—wait for

document.fonts exposes the page’s FontFaceSet. Its ready promise fulfills after font loading and associated layout operations for fonts currently used by the document are complete. MDN Web Docs puts it this way: “The promise will only resolve once the document has completed loading fonts, layout operations are completed, and no further font loads are needed.” MDN Web Docs: FontFaceSet: ready property.

That is narrower than “all fonts declared in CSS have downloaded.” Unused font faces may not load, and optional faces that did not load in time may remain unused. If the screenshot still shows an unexpected typeface, check whether the intended face was actually used and inspect font loading status or errors through the CSS Font Loading API.

Playwright: capture the full scrollable page

Playwright’s fullPage: true screenshot option captures the full scrollable page rather than just the current viewport. Keep the font wait immediately before the capture, after any page-specific work that can introduce content or trigger font use:

await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'page.png', fullPage: true });

Font readiness and animation handling are separate concerns. For visual regression work, decide separately whether to disable or otherwise handle animations using Playwright’s screenshot options.

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

Capture through Chrome DevTools Protocol

With CDP, evaluate document.fonts.ready in the target page’s execution context, then send Page.captureScreenshot. To capture beyond the viewport, CDP provides captureBeyondViewport; the current protocol reference marks it experimental and lists its default as false. Check the behavior supported by the Chromium version you use.

Playwright offers a higher-level full-page option; CDP exposes the protocol command directly. The conceptual order is the same in both: wait in the page, then capture. Chrome DevTools Protocol: Page.captureScreenshot.

Timeouts and troubleshooting

  • Screenshot uses a fallback font: Verify that the expected font face is used and check the CSS Font Loading API for loading status or errors. An unused or optional face need not be loaded by document.fonts.ready.
  • Some page content is missing: Wait for the app-specific content before the font wait. If scrolling or interaction loads more content, trigger it and await font readiness again before capturing.
  • The page appears to hang: A production script can apply its own timeout policy so a broken or stalled page does not wait indefinitely. There is no universal correct duration established here; choose one appropriate to your pages and failure handling.
  • Layout changes after the capture starts: Ensure the page has reached the state you intend to test before awaiting fonts. The promise concerns font work currently needed by the document; it is not a general guarantee that application rendering has stopped.
  • Screenshot differs because of motion: Handle animations separately; waiting for fonts does not freeze them.
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 can take a screenshot with one GET request. Its API documentation describes the request options.

Quick Recap

Bestseller No. 1
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides screenshot tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

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

Sign up free for ScreenshotNeo.

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.