DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk6 min

How to Capture a Lazy-Loaded Page with Selenium in Java

A practical Selenium Java pattern for scrolling through lazy-loaded content, waiting for the right completion signal, and saving a screenshot.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To capture a lazy-loaded page with Selenium in Java, scroll the page in steps, wait after each step for the specific content you expect, and take the screenshot only when your completion condition is met. A completed navigation or document.readyState value of complete does not guarantee that JavaScript-driven content has appeared.

Use a content signal, not a fixed delay

Lazy-loaded pages often add content as a visitor approaches it. Selenium can execute JavaScript to scroll, while WebDriverWait can poll for a meaningful change, such as a result count increasing or a target element becoming visible. The selector and completion rule must match the page you are capturing; there is no universal selector or fixed wait time that proves every page is complete.

As an Amazon Associate I earn from qualifying purchases.

The example below uses a result-count increase as its signal. Replace .result-item with a selector from the target page. It scrolls incrementally, stops after two consecutive rounds without an increase, and has a maximum-round safety bound. Treat the quiet-round rule as a heuristic, not proof that all content has loaded.

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

Runnable Java example

This example uses Selenium’s Java APIs, ChromeDriver, and a Java version that supports text blocks only if you choose to add them; the code itself uses standard Java syntax. Add Selenium and a compatible ChromeDriver setup to your project before running it.

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;

public class LazyPageScreenshot {
    public static void main(String[] args) throws Exception {
        String url = "https://example.com"; // Replace with the page to capture.
        By itemSelector = By.cssSelector(".result-item"); // Replace with the page's real selector.
        int maximumRounds = 20; // Safety bound; tune for the target page.

        WebDriver driver = new ChromeDriver();
        try {
            driver.get(url);

            JavascriptExecutor js = (JavascriptExecutor) driver;
            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
            AtomicInteger previousCount = new AtomicInteger(
                driver.findElements(itemSelector).size()
            );
            int stableRounds = 0;

            for (int round = 0;
                 round < maximumRounds && stableRounds < 2;
                 round++) {
                js.executeScript(
                    "window.scrollBy(0, Math.max(300, window.innerHeight * 0.8));"
                );

                int countBeforeScroll = previousCount.get();
                try {
                    wait.until(d ->
                        d.findElements(itemSelector).size() > countBeforeScroll
                    );
                    previousCount.set(driver.findElements(itemSelector).size());
                    stableRounds = 0;
                } catch (TimeoutException noNewItemsWithinTimeout) {
                    // May mean no more items, or a wrong selector/condition.
                    stableRounds++;
                }
            }

            File screenshot = ((TakesScreenshot) driver)
                .getScreenshotAs(OutputType.FILE);
            Files.copy(
                screenshot.toPath(),
                Path.of("lazy-page.png"),
                StandardCopyOption.REPLACE_EXISTING
            );
        } finally {
            driver.quit();
        }
    }
}

The AtomicInteger keeps the count usable inside the wait lambda while allowing it to be updated between rounds. The example captures after the loop, even if the maximum-round bound is reached; in production, decide whether reaching that bound should instead fail the job or produce an explicitly partial capture.

Choose a completion condition that fits the page

  • Known element: wait for the target element to become visible when a specific section or item is the goal.
  • Known total: wait until the number of matching results reaches the expected count when the page exposes one.
  • Loading indicator: wait for a loading marker to disappear, ideally alongside a check that the desired content is present.
  • Explicit end state: use a page-provided end marker or completion signal when available.

A count increase is not suitable when the page replaces existing elements rather than appending them. In that case, wait for the target element or another signal that reflects the content you need.

Adapt the scrolling to the page

The sample scrolls the document by a fraction of the viewport. Incremental scrolling is useful when a page responds as successive regions approach the viewport; one jump to the bottom may not trigger the same sequence. This is site-dependent behavior, not a Selenium guarantee.

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

Document scroll or nested container

If the page’s results sit inside a scrollable panel, scrolling window will not move that panel. Identify the scroll container and move that element instead, for example by executing JavaScript that changes the container’s scrollTop. Verify that the intended region actually moves and that the site’s content appears afterward.

Scroll toward a known element

If the target is already discoverable in the DOM, use Selenium element interaction or scroll it into view. This can be a better fit when the page listens to element visibility or when user-like interaction matters. Selenium JavaScript execution runs in the currently selected frame or window; switch into the correct frame before looking for or scrolling content inside it. Selenium also documents that cross-domain restrictions can affect scripts, particularly custom requests or access involving another frame.

Save the right kind of capture

For a screenshot, Selenium’s Java API supports TakesScreenshot and OutputType.FILE, as used above. The driver and browsing context can affect what the screenshot contains. Check the saved image in the actual target environment rather than assuming the result is a full-page image.

If you need only a component, Selenium also supports taking a screenshot of a web element. If you need the whole page, confirm that your chosen browser and driver support the full-page mechanism you intend to use; a normal screenshot may capture only the current viewport.

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

If by “capture” you mean page text or DOM data, locate and extract the loaded elements after the wait condition. Do not rely on getPageSource() as proof that post-load JavaScript changes are represented: Selenium’s Java API does not guarantee that returned source reflects modifications made after the page loaded.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Waits, timing, and reliability

Explicit waits poll until a particular condition becomes true, which suits asynchronously arriving content. Selenium warns: “Do not mix implicit and explicit waits.” Combining them can make timing unpredictable. Prefer an explicit wait tied to the page’s content signal rather than using a fixed sleep as the main completion test.

driver.get() returning, or the browser reaching document.readyState == "complete", is not enough to establish that a single-page app has stopped adding JavaScript-driven content. Page-load strategy checks document readiness; it does not provide a universal application-level completion signal.

For a transition that itself requires asynchronous JavaScript, Selenium Java provides executeAsyncScript. The script must invoke Selenium’s injected completion callback, and the configured script timeout must allow the operation to finish. For most scroll-triggered loading, a synchronous scroll followed by an explicit DOM condition is simpler to inspect and debug.

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

Troubleshooting incomplete captures

Symptom Likely cause What to check or change
The first screenshot is missing lower-page content Navigation completed before the page’s JavaScript added it. Scroll through the page and wait for the target content condition before capturing.
Loading stops at a fixed point The page may load only as successive regions approach view, or the content may be in a nested scroll container. Use incremental scrolling and verify which element actually scrolls.
The wait times out although content seems visible The selector or condition may be wrong, or the content may be inside a frame Selenium has not selected. Check the selector against the rendered DOM and switch to the correct frame before querying it.
The image is not a full-page screenshot Screenshot scope can differ across driver and browsing context. Inspect the output and use a full-page mechanism supported by the target browser and driver if necessary.
getPageSource() appears stale Returned source is not guaranteed to reflect JavaScript changes made after loading. Verify the relevant elements directly or inspect the rendered screenshot.

Or skip the browser setup

ScreenshotNeo can capture a URL with one GET request. Before capture, it accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of these steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, with the response identifying the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and other MCP clients.

For example, with ScreenshotNeo API access configured:

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

The service returns PNG, JPEG, WebP, or PDF captures. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.

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.

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

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.