To keep screenshots from showing fallback fonts or missing images, wait for visual readiness—not just page navigation. After the relevant content renders, wait for document.fonts.ready, then check that the images you need have finished loading and succeeded. For lazy-loaded images, first scroll the capture area to trigger their requests.
Why a page can load before it is screenshot-ready
Navigation events describe document and network activity, not whether the exact content you want to capture is visually ready.
As an Amazon Associate I earn from qualifying purchases.
DOMContentLoadedfires after the browser parses the HTML. It does not establish that custom fonts or images are ready.loadis a useful baseline, but application code can still insert or update content afterward.networkidleis a heuristic, not a guarantee that specific fonts or images are ready. Playwright defines it as no network connections for at least 500 ms and discourages using it as a general readiness assertion; use page-specific checks instead. Playwright Page APIdocument.fonts.readyresolves when loading and layout operations for fonts used by the document are complete. It does not mean every declared font was used or loaded. MDN: Document.fonts MDN: FontFaceSet.ready- An image’s
completeproperty can be true even when loading failed, so checknaturalWidthif success matters. MDN: HTMLImageElement.complete
Wait for used fonts and images in a browser-side script
If your screenshot provider supports a pre-capture JavaScript hook, run a readiness check after the page’s relevant content has appeared. This example waits for used fonts and the images currently in the document, then reports broken images rather than silently treating them as successful:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
await document.fonts.ready;
const images = [...document.images];
await Promise.all(
images.map((img) =>
img.complete
? Promise.resolve()
: new Promise((resolve) => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
})
)
);
const failedImages = images.filter((img) => !img.naturalWidth);
if (failedImages.length) {
throw new Error(`${failedImages.length} image(s) failed to load`);
}
The wait resolves when each image either loads or errors, so an error does not leave the capture waiting forever. The final naturalWidth check distinguishes a successful image from a broken one. Add a timeout using the mechanism your provider supports. If the page inserts images dynamically, wait for the relevant content first and collect document.images afterward; otherwise, the check may miss images added later.
#1 Best Overall
Use a bounded scroll for lazy-loaded images
A lazy-loaded image may not start fetching until it is near the viewport. Waiting for all currently discovered images cannot wait for a request that has not started. Scroll the relevant page or element region to trigger loading, allow the page to respond, and then run the image check.
For full-page screenshots, bound the scrolling work and define the maximum capture height. Pages that grow indefinitely or contain interactive feeds can keep exposing new content; waiting for every off-screen image may waste time or fail to finish. Browserless describes scrolling as a way to trigger below-the-fold lazy images, and ScreenshotOne documents full-page scrolling controls, including the need for smaller scroll steps or more delay on some pages. Browserless screenshot documentation ScreenshotOne options
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Playwright example: navigate, wait, then capture
With a Playwright-controlled browser, use a navigation event as a baseline, then wait for the specific browser-side conditions your screenshot needs:
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.goto(url, { waitUntil: 'load' });
await page.evaluate(async () => {
await document.fonts.ready;
await Promise.all([...document.images].map((img) => {
if (img.complete) return Promise.resolve();
return new Promise((resolve) => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
});
await page.screenshot({ path: 'capture.png' });
This example does not fail the job on broken images; add a naturalWidth check if that is required. For an application that renders asynchronously, use page.waitForFunction with a predicate for its actual state, such as the presence of a known element or a defined image set. Playwright evaluates that predicate in the page context and resolves when it becomes truthy. Playwright Page API
Rank #3
Choose provider controls that match the readiness condition
Provider parameters are not interchangeable. Check the endpoint and interface you use for script execution order, timeout behavior, request limits, and the precise meaning of each wait option.
- Browserless: Its BAP screenshot documentation describes image waiting, and its screenshot API has request options. Verify that the specific endpoint or interface you use exposes the needed control; lazy images may also need scrolling. Browserless screenshot documentation Browserless screenshot API
- ScreenshotOne: Its options include
wait_until,delay, and full-page scrolling settings.wait_untilwaits for navigation events, whiledelaypauses for a fixed interval. Scrolling can trigger lazy loads. A fixed delay may help as a fallback, but a page-side condition is more directly tied to the visual result when custom scripts are available. ScreenshotOne options - Playwright: Navigate with a suitable baseline, then explicitly wait for font, image, or application-specific conditions before calling the screenshot method. Its documentation discourages using
networkidleas a general readiness assertion. Playwright Page API - Puppeteer: Its screenshot guide shows
page.gotowithwaitUntil: 'networkidle2'followed by a screenshot. Treat that as an example navigation flow, not proof that every resource needed by your page has loaded successfully; add explicit readiness checks for the content that matters. Puppeteer screenshot guide
Or skip the browser setup
ScreenshotNeo accepts one GET request with a URL and returns an image or PDF. For a screenshot, its request can include custom JavaScript and wait options; see the ScreenshotNeo documentation for the request parameters and usage. This call saves the returned WebP:
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners as 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, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Troubleshoot missing images or fallback fonts
- Identify what is missing. Determine whether the issue is a fallback font, a failed image, an image that never started loading, or content added after the page’s load event.
- Wait for fonts after relevant content renders. Use
document.fonts.readyrather than an arbitrary sleep when the provider permits browser-side code. - Check image completion and success separately. Wait for load or error events, then inspect
naturalWidthif a broken image should fail the job. - Trigger lazy loading. Scroll the capture region before collecting the final image list and waiting for it.
- Wait for application state when needed. Use a selector or custom predicate if the page renders asynchronously.
- Set a deadline and define failure behavior. Use the provider’s timeout mechanism so a stalled resource does not delay the job indefinitely; report failures rather than silently capturing an incomplete result if accuracy matters.
- Verify the provider’s semantics. Compare its native wait option with a browser-side condition instead of assuming similarly named settings behave the same way.
Balance precision, time, and cost
A precise font/image predicate is more directly tied to the capture than a broad delay, but it still needs a timeout and a clear policy for failed resources. Scrolling can reveal lazy-loaded assets but adds work, especially on long pages. Waiting for every image on an unbounded page is rarely the right target: choose the capture area and the resources that matter. A fixed delay is simple, but it can be too short on a slow page and unnecessarily long on a fast one. No universal wait duration or performance figure applies across pages and providers.
Best Value
Frequently Asked Questions
Does document.fonts.ready wait for every font declared in CSS?
No. It resolves for fonts used by the document and their loading and layout work; unused declared fonts are not necessarily loaded.
Should I use networkidle for screenshot readiness?
Use it only as a navigation heuristic, not as proof that the specific fonts and images in your capture are ready. Prefer targeted page-side conditions.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteWhy does my image check miss images below the fold?
Lazy-loaded images may not begin fetching until they approach the viewport. Scroll the intended capture region first, then wait for its images.
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.




