ScreenshotNeo

BlogHow-to

How to Capture a Selenium Screenshot at a Specific Scroll Position

Scroll to document coordinates with Selenium, wait for dynamic content to settle, then capture the viewport. Includes Python, cURL, Node.js, troubleshooting, and a no-browser option.

By the ScreenshotNeo team4 October 20267 min read

To capture a Selenium screenshot at a specific scroll position, scroll the page to the desired document coordinates and then save a normal window screenshot. In Python:

driver.execute_script("window.scrollTo(0, 1200)")
driver.save_screenshot("page.png")

The second argument is the vertical offset in CSS pixels; the first is the horizontal offset. A normal window screenshot captures the viewport at that position, not the entire page. Selenium’s WebDriver screenshot operation captures the current browsing context, and its Python API provides methods to save that screenshot to a file or return its bytes. Selenium window and screenshot documentation · Selenium Python WebDriver API.

Python: scroll, wait, and capture

This runnable example assumes the target page and its content are available after navigation. Install Selenium with python -m pip install selenium; configure a browser driver using the setup guidance for your Selenium version and browser.

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

url = "https://example.com"
x = 0       # horizontal CSS-pixel offset
 y = 1200   # vertical CSS-pixel offset

options = webdriver.ChromeOptions()
# Uncomment for a headless run:
# options.add_argument("--headless=new")

driver = webdriver.Chrome(options=options)
try:
    driver.get(url)

    # Scroll to the requested document coordinates.
    driver.execute_script("window.scrollTo(arguments[0], arguments[1])", x, y)

    # Wait for the browser to reach the requested position. This is a
    # condition-based wait; it does not assume a fixed page load duration.
    WebDriverWait(driver, 10).until(
        lambda d: d.execute_script("return window.scrollX") == x
        and d.execute_script("return window.scrollY") == y
    )

    driver.save_screenshot("page.png")
finally:
    driver.quit()

In the code, remove the accidental leading space before y = 1200 if copying from a formatter that preserves it; the assignment should be at the same indentation level as x. Browsers may clamp a requested offset near the document’s end, so exact equality can fail when the page is shorter than the requested position. For a general-purpose capture, wait for the actual settled position or use a bounded check:

requested_y = 1200
driver.execute_script("window.scrollTo(0, arguments[0])", requested_y)
WebDriverWait(driver, 10).until(
    lambda d: d.execute_script("return window.scrollY") >= requested_y
    or d.execute_script("return window.scrollY") == d.execute_script(
        "return document.documentElement.scrollHeight - window.innerHeight"
    )
)

The page may change height as images, fonts, or client-rendered sections load. If that changes the reachable position, wait for the relevant content or layout condition before capturing rather than relying on a fixed sleep.

Choose the screenshot area

Need Use What it captures
The page as seen at the chosen scroll position Window screenshot The current viewport in the browsing context
One particular element Element screenshot The visible bounds covered by that element’s bounding rectangle
The whole document Full-page capture where supported by your browser and setup A full-page image, rather than only the current viewport

For a viewport image, scroll first and call driver.save_screenshot(). For a specific element, locate it and call its screenshot method; that is a different output target from the viewport. Selenium documents element screenshots as covering the visible region of the element’s bounding rectangle. See the Selenium WebDriver documentation.

Coordinate and timing details

  • Coordinates are CSS pixels. Browser zoom, device scale, and screenshot pixel dimensions can differ; do not assume the scroll offset is a physical image-pixel coordinate.
  • Horizontal position: pass a nonzero x value to window.scrollTo(x, y) when the page is horizontally scrolled.
  • Document versus element scrolling: window.scrollTo scrolls the document viewport. For a scrollable panel, scroll that element instead, for example arguments[0].scrollTop = 500 after locating it.
  • Lazy content: some pages load images or sections only when they approach the viewport. Scroll to the target, wait for the content you need to appear and settle, then capture.
  • Sticky headers: a fixed header remains over the viewport after scrolling. If it obscures the desired content, use a different offset or a page-specific approach; do not assume scrolling removes overlays.
  • Nested frames: switch to the relevant iframe before interacting with its document. Coordinates in a frame are relative to that frame’s viewport.
  • Reduced motion: pages with smooth scrolling may not reach the target immediately. Wait until the scroll position meets a condition before saving.

Selenium IDE’s FAQ demonstrates coordinate scrolling with window.scrollTo(0,1000). Selenium’s troubleshooting guidance also covers scrolling when elements are out of view or overlapped and using waits when interaction depends on timing. Selenium IDE FAQ · Selenium troubleshooting.

Other runnable bindings

JavaScript with Selenium WebDriver

Install the JavaScript package with npm install selenium-webdriver and configure the browser driver as required for your environment.

const { Builder, By, until } = require('selenium-webdriver');

(async () => {
  const driver = await new Builder().forBrowser('chrome').build();
  try {
    await driver.get('https://example.com');
    await driver.executeScript('window.scrollTo(arguments[0], arguments[1])', 0, 1200);
    await driver.wait(async () => {
      const y = await driver.executeScript('return window.scrollY');
      return y >= 1200;
    }, 10000);
    const png = await driver.takeScreenshot();
    require('fs').writeFileSync('page.png', Buffer.from(png, 'base64'));
  } finally {
    await driver.quit();
  }
})();

For a page that may be shorter than the requested offset, wait for either the requested position or the document’s maximum scroll position, as in the Python example. Selenium API names vary by language binding; consult the official examples for your binding.

cURL and Python requests

cURL and requests do not control a Selenium browser or scroll a live document. They fetch HTTP responses, which is not equivalent to rendering a page and capturing its viewport. If a rendered screenshot is the goal and browser setup is unnecessary, use the ScreenshotNeo call below.

Or skip the browser setup

ScreenshotNeo captures a URL with one API request and supports image output including WebP, PNG, and JPEG. The basic call captures the page; it does not expose a requested Selenium scroll coordinate in the supplied product facts.

ScreenshotNeo API documentation

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the shot was billed. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Learn more at ScreenshotNeo and the API docs, then sign up for 1,000 free screenshots a month, with no card.

Troubleshooting

Symptom Likely cause Fix
Screenshot shows the top of the page The scroll command ran before navigation completed, targeted the wrong browsing context, or a later script reset the position. Scroll after navigation and any relevant page update; wait for the actual scroll position just before saving.
Requested position is never reached The page is shorter than the requested offset, the browser clamps the scroll, or the page is still changing height. Check document.documentElement.scrollHeight and window.innerHeight; wait for content, or treat the maximum scroll position as the settled result.
Capture misses content that appears on scroll Lazy-loaded content has not rendered or loaded yet. Wait for the target element or image to be present and visible, and for any relevant loading state to finish.
Wrong area moves while scrolling The target is inside a scrollable container or iframe rather than the top-level document. Switch into the frame if needed, or set the scroll position on the specific container element.
Content is hidden behind a header or overlay A sticky header, modal, or consent layer covers the viewport. Account for the overlay in the chosen position or handle it through the page’s UI before capture.
Screenshot file is missing or empty Capture failed, the process exited early, or the output path is not where expected. Check the return value from save_screenshot, use an explicit path, and keep the browser open until the file is written.
WebDriver cannot start Browser/driver setup or version configuration is incomplete. Follow the Selenium setup instructions for the installed browser and binding, then confirm the browser launches independently.

Performance, reliability, and cost

Each Selenium capture requires a browser session and page navigation, so reuse a driver for a sequence of captures when appropriate and close it reliably in a finally block. Avoid arbitrary long sleeps: wait for the actual content or position the screenshot depends on. For reproducibility, use the same viewport, browser configuration, URL state, and wait conditions across runs. Dynamic advertisements, timestamps, rotating content, and network delays can still make otherwise identical captures differ.

Selenium itself is browser automation software; any browser compute and infrastructure costs depend on where and how you run it. ScreenshotNeo uses usage plans: Free is 1,000 shots per month; Starter is $5 for 3,000; Growth $15 for 15,000; Pro $39 for 60,000; Scale $99 for 250,000; and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. These are the supplied plan terms; check the product site for current details before choosing.

FAQ

How do I scroll?

Run JavaScript in the active page context, such as window.scrollTo(0, 1200), then capture the current window. Use element or container scrolling when the content has its own scroll area.

Does a normal Selenium screenshot include the whole page?

The standard window screenshot is the current viewport. Full-page capture is a separate capability whose support depends on the browser and setup.

Can I capture the element at that position instead?

Yes. Scroll it into the desired visible location and use the element screenshot method when the output should be limited to that element’s visible bounds.

Why is a condition wait better than a fixed delay?

A condition wait continues as soon as the required position or content is ready, while a fixed delay can be too short on a slow run and unnecessarily long on a fast one.