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.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

To capture lazy-loaded images in Selenium, scroll through the page before taking the screenshot, then wait for the images you need to load successfully. A completed driver.get() alone does not prove that JavaScript-driven content or images are ready.

Use this Python workflow

The example below triggers content that loads as it approaches the viewport, waits up to 20 seconds for ordinary document images to load successfully, returns to the top, and saves a viewport screenshot. It assumes you have already created driver and opened the target page.

from selenium.webdriver.support.ui import WebDriverWait


def trigger_lazy_content(driver, step=600):
    height = driver.execute_script(
        "return document.documentElement.scrollHeight"
    )
    y = 0

    while y < height:
        driver.execute_script("window.scrollTo(0, arguments[0])", y)
        y += step
        # Pages that expand as you scroll may increase in height.
        height = driver.execute_script(
            "return document.documentElement.scrollHeight"
        )

    # Visit the bottom as well, including after a height change.
    driver.execute_script(
        "window.scrollTo(0, document.documentElement.scrollHeight)"
    )


trigger_lazy_content(driver)

# complete is true after a fetch ends, even if it failed.
# naturalWidth > 0 filters out ordinary images without available image data.
WebDriverWait(driver, 20).until(lambda d: d.execute_script("""
    return Array.from(document.images).every(
        img => img.complete && img.naturalWidth > 0
    )
"""))

driver.execute_script("window.scrollTo(0, 0)")
driver.save_screenshot("page.png")

For a full-document PNG in Firefox, Selenium’s Python API documents get_full_page_screenshot_as_file:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
driver.get_full_page_screenshot_as_file("page-full.png")

Check that this method is available for your installed Selenium and browser combination. Selenium’s general screenshot method saves the current browsing context; the Firefox full-page method is browser-specific. See Selenium WebDriver documentation and verify the API for the browser you use.

Why scrolling and explicit waits matter

Navigation readiness is not image readiness

Selenium’s pageLoadStrategy controls when navigation returns: normal waits for the document’s complete ready state, eager for interactive, and none does not wait for document readiness. None guarantees that a JavaScript application has finished updating. Selenium’s Browser Options documentation cautions that a page may continue loading content after the ready state returns complete. Wait for the specific content your screenshot needs.

Lazy loading responds to visibility

With native lazy loading, a browser postpones fetching an image until it is near the viewport. Scrolling brings below-the-fold images close enough to trigger fetching. Sites may instead load content through JavaScript, often in response to visibility changes; such pages can need an application-specific wait or interaction. See MDN’s overview of lazy loading.

Check successful loads, not just completed fetches

HTMLImageElement.complete becomes true when fetching has ended, including when it failed. naturalWidth is zero when image data is unavailable, so requiring complete and a positive naturalWidth is a better success check for ordinary <img> elements. If the screenshot depends on decoded pixels being ready to paint, the browser’s decode() method can provide a more specific signal. See MDN on complete, MDN on naturalWidth, and MDN on decode().

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

Choose viewport or full-page output

A viewport screenshot captures the currently visible browsing context. A full-page screenshot aims to capture the whole document. Decide which output you need before choosing a method: an expanding capture alone may not scroll through the page and therefore may not trigger visibility-based image loading. After triggering and waiting for content, return to the intended starting position if the capture method or page behavior depends on scroll position.

  • Viewport: use driver.save_screenshot("page.png") after positioning the browser at the desired section.
  • Full document: use a full-page method supported by your browser and Selenium version; the documented Python full-document method is for Firefox.

Adapt the workflow for pages that do not fit the basic pattern

Wait only for images that matter

The example waits for every image in document.images. A page with intentionally broken images can therefore time out even if all required images are present. Identify the target images and wait only for those, or handle failures explicitly. Do not silently treat a timed-out readiness check as a successful complete capture.

Handle content outside ordinary document images

The document.images check covers ordinary <img> elements, not every visual asset. CSS background images, images outside the document, or content that appears only after a click may need separate, page-specific checks and triggers.

Scroll nested containers and expanding pages deliberately

If the images are inside a scrollable panel, scrolling the window will not bring them into view; scroll that container instead. Infinite-scroll pages may keep increasing their height indefinitely. Set a stopping condition appropriate to the task, such as reaching a known target element or a maximum number of scrolls, rather than waiting for the height to stop changing forever.

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

Troubleshooting

  • The screenshot still has blank image areas: navigation may have returned before JavaScript finished, the page may require scrolling or interaction, or the images may be inside a nested scroller. Trigger the relevant content and wait for its specific elements.
  • The image wait times out: complete plus positive naturalWidth rejects failed images. Check whether an image is intentionally broken, inaccessible, or outside the page content you need; narrow the condition rather than removing the timeout.
  • The scroll loop never finishes on an infinite page: the document keeps growing. Add a task-specific stopping rule, such as a target element or a maximum scroll count.
  • The full-page screenshot method is missing: get_full_page_screenshot_as_file is documented for Selenium’s Firefox Python API, not as a universal cross-browser method. Check your installed browser and Selenium API and use a supported full-page capture option.
  • The capture happens at the wrong vertical position: return to the required scroll position after loading; the example returns to the top before saving.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo can return a screenshot or PDF with one GET request. Its capture flow accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents.

Install requests, set your API key, and run this Python example to save a screenshot:

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)

See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.

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.