Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesSome 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.
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:
#1 Best Overall
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.
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.
Rank #2
| 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.
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
- Navigate to the page.
- Perform any application-specific readiness check your test already uses.
- Scroll to the bottom or to the target element.
- 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.
- 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.
Rank #3
Java equivalent
The same concepts are available in Selenium Java through JavascriptExecutor and TakesScreenshot:
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_scriptimmediately beforesave_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_screenshotis a current-window/viewport API. - Fix: use Firefox’s
save_full_page_screenshotwhere 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.
Recommended Free Tools
Rank #4
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.
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:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC 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 & 11import 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.
Best Value
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.
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.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →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.
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.

