To capture lazy-loaded content with Selenium, scroll the page—or the nested element that actually scrolls—until the content has loaded, wait for a page-specific condition, and then take the screenshot. A successful navigation or document.readyState check alone does not guarantee that JavaScript-driven content is ready.
Why a Selenium screenshot can miss content
Many pages defer loading images, cards, or other content until the relevant area approaches the viewport. Infinite-scroll pages may fetch more items only after a scroll. Selenium can wait for document readiness, but that is not the same as waiting for an application’s asynchronous content. Selenium’s browser-options documentation cautions that a page may not have finished loading when the ready state returns complete, especially in single-page applications: Browser Options.
As an Amazon Associate I earn from qualifying purchases.
The key is to trigger the page’s loading behavior, then wait for an observable sign that the content you need is ready. The correct scroll target and completion condition depend on the site.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesReliable workflow
- Identify what needs to appear. Choose a target element, a count of cards, an image, or the page’s loading indicator. Inspect the page to determine whether scrolling happens on the window or inside a nested container.
- Navigate and wait for initial structure. Use an explicit wait for a useful starting condition, such as the target list being present. Do not treat navigation returning or
document.readyStatebecoming complete as proof that lazy content is ready. See Selenium’s Waiting Strategies. - Scroll in increments. Scroll the window or the identified inner container. Incremental scrolling gives viewport-triggered loading opportunities as the relevant area approaches view.
- Wait for meaningful progress. After a scroll, wait for the desired element to become visible, the item count to increase, an image to finish loading, or a loading indicator to disappear. Prefer such a condition to an arbitrary fixed sleep.
- Stop deliberately. For infinite scroll, stop when the target content exists, the page reaches a known boundary, or repeated attempts produce no new items. Selenium provides the script execution and wait mechanisms; it does not prescribe a universal lazy-loading loop.
- Capture and inspect. Take the screenshot only after the relevant condition is satisfied. Check the saved image for missing content, clipping, or a page that stopped loading earlier than expected.
Python example: scroll the page and wait for the target
This runnable pattern uses Selenium’s Python binding. Replace the URL and CSS selector with those for the page. It scrolls the window in steps and waits for the target element to become visible after each step. If your site uses a nested scrolling container or infinite scroll without a stable target, adapt the scroll and wait condition as described below.
#1 Best Overall
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
url = "https://example.com/page"
target_selector = "#content-loaded-below-fold"
options = webdriver.ChromeOptions()
# Uncomment to run without opening a browser window:
# options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
try:
driver.get(url)
# Wait for initial page structure, not for every deferred resource.
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "body")))
target = None
max_scrolls = 30
step_px = 700
for _ in range(max_scrolls):
# Scroll the window down by one step.
driver.execute_script("window.scrollBy(0, arguments[0]);", step_px)
try:
target = WebDriverWait(driver, 3).until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR, target_selector)
)
)
break
except TimeoutException:
# The target may need another scroll to approach the viewport.
continue
if target is None:
raise TimeoutException(
f"Target did not become visible after {max_scrolls} scrolls: "
f"{target_selector}"
)
# Capture the current browser viewport as a PNG.
driver.save_screenshot("lazy-page.png")
finally:
driver.quit()
The loop has a maximum number of scrolls so it cannot run forever. Its short per-step wait is a practical bound, not a claim that the page will always load in that time; adjust the wait to the page and environment. For a more reliable implementation, wait for the actual content-change signal that the page exposes.
Wait for an item count to increase
If each scroll appends items, capture the current count before scrolling and wait until it increases. This is often more useful than waiting for a particular item when you do not know how far down it will appear. For example, use a CSS selector for the repeated cards and a condition that checks whether find_elements returns more elements than the prior count.
Rank #2
Wait for an image to finish loading
If the content element exists but its image is still loading, wait on that image’s DOM state, such as its complete property and a nonzero naturalWidth. An element being present in the DOM does not by itself prove that its image has rendered successfully.
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 & 11Scrolling a nested container
Some pages keep the main document still while a panel or feed scrolls internally. Scrolling window will not trigger that panel’s lazy loading. Find the element whose scrollHeight exceeds its clientHeight, then scroll that element in the page context. Selenium supports JavaScript execution in the currently selected frame or window; see the JavaScript WebDriver API.
Rank #3
container = driver.find_element(By.CSS_SELECTOR, "#scrolling-feed")
driver.execute_script(
"arguments[0].scrollTop = arguments[0].scrollTop + arguments[1];",
container,
600,
)
Use the same approach of checking for a target or meaningful content change after each increment. If the scrollable element is inside an iframe, switch to that frame before locating and scrolling it.
Choose the screenshot scope you need
driver.save_screenshot() captures the current browser screenshot. A WebElement screenshot captures the region within that element’s bounding rectangle; it should not be assumed to capture an entire long page. Selenium’s WebElement API documents the element screenshot scope.
Rank #4
- Used Book in Good Condition
Full-page capture support and behavior depend on the Selenium binding and driver. For example, Selenium’s Ruby screenshot API makes full-page capture conditional on support: TakesScreenshot. Check the API for the binding and driver you actually use, and inspect the result rather than assuming a viewport screenshot includes everything below the fold.
Recommended Free Tools
Common problems and fixes
- Screenshot taken immediately after navigation: navigation readiness does not imply that client-side content has appeared. Add an explicit wait for the target or another page-specific condition.
- Scrolling does not load anything: the page may use a nested scroll container, an iframe, or a different trigger. Identify the actual scrolling element and execute the scroll in the correct frame.
- The target never becomes visible: confirm the selector matches the intended element, check whether it is hidden behind a collapsed section, and verify that the page has not stopped at a consent dialog or other overlay.
- Repeated scrolling produces no new items: the page may have reached its boundary, the site may require a different trigger, or loading may have failed. Use a practical stop limit and check the page’s own loading state rather than looping indefinitely.
- Element appears but image is blank: wait for the image itself to load and verify its dimensions; presence of the containing card is not enough.
- Full-page output is clipped or unavailable: confirm that the binding and driver support the full-page method you selected. Otherwise, capture the required region in a supported way or use viewport captures after scrolling.
- Fixed delays work inconsistently: network and application timing vary. Replace sleeps as the sole readiness test with explicit waits for a target, count change, image completion, or disappearance of a loading indicator.
Or skip the browser setup
For a one-call capture, ScreenshotNeo accepts a URL and returns an image or PDF. For this page, use:
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/page -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets; these steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status. Its MCP server gives AI agents tools for taking screenshots, getting page information, and capturing PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for the free plan.
Frequently Asked Questions
Can Selenium guarantee that every lazy-loaded item has appeared?
No. Selenium supplies scrolling, script execution, waits, and screenshot commands; the site determines when and how it loads content. Your automation needs a page-specific stopping condition.
Does a WebElement screenshot capture the whole page?
No. It captures the visible region inside the element’s bounding rectangle. Use a supported full-page method or another capture approach if you need more than that region.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
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.




