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.

To capture an element below the fold with Selenium, locate it, scroll it into view, then call WebElement.screenshot(). An element can exist in the DOM while outside the viewport; that is different from an element hidden with display:none or one that has been removed. For the whole document rather than one node, use a full-page method supported by your browser driver—Firefox’s Python driver documents explicit full-document screenshot methods.

Choose the screenshot you actually need

There are two different tasks that are easy to confuse:

  • One element: Capture a particular node, such as a result card, chart, or dialog. Selenium’s WebElement.screenshot() saves an element screenshot as a PNG.
  • The document: Capture the whole scrollable page, including content below the current viewport. This requires a full-page capture method supported by the driver; an ordinary current-window screenshot is not the same thing.

Playwright’s documentation makes the same distinction: its full-page screenshot means capturing the full scrollable page, while element screenshots are documented separately. Use the element method when the test artifact should contain only the target. Use a full-page method when the page layout as a whole is what you need to inspect.

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

Capture an off-screen element with Selenium in Python

For an element outside the current viewport, Selenium’s Python API documents location_once_scrolled_into_view as causing the element to be scrolled into view. Read that property before taking the element screenshot. Here is a runnable example for a page whose target matches article.result:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

url = "https://example.com/results"
driver = webdriver.Chrome()

try:
    driver.get(url)
    card = driver.find_element(By.CSS_SELECTOR, "article.result")

    if not card.is_displayed():
        raise RuntimeError("The result element is not displayed")

    # Selenium documents this property as causing the element to be
    # scrolled into view.
    _ = card.location_once_scrolled_into_view
    card.screenshot("result-card.png")
finally:
    driver.quit()

Replace the URL and selector with values for your page. This example uses Chrome for ordinary navigation and element capture; it does not claim to capture the entire document. The Selenium API describes the element screenshot as saving the current element to a PNG image file.

Why check visibility?

find_element() answers whether Selenium can locate a matching node. It does not, by itself, tell you that a person could currently see it. Selenium’s is_displayed() is the API to check displayed state when that distinction matters. An off-screen element may still be displayed, whereas a hidden or detached element is a different case. If the check fails, first verify that you selected the intended node and that the page has finished rendering it; scrolling cannot make a hidden or missing node visible.

Alternative scroll alignment for sticky headers

If scrolling the target to the viewport edge leaves it under a sticky header, a practical JavaScript pattern is to center it before capture:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
driver.execute_script(
    "arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});",
    card,
)
card.screenshot("result-card.png")

This is a practical positioning pattern, not a guarantee in Selenium’s API that a site’s overlays will disappear or that every browser will render the page identically. Inspect the resulting image when the exact visible framing matters.

Choose the output format that fits your test

Selenium’s element screenshot API offers file, byte, and base64 forms. Use the file form for a test artifact that should be written directly to disk. Use PNG bytes when another part of a Python image pipeline should consume the capture, or base64 when the receiving system expects encoded image data.

# Save directly as a PNG file
card.screenshot("result-card.png")

# Get PNG bytes
png_bytes = card.screenshot_as_png

# Get a base64-encoded PNG string
png_base64 = card.screenshot_as_base64

The Firefox Python API documents corresponding full-document screenshot forms as well as saving a full-document PNG to a file. The exact output method you choose should match what consumes the result; avoid converting to base64 simply to save a local file.

Capture the full page in Firefox

If the requirement is a full document rather than one element, Firefox’s Python driver exposes full-page screenshot methods. For example:

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

url = "https://example.com/results"
driver = webdriver.Firefox()

try:
    driver.get(url)
    driver.save_full_page_screenshot("page.png")
finally:
    driver.quit()

save_full_page_screenshot() is documented as saving a full-document screenshot of the current window to a PNG image file. The Firefox API also documents get_full_page_screenshot_as_file and PNG/base64 variants. Check the API documentation for the driver version you use before relying on a specific method name or return form.

Do not assume all browser drivers expose identical full-page APIs. Chromium’s documented screenshot options include current-window capture and WebDriver BiDi browsing-context capture; that is not evidence of universal full-page parity across drivers. If you need a full document, choose a method documented for your browser and validate the output against a long page with content below the fold.

Handle nested scroll containers, iframes, and tabs

Element inside an independently scrolling panel

A page can have a scrollable panel inside the window. Scrolling the window does not necessarily move that panel’s contents. If the node is inside a nested scroller, scroll the owning container or otherwise bring the node into view within that container, then capture the element. If the page-level scroll seems to do nothing, inspect the layout for an independently scrolling ancestor instead of repeating the window scroll.

Element inside an iframe

An iframe is a separate browsing context. Switch into the frame before locating the element, then switch back to the parent document when finished:

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

frame = driver.find_element(By.CSS_SELECTOR, "iframe#results-frame")
driver.switch_to.frame(frame)
try:
    card = driver.find_element(By.CSS_SELECTOR, "article.result")
    _ = card.location_once_scrolled_into_view
    card.screenshot("framed-result.png")
finally:
    driver.switch_to.parent_frame()

Use a selector that identifies the actual iframe on the page. If frames are nested, switch through the frame hierarchy to the one containing the target. Selenium’s Chromium API documents frame switching, including parent_frame() and default_content(); use the appropriate context-switch operation for your binding.

Element in another window or tab

Switch to the correct window before searching for the node. A locator run in the wrong tab cannot find an element that belongs to another browsing context. Selenium’s Chromium API documents switch_to.window(...) alongside frame-context operations. After the capture, switch back if later test steps depend on the original window.

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

Common failures and practical fixes

  • No such element: The selector may not match, the node may not have been added yet, or you may be in the wrong frame or window. Confirm the selector and browsing context, then wait for the page’s own rendering behavior before locating it.
  • Element is found but the screenshot fails or is empty: Check whether it is displayed and attached, and whether it is inside an iframe. Scroll it into view before using the element screenshot API.
  • Window scroll does not reveal the target: Look for a nested, independently scrolling container and scroll the element’s owning panel instead.
  • Target is obscured after scrolling: Try centering it with scrollIntoView({block: 'center', inline: 'nearest'}), then inspect the capture. The screenshot APIs do not promise that sticky headers, cookie banners, or other overlays will be removed.
  • Capture contains only the visible window: You likely used a viewport/current-window screenshot while expecting the full document. Use a full-page method documented for the driver in use; Firefox’s Python API documents explicit full-document methods.
  • Wrong image representation: Use the file method for a PNG artifact, the bytes property for binary processing, or the base64 property for a consumer that specifically expects encoded text.

Performance, reliability, and cost considerations

Element capture avoids asking for a full-document image when the test only needs one node. Full-page capture is more appropriate for document-wide review, but the available API and behavior depend on the driver. There are no numeric performance or cross-browser coverage figures established here, so treat capture duration and rendering behavior as properties to verify in your own browser, page, and CI environment rather than assuming a universal benchmark.

For repeatable artifacts, capture only after the page has reached the state your test intends to verify. A screenshot taken before asynchronous content appears can be a valid image of the wrong state. Where timing is variable, have the test wait for a meaningful page condition before capturing. Keep the selector stable, and preserve the screenshot as a test artifact if it will be used to diagnose failures.

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

Or skip the browser setup

If you need a website screenshot without maintaining a WebDriver session, ScreenshotNeo is a screenshot API with an MCP server. Its URL-based API can return PNG, JPEG, WebP, or PDF; separate options include full-page capture and capture of one element by CSS selector. A URL capture does not replace Selenium when you need to interact with an already-running browser session or test application state.

One-call cURL example for a URL screenshot:

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. Before capture, it can accept cookie/consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify page verdict and billing status in headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

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.