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

With Selenium’s Python bindings, the documented native full-page screenshot methods are available in Firefox WebDriver: scroll through the page to trigger lazy loading, wait for images to finish, then call save_full_page_screenshot(). A normal WebDriver screenshot captures the current window, not automatically the entire document. The workflow below checks image success as well as completion; pages with application-driven content may need additional site-specific waits.

What you need

  • Python and Selenium installed in the environment running your script.
  • Firefox and a compatible Firefox WebDriver. Selenium’s Firefox Python API documents full-document PNG capture; do not assume the same methods exist or behave identically in other browsers.
  • A URL you are authorized to access. The example saves the image as page.png in the current working directory.

The Selenium Firefox API reference, surfaced as version 4.50.0 documentation when accessed on October 3, 2026, documents save_full_page_screenshot(path) and get_full_page_screenshot_as_png(). Check the API documentation for the Selenium version and browser you actually use: Selenium Python Firefox WebDriver API.

Use this complete Python script

This script scrolls in viewport-sized steps, waits for image load attempts to finish, checks for images that failed to load, and repeats if the page height grows. It then saves a full-document PNG using Firefox’s native method.

import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

URL = "https://example.com"
OUTPUT = "page.png"


def scroll_through_page(driver, max_passes=5, settle_seconds=0.25):
    """Trigger viewport-based loading and revisit the page if it grows."""
    previous_height = 0

    for _ in range(max_passes):
        height = driver.execute_script(
            "return Math.max(document.body.scrollHeight, "
            "document.documentElement.scrollHeight);"
        )
        viewport = driver.execute_script("return window.innerHeight;")

        # Advance by about one viewport at a time, including the bottom edge.
        for y in range(0, max(height, 1), max(viewport, 1)):
            driver.execute_script("window.scrollTo(0, arguments[0]);", y)
            time.sleep(settle_seconds)

        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(settle_seconds)

        new_height = driver.execute_script(
            "return Math.max(document.body.scrollHeight, "
            "document.documentElement.scrollHeight);"
        )
        if new_height <= previous_height and new_height <= height:
            break
        previous_height = new_height

    # Return to the top for a predictable starting position.
    driver.execute_script("window.scrollTo(0, 0);")


def image_status(driver):
    """Report incomplete images and completed images with no usable width."""
    return driver.execute_script("""
        return Array.from(document.images).map((img, index) => ({
            index,
            src: img.currentSrc || img.src,
            complete: img.complete,
            naturalWidth: img.naturalWidth
        }));
    """)


def main():
    driver = webdriver.Firefox()
    try:
        driver.get(URL)
        # Navigation returning is only an initial readiness point. Dynamic pages
        # and lazy images may continue loading afterward.
        scroll_through_page(driver)

        WebDriverWait(driver, 30).until(
            lambda d: all(item["complete"] for item in image_status(d))
        )

        images = image_status(driver)
        failures = [item for item in images if item["naturalWidth"] == 0]
        if failures:
            print("Images whose load attempts completed without usable data:")
            for item in failures:
                print(f"  image {item['index']}: {item['src']}")

        driver.save_full_page_screenshot(OUTPUT)
        print(f"Saved full-page PNG to {OUTPUT}")
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

Replace URL with the page to capture. The scrolling delay and five-pass ceiling are practical starting values, not universal guarantees: a site may insert content after a longer delay or only after a particular interaction. Selenium supports synchronous JavaScript execution through execute_script; see the Remote WebDriver Python API.

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.

Why scrolling and image checks matter

Scrolling triggers native lazy loading

Browsers defer fetching native lazy-loaded resources until they approach the viewport. Moving down the page brings below-the-fold images into range; waiting at the top alone may leave them unfetched. The browser determines the precise loading distance, so one scroll pass may not be enough if loading adds more page content. See MDN’s lazy-loading overview.

Navigation completion is not visual completion

driver.get() returning, or the browser firing its load event, does not prove every lazy image or dynamic application element is ready. Selenium notes that single-page applications can continue changing after document readiness reaches complete; the load event is also based on eagerly loaded content. For background, see Selenium’s browser options and page-load strategy documentation and MDN’s lazy-loading guide.

Complete does not necessarily mean successful

An image’s complete property indicates that its load attempt has completed, including cases where the request failed. Check naturalWidth as well: a value of zero can indicate no usable image data. The script prints those cases instead of silently treating them as successful. See MDN’s HTMLImageElement.complete reference.

Choose the right full-page capture method

Method What it captures When to use it
ScreenshotNeo API Website screenshot returned as PNG, JPEG, WebP, or PDF Try first if you want a hosted API rather than managing a browser. It removes cookie/consent banners, newsletter popups, and chat widgets before capture; only clean shots are billed.
Firefox WebDriver save_full_page_screenshot() Full document as PNG Use for a Python-controlled Firefox workflow with a documented native full-page method.
Ordinary WebDriver screenshot Current window Use when the visible viewport is all you need. Selenium documents its generic screenshot method as a current-window capture, not a cross-browser full-document method.

The generic screenshot behavior is documented in the Selenium Remote WebDriver Python API. Other browser-specific or stitched approaches vary; verify current official browser and driver documentation, and test sticky headers, very tall pages, and dynamic content before relying on them.

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

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers, made by Yorker Media. Its API takes one GET request with a URL. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, and failed loads are not billed. AI agents can take screenshots through its MCP server, and the Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

Example using the API’s documented cURL pattern (the response is saved as WebP):

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. ScreenshotNeo is an alternative when you want to avoid setting up and maintaining a local browser; learn more at ScreenshotNeo. Sign up for 1,000 free screenshots a month with no card.

Troubleshooting

The output only shows the viewport

Confirm the script is running Firefox WebDriver and calls save_full_page_screenshot(). Selenium’s ordinary screenshot method is for the current window; do not substitute it and expect full-document output.

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

Some images are missing

Check the printed failed-image URLs and naturalWidth values. A completed request can still fail. If images are merely delayed, increase the settling delay or wait for a site-specific selector, then scroll again. Pages may use application-specific triggers beyond native loading="lazy".

The capture misses content appended near the bottom

Repeat the scroll-and-wait pass and inspect the document height after scrolling. The example revisits the page if it grows, but its pass limit is not a guarantee for pages that continue adding content indefinitely. For an application-specific page, wait for a known element or state that signals its content is ready.

The browser hangs or the script exits with an error

Use a finite wait, as in the 30-second image wait above, so a permanently incomplete image does not block the script indefinitely. Keep driver.quit() in a finally block to close Firefox even when navigation, waiting, or capture raises an exception. If the full-page method is unavailable, verify the browser and Selenium version against the Firefox API documentation.

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

Reliability and performance notes

  • Scrolling and waiting take longer than capturing the initial viewport, especially on long pages. Tune the settling delay and wait conditions to the site rather than relying on a fixed sleep as proof of readiness.
  • Rechecking document height helps with content inserted during scrolling, but there is no universal wait that proves a page has no pending visual changes.
  • Very tall pages, sticky elements, and application-specific loading can affect the result. Inspect the saved PNG and test the target page, browser, and driver combination.
  • Full-page screenshot support is browser/API-specific in the documented material. Firefox’s native method is explicit; do not assume generic Selenium screenshot behavior is equivalent.

Frequently Asked Questions

Can Selenium take a full-page screenshot in every browser?

The documented Python full-document methods cited here are Firefox WebDriver methods. Selenium’s generic screenshot API describes the current window; confirm support for the browser and driver you plan to use.

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

Does waiting for all images guarantee the whole page is finished?

No. It checks image load attempts, but scripts, fonts, background images, and application-driven content may still change the page. Use a site-specific readiness condition when the page requires one.

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.