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 →Scroll the image into view, wait until the image itself has loaded, then capture the page or element. A page’s load event—or a full-page screenshot option—does not guarantee that a lazy-loaded image has been fetched. MDN explains that lazy-loaded resources can remain unloaded when the document’s load event fires (MDN: Lazy loading).
Why a lazy-loaded image can be missing
Lazy loading postpones fetching non-critical resources, often until they are near the viewport. With loading="lazy", the browser decides how close an image must be to the viewport before loading it (MDN: the img loading attribute). Websites may also use their own scroll or intersection-based scripts.
As a result, navigation completing—or waiting for network activity to settle—may not be enough: an image that has not yet been requested cannot finish loading. Trigger the page’s loading behavior by scrolling, then verify the target image before capture.
Choose full-page or element capture
| Capture | Use it when | What to check |
|---|---|---|
| Full page | You need the whole scrollable document. | Scroll through the page to trigger lazy loading, then wait for relevant images before capturing. The full-page option controls capture scope; it does not promise to run every site’s loading logic. |
| Element | You need one image or component. | Bring the target into view and confirm its image loaded. Some element screenshot APIs scroll a hidden target into view, but still verify image readiness. |
Playwright supports both page and locator screenshots (Playwright screenshot guide; Page screenshot API). Puppeteer supports page and element screenshots (Puppeteer screenshot guide).
#1 Best Overall
Capture with Playwright
This Node.js example scrolls the target image into view, waits for it to load successfully, and saves an element screenshot. Change the selector to match the image you need.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com/page', { waitUntil: 'domcontentloaded' });
const image = page.locator('img.hero-image');
await image.scrollIntoViewIfNeeded();
await image.waitForFunction(img => img.complete && img.naturalWidth > 0);
await image.screenshot({ path: 'image.png' });
} finally {
await browser.close();
}
})();
complete indicates the image has finished loading (or failed); naturalWidth > 0 helps distinguish a successfully loaded image from a broken one. If the page uses a custom widget rather than a normal <img>, inspect its rendered state and wait for the site-specific indicator instead.
For the whole page, use the same scroll-and-readiness approach, then replace the element capture with:
Rank #2
await page.screenshot({ path: 'screenshot.png', fullPage: true });
For long pages, scroll in increments so viewport-based and custom loaders get a chance to run. Do not assume that fullPage: true itself triggers every lazy loader.
Recommended Free Tools
Capture with Puppeteer
Puppeteer’s element screenshot attempts to scroll a hidden element into view (Puppeteer screenshot guide). Wait for the image’s own state before taking the screenshot:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com/page', { waitUntil: 'domcontentloaded' });
const image = await page.$('img.hero-image');
if (!image) throw new Error('Target image was not found');
await image.evaluate(img => img.scrollIntoView({ block: 'center' }));
await page.waitForFunction(img => img.complete && img.naturalWidth > 0, {}, image);
await image.screenshot({ path: 'image.png' });
} finally {
await browser.close();
}
})();
For a whole-page screenshot, use await page.screenshot({ path: 'screenshot.png', fullPage: true }); after triggering and checking lazy-loaded content. Puppeteer’s navigation example may use networkidle2, but network idleness alone does not prove that images not yet requested have loaded.
Rank #3
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its capture options include full-page screenshots with lazy images loaded, and one GET request can return an image or PDF. For an API overview and options, see the ScreenshotNeo documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners and consent overlays, newsletter popups, and chat widgets are removed before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. AI agents can use its MCP server tools, including take_screenshot. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Sign up for ScreenshotNeo’s free plan.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot a missing image
- The image is still blank: Confirm the selector matches the intended image, scroll it into view, and wait for
complete. IfnaturalWidthis zero, treat it as a failed image rather than capturing it as ready. - The page load or network-idle wait finished first: That only describes the current document or network state; it does not trigger resources the page has not requested. Scroll progressively and wait on the image itself.
- Full-page output omits lower images: The capture option sets the output area, not the site’s custom lazy-loading behavior. Visit the page in increments before capture.
- The element screenshot is empty: Check that the locator or selector exists and refers to the rendered target. Scrolling an element into view can trigger loading, but allow the image to finish loading before saving.
- The page uses a custom loader: A normal image readiness check may not represent completion of a widget or background image. Wait for an observable site-specific state, then capture.
Frequently Asked Questions
Does Playwright’s fullPage option load lazy images automatically?
No such guarantee is documented. It captures the full scrollable page; trigger lazy loading and verify image readiness before capture.
What does it mean if an image is complete but has no natural width?
The image may have failed to load. Check its source and the page’s image-loading behavior rather than treating it as a successful load.
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.

