Use a Selenium Java explicit wait that evaluates every <img> in the current document. The reliable success condition is that each image is complete and has a positive intrinsic width:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
wait.until(d -> (Boolean) ((JavascriptExecutor) d).executeScript(
"return Array.from(document.images).every(img => img.complete && img.naturalWidth > 0);"
));
The naturalWidth test is important: complete can also be true for an empty source or a broken image. This wait covers the current document’s <img> elements; it does not automatically fetch off-screen lazy images, inspect CSS backgrounds, or enter child frames.
Complete runnable Java example
The following test opens a page, waits for its images to load successfully, and then continues with assertions or screenshots.
import java.time.Duration;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
public class WaitForImages {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
Boolean imagesLoaded = wait.until(d -> (Boolean)
((JavascriptExecutor) d).executeScript(
"return Array.from(document.images).every(" +
"img => img.complete && img.naturalWidth > 0);"
)
);
System.out.println("Images loaded: " + imagesLoaded);
} finally {
driver.quit();
}
}
}
Add Selenium’s Java client to your build in the usual way for your project, and use a browser driver compatible with the browser under test. The imports above are sufficient for the wait itself.
#1 Best Overall
Why an explicit wait is needed
Selenium navigation’s default page-load behavior waits for a document ready state, but a ready document is not the same as a fully updated application. JavaScript may insert images after navigation, replace placeholders, or change image URLs after an API response. An explicit wait polls the condition your test actually needs instead of assuming that navigation completion is enough.
WebDriverWait is a specialization of FluentWait<WebDriver>. Its constructor accepts a WebDriver and a Duration; until keeps polling until the function returns a value that is neither null nor false, or the timeout expires.
What the JavaScript predicate checks
document.images
This collection contains the <img> elements in the current document. Array.from(...).every(...) requires every member to satisfy the predicate. If there are no image elements, every returns true; that is logically correct for “all current images,” but you can add a separate assertion if the page must contain at least one image.
img.complete
complete means the browser has finished attempting to load the image resource. It can be true for a successfully decoded image, a broken request, an empty or missing source, or an image that has not required a fetch. It therefore describes settled loading state, not success.
img.naturalWidth > 0
A positive intrinsic width indicates that the browser obtained usable image data. Combining it with complete makes the sample fail when an image request finished unsuccessfully. If your contract is only that requests have settled, use img.complete alone and report broken images separately.
Define what “all images” means
The correct predicate depends on the test’s scope. Decide this before choosing a wait.
Rank #2
- Current document: the supplied predicate checks every current
<img>. - A component: query a known container and evaluate its images, avoiding unrelated ads or widgets.
- Images inserted later: first wait for the application state or component that creates them, then run the image predicate, or combine both checks in one script.
- Lazy-loaded content: scroll through the relevant page so the browser requests images near the viewport, then wait for the resulting elements.
- CSS backgrounds: these are not in
document.imagesand need a separate asset-loading strategy. - Frames: switch into each frame and evaluate that frame’s document independently.
Lazy-loaded images and scrolling
Native lazy loading postpones a fetch until an image approaches the viewport. Such an image may still be pending when the window load event fires. A global image wait cannot force an off-screen lazy image to load; it can only observe the elements and states that currently exist.
For a long page, scroll in increments, allow the application to schedule requests, and then apply the same success check. A simple JavaScript scroll loop is:
((JavascriptExecutor) driver).executeScript(
"window.scrollTo(0, document.body.scrollHeight);"
);
For robust tests, scroll through several viewport-sized positions rather than jumping only to the bottom, because some applications load content when an intersection occurs. After scrolling, wait again:
wait.until(d -> (Boolean) ((JavascriptExecutor) d).executeScript(
"return Array.from(document.images).every(" +
"img => img.complete && img.naturalWidth > 0);"
));
Whether this is sufficient depends on the application’s lazy-loading implementation. Some frameworks replace data-src only after an observer callback, so include the framework’s “content ready” signal when one is available.
Wait for a component and its images together
If images are inserted asynchronously, waiting only on document.images can finish before insertion occurs. Combine a component-presence check with the image check:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
wait.until(d -> (Boolean) ((JavascriptExecutor) d).executeScript(
"const panel = document.querySelector('#product-gallery');" +
"if (!panel) return false;" +
"return Array.from(panel.querySelectorAll('img')).every(" +
"img => img.complete && img.naturalWidth > 0);"
));
This condition does not assert that a particular number of images exists. If the gallery must contain, for example, four images, assert that count separately so a completely empty gallery cannot pass.
Rank #3
Page-load strategy versus an image wait
| Approach | What it tells you | What it does not guarantee |
|---|---|---|
normal (default) |
Navigation waits for the document ready state complete. |
JavaScript-driven updates, late-inserted images, or successful image decoding. |
eager |
Navigation waits for the document to become interactive. |
Most remaining resources and application work. |
none |
Navigation does not block on a ready state. | Any readiness condition; your test must provide explicit waits. |
| Custom image wait | The exact image condition you define, including success via naturalWidth. |
Images outside the queried document, CSS assets, or lazy resources never triggered. |
Choose the narrowest condition that matches the test. Do not mix implicit and explicit waits; Selenium warns that their interactions can make total wait time unpredictable.
Common failures and fixes
TimeoutException
Cause: at least one image never reaches the predicate, often because the URL is broken, blocked, requires authentication, or belongs to an off-screen lazy element.
Fix: inspect the failing elements in the browser, log each image’s src, complete, and naturalWidth, verify network access and credentials, and trigger lazy loading by scrolling. Increase the timeout only when the page legitimately needs more time; a larger timeout does not repair a failed request.
The wait passes despite a broken image
Cause: the predicate checks only complete.
Fix: require naturalWidth > 0, as in the main example, and report the URL of any element that fails.
Recommended Free Tools
The wait passes before images appear
Cause: the page initially has no matching images and asynchronous code inserts them later.
Fix: wait for the container, a known image count, or the application’s loaded state before evaluating image success.
Lazy images remain unloaded
Cause: they are intentionally outside the viewport, so no request has started.
Fix: scroll through the page, wait for each batch, and then run the predicate. If the test is only about visible content, limit the query to that region instead of forcing every page image.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchImages in an iframe are missing
Cause: each frame has its own document.
Fix: locate the frame, call driver.switchTo().frame(...), evaluate the predicate there, then return with driver.switchTo().defaultContent().
CSS background images are not detected
Cause: background images are stylesheets resources, not <img> elements.
Fix: test the component’s computed styles or application-specific readiness signal, and treat that as a separate condition.
Diagnostics for a failing page
Run this script to identify which current-document images are not successful:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
Object[] failures = (Object[]) ((JavascriptExecutor) driver).executeScript(
"return Array.from(document.images)" +
".filter(img => !(img.complete && img.naturalWidth > 0))" +
".map(img => ({src: img.currentSrc || img.src," +
"complete: img.complete, naturalWidth: img.naturalWidth}));"
);
Use the returned records in test logs. They distinguish a not-yet-settled request from a settled request with zero intrinsic width and show the URL the browser actually selected through currentSrc.
Or skip the browser setup
If your goal is a dependable page image rather than a browser test, ScreenshotNeo provides a website screenshot API and MCP server. One request can return PNG, JPEG, WebP, or PDF, with options for full-page capture, lazy-image loading, selectors, waits, custom JavaScript and CSS, device emulation, headers, cookies, blocking rules, and more. Cookie banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools let AI agents call take_screenshot, get_page_info, and capture_pdf.
Use the API documentation at https://screenshotneo.com/docs/ for the complete option list. A minimal cURL request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
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}`);
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account to try it.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minutePerformance, reliability, and cost decisions
- Use the shortest timeout that accommodates the application, and keep polling focused on the component under test when possible.
- Do not wait for third-party advertising or analytics images unless they are part of the requirement; they can make a test slow and nondeterministic.
- For visual assertions, wait for successful intrinsic dimensions before capturing. For request-settlement tests, allow failed images and assert failures explicitly.
- When pages change continuously, define a stable boundary such as a gallery count, a network-idle signal supplied by the application, or a component-ready marker.
- Keep the browser session and test data consistent so authentication, geolocation, and responsive layout do not change which images are requested.
Frequently Asked Questions
Does Selenium have a built-in “wait for all images” condition in Java?
The documented approach is a custom explicit wait. Evaluate the page’s image collection with JavaScript and return a boolean that represents your test’s definition of loaded.
Should I use window.onload instead?
Not when JavaScript inserts content or lazy loading is involved. The load event can fire while deferred images remain unfetched, so wait for the specific state your test needs.
What does a 20-second timeout mean?
It is the maximum time for the explicit wait in the example, not a guarantee that the page will load within that period. A timeout raises an exception when the predicate never becomes true.
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.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.

