Website Screenshot Has Missing Images: How to Fix It
Find out whether missing screenshot images failed to load, were blocked by the browser, or appeared after capture—and fix the cause.
A missing image in a website screenshot usually has one of three causes: its request failed, the browser blocked it, or the capture happened before it loaded. Start in Chrome DevTools: open Network, reload, filter to images, and inspect the missing image’s request URL, status, response, initiator, and timing. That evidence tells you which fix to try. Chrome’s Network panel guide covers these inspection tools.
1. Find the image request that failed
- Open the affected page in Chrome and open DevTools.
- Select Network, enable Preserve log if navigation may occur, then reload the page.
- Filter by the Img resource type. Locate the request corresponding to the missing image.
- Inspect its status, request URL, response, headers, initiator, and timing. Use the Preview or Response view when available.
A failed request points toward a URL, server, or request-path problem. A blocked request or a Console/Issues warning points toward a browser security or policy condition. A successful request that completes after the screenshot points toward a capture timing problem. The missing visual alone cannot identify the root cause.
2. Check browser security and policy errors
Check the Console and Issues panel for errors tied to the image. Chrome reports issues such as mixed content, CORS errors, and Content Security Policy violations. Follow the affected-resource link and inspect that specific request before changing a policy. See Chrome’s Issues guide and Privacy and security panel documentation.
Mixed content: HTTP image on an HTTPS page
If the page is loaded over HTTPS but an image URL uses HTTP, the request is mixed content. Depending on the resource and browser behavior, it can be blocked or upgraded. Change the image URL to a working HTTPS endpoint, then reload and verify the request in Network. Do not assume all browsers handle every mixed-content image the same way. See web.dev’s mixed-content guidance.
CORS or Content Security Policy
Do not add broad security exceptions based only on the symptom. Use the Console or Issues link to identify the specific resource and reported policy. Then check the image request and the page’s relevant policy or server configuration. The evidence determines the appropriate change; a screenshot cannot tell you which policy is wrong.
3. Check whether the screenshot was taken too early
In Network, enable screenshots and reload. The loading timeline lets you compare what was visible at different moments with when image requests occurred. If the image request is still pending or rendering occurs after the capture point, the image may be healthy but late.
For a useful retest, disable the cache and simulate a slower connection in DevTools. This can expose first-visit or timing issues hidden by a warm cache or a fast local connection. See Chrome’s Network activity guide.
4. Wait for the required content in browser automation
A navigation completion condition is not proof that every deferred, site-specific, or scroll-triggered image has rendered. Wait for the actual image or page state you need, and verify it before capturing. Puppeteer documents navigation wait conditions and screenshot capture in its screenshots guide; Playwright documents its screenshot APIs.
Puppeteer: wait for an image before capture
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
// Replace this selector with the image that must appear in the screenshot.
await page.waitForSelector('.hero img', { visible: true, timeout: 15000 });
await page.waitForFunction(() => {
const img = document.querySelector('.hero img');
return img instanceof HTMLImageElement && img.complete && img.naturalWidth > 0;
}, { timeout: 15000 });
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
The selector and timeout are site-specific. If an image is lazy-loaded only after scrolling into view, scroll it into view before waiting. A visible element can still be a broken image, so checking complete and naturalWidth catches a common failure that selector visibility alone misses.
Playwright: wait for an image before capture
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
const image = page.locator('.hero img');
await image.waitFor({ state: 'visible', timeout: 15000 });
await image.evaluate(async (element) => {
const img = element;
if (!img.complete) {
await new Promise((resolve, reject) => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', reject, { once: true });
});
}
if (img.naturalWidth === 0) throw new Error('Image loaded without usable pixels');
});
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
For a page with several important images, wait for each relevant element or check them together. Avoid treating a generic delay as proof: network conditions and page behavior vary, and a delay can still finish before the image is ready.
5. Interpret the symptom before changing anything
| What you observe | What to inspect | Next step |
|---|---|---|
| Image request failed or returned an error | Request URL, status, response, initiator | Correct the URL, server response, or request path indicated by the request details. |
| Request is blocked or a browser issue is reported | Console, Issues, Network details | Resolve the reported mixed-content or policy condition for that resource. |
| Image appears after waiting or scrolling | Loading timeline and capture time | Trigger the required lazy content and wait for the image to load before capture. |
| Image is missing only in one capture environment | Browser, viewport, cache, connection conditions | Reproduce with cache disabled or throttling and compare the image requests. |
6. Troubleshooting common capture failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Image URL returns an error | Bad path or server response | Use the Network request URL and response details to correct the path or server behavior. |
| Console reports mixed content | HTTPS page requests an HTTP image | Use a working HTTPS image URL and confirm the resulting request. |
| Console or Issues links a policy error | Browser security or page policy affects the resource | Follow the linked resource and inspect its request before adjusting the specific policy. |
| Image is absent in automation but appears later | Capture ran before request or rendering completed | Wait for the target image’s loaded state and verify it before taking the screenshot. |
| Image loads after scrolling | Page defers or triggers loading based on visibility | Scroll the image into view, then wait for its request and rendered pixels. |
| It works locally but not on first capture | Warm cache or fast local connection masks timing | Disable cache, throttle the connection, and inspect the cold-load request sequence. |
| Wait-for-selector succeeds but image is blank | The element exists, but its image request failed or has no usable pixels | Check the request and verify that the image has nonzero natural dimensions. |
Or skip the browser setup
ScreenshotNeo captures a URL with one request and returns an image or PDF. It accepts cookie 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, blank pages, and failed loads are never billed, and response headers identify the page verdict and billing status. Its MCP server gives Claude, Cursor, and other MCP clients screenshot, page-info, and PDF tools.
For a missing-image investigation, first make sure the source page itself loads the needed image. Screenshot automation cannot repair a failed image URL or a browser policy error; it can help you capture after page content is ready. The call below requests a WebP capture of the example URL.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options and response details. The API also supports full-page capture with lazy images loaded, selector-based element capture, waits for a selector, delay, or network idle, and custom CSS or JavaScript. Use the wait option that matches the page; a generic delay does not establish that a particular image succeeded.
ScreenshotNeo includes 1,000 screenshots a month free with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Sign up for 1,000 free screenshots a month, with no card required.
Performance, reliability, and cost
- Performance: Waiting for a specific image can avoid unnecessary delay compared with an arbitrary long timeout. Choose a bounded timeout and fail clearly when the needed image never becomes usable.
- Reliability: Reproduce with cache disabled and a slower connection, then inspect the target request. A single successful warm-cache capture may not represent a first visit.
- Cost: For self-hosted browser automation, account for browser runtime and retries in your own environment. For ScreenshotNeo, only clean shots are billed; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Check the response’s billing headers for an individual capture.
FAQ
Does a screenshot tool fix broken images on the page?
No. It captures the page state. Fix the image URL, server response, or browser policy problem at its source.
Is waiting for the page’s load event enough?
Not necessarily. Deferred and scroll-triggered content can load later. Wait for the specific image you need and verify it has usable pixels.
Why does the image show in my browser but not in an automated screenshot?
The browser environment, cache, viewport, network timing, or capture point may differ. Compare those conditions and inspect the image request in the failing environment.
Should I add a fixed sleep before every screenshot?
A fixed delay can mask a timing issue but cannot prove an image loaded. Prefer an image-specific readiness check with a timeout.


