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

The dependable way to find broken images is to use two checks together: inspect image requests in the browser’s Network panel, then verify the rendered <img> elements with JavaScript. Network data explains whether a URL returned a 404, redirect, server error, or non-image response; the browser check confirms whether the returned bytes actually decoded into usable image data.

For a single page, DevTools and the script below are enough. For a whole site, repeat the checks across representative templates, authenticated and localized views, lazy-loaded content, and responsive variants. Keep missing alternative text, layout problems, and oversized files as separate test categories: an image can load correctly and still fail one of those other requirements.

What counts as a broken image?

An image is broken when the browser cannot display usable image data in its <img> element. Common causes include a missing file, an incorrect case-sensitive path, a failed deployment, a blocked request, an expired signed URL, an HTML error page returned where an image was expected, or a file format the browser cannot decode. The HTML specification requires the element to enter a broken state when the data is fatally corrupted or uses an unsupported format.

Do not define success only as “the server returned HTTP 200.” A server can return a 200 response containing an HTML login page, JSON error object, or corrupted bytes. Pair the status and response inspection with a rendered-browser check.

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

Use a layered test

  1. Observe the request. Record the request URL, final URL after redirects, status, response headers, content type, cache state, and initiator in DevTools.
  2. Confirm browser decoding. After the page settles, find images whose request completed but whose naturalWidth is zero.
  3. Cover images added later. Scroll through lazy-loaded sections and listen for error events on images inserted by JavaScript.
  4. Test the real delivery context. Include logged-in pages, regional variants, CDN cache states, different viewports, and picture/srcset candidates.
  5. Separate other defects. Check alternative text, responsive layout, and image weight with their own acceptance criteria.

Manual test in Chrome DevTools

1. Start with the correct page state

Open the page in a current browser. If the page is private, sign in before testing and note that the result applies to that account and permission scope. Use a clean reload so stale markup or cached failures do not hide the current behavior.

2. Filter Network requests to images

Open DevTools → Network, reload the page, and select the Img resource filter. Chrome’s Network panel lets you inspect image headers and response bodies as well as timing and initiator information.

3. Investigate suspicious rows

Look for 404 or 410 responses, 500 or 503 responses, unexpected redirects, mixed-content blocks, CORS failures, and requests marked as blocked. Open each candidate and record:

  • the requested URL and the final URL after redirects;
  • the HTTP status and status text;
  • the Content-Type header;
  • whether the response came from memory, disk, or a CDN cache;
  • the response body, when DevTools makes it available; and
  • the initiator, which identifies the HTML, stylesheet, script, or component that created the request.

A 404 or 410 normally points to a bad file name, path, case mismatch, or deployment omission. A 500 or 503 requires checking the origin application, deployment, and CDN rather than changing only the page markup. If a response says 200 but the page shows a broken icon, inspect the body and content type: the endpoint may be returning HTML or JSON instead of an image.

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

4. Retest without stale cache

Enable Disable cache while DevTools is open, then reload. After a fix, use a hard reload and verify the final URL again. A cache can preserve an old redirect, an old 404, or a previously generated transformation.

Confirm failures in the rendered DOM

The naturalWidth property is the intrinsic, density-corrected width of an image in CSS pixels. It is zero when the browser has no usable intrinsic image data. The complete guard prevents reporting an image while its request is still in progress.

const broken = [...document.images].filter(img => img.complete && img.naturalWidth === 0);
console.table(broken.map(img => ({
  src: img.currentSrc || img.src,
  alt: img.alt
})));

Run this in the Console after the initial page has settled. For pages with lazy loading, scroll through the page first, wait for newly requested images to finish, and run it again. The currentSrc value is important because responsive markup may select a different URL from the one shown in the src attribute.

Capture errors as they happen

Attach an error listener before triggering lazy loading or client-side navigation. This catches failures that are inserted after the first page load.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const failures = [];
document.addEventListener('error', event => {
  const img = event.target;
  if (img instanceof HTMLImageElement) {
    failures.push({
      src: img.currentSrc || img.src,
      alt: img.alt,
      element: img
    });
    console.warn('Image failed:', failures[failures.length - 1]);
  }
}, true);

The capture listener is deliberate: image errors do not bubble normally, but listening during capture lets the document observe them. Install it before scrolling, opening a modal, changing a carousel slide, or navigating a single-page application route.

Test every image a user can receive

Lazy-loaded and dynamically inserted images

Initial HTML is not the complete image inventory on many sites. Scroll to the bottom, expand accordions, switch tabs, open galleries, and exercise infinite-scroll or client-side routes. Repeat the naturalWidth check after each state that inserts images.

Authenticated, localized, and regional variants

An image may work for an administrator and fail for an anonymous visitor, or work in one region while a CDN rule fails in another. Run the same page in the relevant login states, locales, geographies, and cache conditions. Record which scope each result covers instead of treating one session as site-wide proof.

Responsive candidates and art direction

Test narrow mobile and large desktop widths, plus any picture sources and srcset candidates. A desktop URL can be valid while a mobile-specific crop is missing. Check the selected currentSrc at each viewport.

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

Representative templates versus exhaustive crawling

For a small site, inspect every page. For a large site, crawl representative templates and URL patterns, then add pages known to contain custom components, user uploads, or unusual transformations. A page audit is not a guarantee that every URL in a large site was tested.

Automate repeated checks

Browser-level automation

A browser script can load a route, wait for network idle or a known selector, scroll to trigger lazy loading, collect image error events, and evaluate the naturalWidth condition. Preserve the page URL, selected currentSrc, alt text, viewport, login scope, and timestamp with each finding so a failure can be reproduced.

HTTP verification alongside browser checks

An HTTP client or crawler can request image URLs directly and flag status codes, redirects, and unexpected content types quickly. It cannot prove that the browser decoded the bytes or that CSS produced a usable layout, so use it as a fast first pass rather than the sole acceptance test.

Scheduling and false-positive control

Run checks after deployments and on a schedule appropriate to the rate at which content changes. Retry transient 5xx responses once, but retain the original evidence. Do not automatically label every redirect as broken: a redirect can be intentional, while a redirect to an HTML login page is a rendering failure. Compare the final URL and response body with the expected image resource.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

W3C’s Link Checker can complement an image-focused check for sites with many templates. Lighthouse is useful for performance, accessibility, best-practices, and SEO audits, but its report covers the page it audits rather than every URL in a site.

Do not confuse a broken image with other image defects

Missing or unsuitable alternative text

A missing alt attribute is an accessibility defect, not evidence that the file failed to load. Automated tools can identify missing attributes, but deciding whether the wording conveys the image’s purpose requires context. Test loading and alternative text as separate criteria.

Visual overflow and poor reflow

An image can load and still break the layout at a narrow width or high zoom. Use responsive constraints such as an appropriate maximum width and height, then inspect mobile widths, large desktop widths, and 400% zoom. Confirm that content reflows without unwanted horizontal scrolling.

Oversized delivery

An image can be valid but inefficiently large. Lighthouse’s image-delivery audit identifies cases where the rendered image is substantially smaller than the downloaded asset and reports potential savings. Optimize this separately from broken-image testing by serving an appropriately sized responsive asset.

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

Troubleshooting matrix

Symptom Evidence to collect Likely cause and next action
404 or 410 Network status, requested path, final URL Correct the URL, file name, case, or deployment path.
500 or 503 Origin/CDN response and timing Check the application, deployment, transformation service, and CDN health.
200 response but broken icon Content type, response body, and naturalWidth Confirm that the body is a decodable image, not HTML or JSON, and inspect image transforms.
Works for some users only Login state, region, cache, user agent, and final URL Reproduce the affected session or geography and check authorization and CDN variation.
Loads but overflows at zoom Viewport, zoom level, computed dimensions Apply responsive sizing and verify reflow at 400% zoom.
Loads but is very heavy Rendered dimensions, transferred bytes, Lighthouse finding Serve a right-sized responsive asset and keep delivery optimization separate from availability.

Or skip the browser setup

When you need a repeatable screenshot of a page while checking its rendered state, ScreenshotNeo provides a website screenshot API and MCP server. Its cleanup step accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Full-page capture loads lazy images, and you can wait for a selector, delay, or network idle, select one element by CSS selector, set a viewport or device preset, use dark mode or a retina scale, and supply custom CSS or JavaScript. Custom headers, cookies, user agents, Authorization, timezone, and geolocation help reproduce authenticated or regional states.

Use the API documented at https://screenshotneo.com/docs/. This cURL request saves a WebP screenshot:

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

The equivalent Python request is:

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)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo identifies the result with X-Page-Verdict and X-Billed headers. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; only clean shots are billed. For larger checks, bulk capture accepts up to 100 URLs per call, and async jobs can notify your system through signed webhooks. Caching uses a TTL you choose, and signed links are available for public <img> tags.

An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients, so an AI agent can inspect pages without custom browser wiring. Every feature is included on every plan. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to start.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Practical acceptance checklist

  • Every image request has an expected final URL and an image content type.
  • No required image ends in a 4xx, 5xx, blocked request, or mixed-content failure.
  • The settled DOM contains no completed image with naturalWidth === 0.
  • Lazy-loaded, modal, carousel, infinite-scroll, and client-rendered images were exercised.
  • Authenticated, localized, regional, and cache-sensitive states were tested where applicable.
  • Each responsive picture or srcset candidate works at its target viewport.
  • Alternative text, reflow at 400% zoom, and image weight were assessed separately.
  • Failures retain the URL, status, response details, viewport, session scope, and reproduction time.

FAQ

Should I test image URLs directly or only through the page?

Use both. Direct requests quickly expose missing paths and server errors, while a real browser catches decoding failures, authentication differences, lazy loading, and the responsive candidate actually selected for a user.

Why can a broken icon disappear after a refresh?

The first request may have encountered a transient origin or CDN failure, or the browser may have used a stale cache entry. Compare a cache-disabled reload with the original Network evidence and keep the failure if it recurs.

What evidence should a bug report contain?

Include the page URL, selected image URL, viewport, login or locale scope, timestamp, status and content type, final redirect URL, a screenshot, and the DOM result. That lets another person distinguish a bad source path from a browser-only decoding or layout issue.

Frequently Asked Questions

Should I test image URLs directly or only through the page?

Use both. Direct requests expose missing paths and server errors quickly; a real browser verifies decoding, authentication, lazy loading, and responsive URL selection.

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

Why can a broken icon disappear after a refresh?

A transient origin or CDN failure, or a stale cache entry, can make the result intermittent. Compare a cache-disabled reload with the original Network evidence.

What evidence should a broken-image bug report contain?

Record the page and selected image URLs, viewport, login or locale scope, timestamp, status, content type, final redirect URL, screenshot, and DOM result.

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.