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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Scroll first, then capture the current window. In Selenium Python, run driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") and immediately call driver.save_screenshot("screenshot.png"). To frame a particular element instead, pass it to scrollIntoView(true) before saving.

The two-line pattern

Selenium screenshots reflect the browser viewport at the instant the screenshot command runs. Scrolling changes that viewport; it does not automatically create a full-document image. The basic bottom-of-page sequence is:

driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
driver.save_screenshot("screenshot.png")

execute_script runs JavaScript synchronously in the current window or frame. The next Python statement therefore starts after the scroll script returns. save_screenshot saves the current window as a PNG file.

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

Capture the bottom of a page in Python

Complete runnable example

Use a browser and WebDriver that are already configured on your machine, then run:

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
    driver.save_screenshot("bottom-of-page.png")
finally:
    driver.quit()

The script navigates to the URL, moves the viewport to the document’s bottom, writes a PNG, and closes the browser even if a later command raises an exception. Replace the URL and output filename with your own values.

What document.body.scrollHeight means

The expression asks the page for the total height of its body and supplies that value as the vertical destination. The viewport moves to the bottom of the document, but the resulting image is still only the visible viewport. A very tall page is not compressed into one image by this call.

Scroll to a specific element, then capture it

When the target is a heading, card, button, chart, or other known node, locate it with Selenium and call scrollIntoView(true). The true argument aligns the element’s top edge with the top of the viewport.

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


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    element = driver.find_element("css selector", "main article h2")
    driver.execute_script("arguments[0].scrollIntoView(true);", element)
    driver.save_screenshot("element-view.png")
finally:
    driver.quit()

The JavaScript receives the WebElement as arguments[0]; Selenium converts it to the corresponding DOM node. You can use another locator strategy, such as an ID or XPath, when that is more stable for the page you are testing.

Choosing the target

  • Page bottom: use window.scrollTo(0, document.body.scrollHeight) when the last section or footer is the subject.
  • Known element: use arguments[0].scrollIntoView(true) when the capture should center on a particular node.
  • Several sections: locate and capture each element in turn, using a different output filename for every position.

Viewport screenshots versus full-page screenshots

These are different operations and should not be substituted for one another.

Approach Capture scope Typical use Browser/API note
Scroll, then save_screenshot The current viewport only Evidence of what a user sees at the bottom or around an element General WebDriver screenshot method
save_screenshot without scrolling The initial/current viewport Top-of-page or above-the-fold checks General WebDriver screenshot method
Firefox save_full_page_screenshot The full document in one full-page image Whole-page visual regression or archival capture Firefox WebDriver provides this separate API

If your requirement is one image containing every vertical section, repeatedly scrolling and saving ordinary viewport shots is not the same as a full-page capture. Firefox’s documented full-page method is designed for that full-document case. A normal Selenium screenshot remains tied to the viewport dimensions.

Firefox full-document example

from selenium import webdriver


driver = webdriver.Firefox()
try:
    driver.get("https://example.com")
    driver.save_full_page_screenshot("entire-document.png")
finally:
    driver.quit()

Use the ordinary save_screenshot method when you need a particular scroll position; use Firefox’s full-page method when the desired output is the complete document.

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

Lazy-loaded and asynchronous content

The scroll call is synchronous, but that only means the JavaScript operation has returned. It does not establish that images, API responses, infinite-scroll rows, or other resources have finished loading. A page can reach its current bottom while additional content is still being requested.

A reliable sequence

  1. Navigate to the page.
  2. Perform any application-specific readiness check your test already uses.
  3. Scroll to the bottom or to the target element.
  4. Wait using a condition tied to the page’s asynchronous behavior—for example, the appearance of the content your test expects—not an assumed universal delay.
  5. Save the screenshot only after that condition succeeds.

There is no universal delay that guarantees lazy content has loaded on every site. A fixed sleep may work for one environment and fail under another network speed. Prefer a condition that observes the actual selector, state, or content your application exposes.

Infinite-scroll pages

On an infinite-scroll page, document.body.scrollHeight can increase after you reach the initial bottom. If you need the eventual end, repeat a scroll-and-check cycle until the page stops growing or your own completion condition is met, then save the image. Keep a maximum iteration count so a never-ending feed cannot run forever. The exact stopping condition belongs to the application under test.

Java equivalent

The same concepts are available in Selenium Java through JavascriptExecutor and TakesScreenshot:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebDriver driver = new ChromeDriver();
try {
    driver.get("https://example.com");
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("window.scrollTo(0, document.body.scrollHeight)");

    File source = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
    Files.copy(source.toPath(), Paths.get("bottom-of-page.png"));
} finally {
    driver.quit();
}

For an element-centered capture, pass the element as an argument:

WebElement element = driver.findElement(By.cssSelector("main article h2"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView(true);", element);
File source = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

Java’s TakesScreenshot can return a PNG file or a base64 representation. The target and scope rules remain the same as in Python: scrolling changes the viewport, while a full-page method is a separate capability.

Common failures and fixes

The image still shows the top of the page

  • Cause: the screenshot was taken before the scroll command, or a later navigation reset the page.
  • Fix: place execute_script immediately before save_screenshot, and verify that no redirect or reload occurs between them.

The target element is not visible

  • Cause: the locator selected the wrong node, or the element is not present in the current window/frame.
  • Fix: validate the locator, switch to the correct browsing context when your test uses frames, then call scrollIntoView(true) on the returned element.

The screenshot cuts off newly loaded content

  • Cause: lazy or asynchronous content had not finished loading when the image was saved.
  • Fix: wait for an application-specific condition after scrolling. Do not rely on one delay value for every page.

The page bottom keeps moving

  • Cause: infinite scrolling appends more nodes and increases scrollHeight.
  • Fix: repeat the operation until the page’s own completion signal appears or its height stops changing; enforce a maximum number of passes.

A full-page image was expected, but only one screen was saved

  • Cause: save_screenshot is a current-window/viewport API.
  • Fix: use Firefox’s save_full_page_screenshot where that browser-specific capability fits, or design a multi-capture workflow when separate viewport images are acceptable.

The screenshot file cannot be opened

  • Cause: the path is unwritable, the process lacks permission, or the file was overwritten by another iteration.
  • Fix: write to a known writable directory and give each capture a unique name. Check the Boolean result returned by Selenium’s file-saving method where applicable.

Practical choices for repeatable captures

Set the viewport deliberately

Screenshot dimensions depend on the browser window and device configuration. Keep those settings consistent across runs when comparing images. A capture at one viewport size cannot be compared pixel-for-pixel with a capture at another size without accounting for the difference.

Keep scroll and capture in one transaction

Navigate, wait for the required state, scroll, and save without unrelated actions between the final two commands. This reduces the chance that an animation, redirect, or script changes the viewport before the image is written.

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

Use stable selectors

For element captures, prefer a selector intended for automation over a fragile position-based path. If the element is absent, fail the test clearly rather than saving an unrelated viewport and treating it as a successful capture.

Plan output names and retention

For multiple scroll positions, include the target or sequence number in each filename. Keep the browser cleanup in a finally block so a failed assertion does not leave WebDriver processes running.

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 provides a website screenshot API and MCP server. One request can capture a URL without you installing or controlling a Selenium browser:

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

See the ScreenshotNeo API documentation for request options. The equivalent Python and Node.js calls are:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

For this use case, the relevant options include full-page capture with lazy images loaded, selecting one element by CSS selector, dark mode, device presets or a custom viewport, retina scale, custom CSS and JavaScript, click-before-capture actions, waits for a selector, delay or network idle, and blocking ads, trackers, requests or resource types. You can also set headers, cookies, user agents, Authorization, timezone and geolocation; resize images; choose a cache TTL; create signed links; submit asynchronous jobs with signed webhooks; capture up to 100 URLs per bulk call; and query usage through the API. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

ScreenshotNeo removes cookie/consent banners, newsletter popups and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed as clean shots, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

Plan Included shots Price
Free 1,000 per month $0, no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Yearly billing gives two months free, and every feature is available on every plan. Sign up for ScreenshotNeo to get 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000.

FAQ

Can I restore the original scroll position after a capture?

Yes. Execute a second script such as window.scrollTo(0, 0) after saving, or record the position before the capture and restore that value when the test needs to continue from the same location.

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.

Can one Selenium run save several scroll positions?

Yes. Perform a scroll or element alignment, save a uniquely named file, then move to the next position and repeat. Treat each image as a separate viewport capture.

Why might two captures of the same URL differ?

Viewport dimensions, asynchronous content, animations, ads, and changing page data can alter the rendered result. Keep the browser configuration stable and wait for the specific application state required by your test.

Frequently Asked Questions

Can I restore the original scroll position after a capture?

Yes. Execute a second script such as window.scrollTo(0, 0) after saving, or record the position before the capture and restore that value when the test needs to continue from the same location.

Can one Selenium run save several scroll positions?

Yes. Perform a scroll or element alignment, save a uniquely named file, then move to the next position and repeat. Treat each image as a separate viewport capture.

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

Why might two captures of the same URL differ?

Viewport dimensions, asynchronous content, animations, ads, and changing page data can alter the rendered result. Keep the browser configuration stable and wait for the specific application state required by your test.

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.