Puppeteer Locator Scroll Options Explained
Learn what Puppeteer's LocatorScrollOptions exposes, when to call locator.scroll(), and how automatic viewport handling differs.
Direct answer: Puppeteer’s LocatorScrollOptions exposes two optional numeric properties: scrollLeft and scrollTop. Pass an options object to locator.scroll(options) when your code needs an explicit locator scroll operation. For ordinary locator actions on an offscreen element, Puppeteer separately ensures the element is in the viewport by default, so a manual scroll call is often unnecessary.
The current reference pages can show different versions. The interface fields are documented in the Puppeteer 25.4.0 reference; related locator and handle APIs have their own versioned references. Check the version installed in your project before relying on a detail. See the LocatorScrollOptions reference, Locator.scroll() reference, and viewport handling reference.
1. What the scroll options mean
LocatorScrollOptions extends ActionOptions. In the 25.4.0 interface reference, it contains:
| Property | Type | Documented meaning |
|---|---|---|
scrollLeft |
number (optional) |
A horizontal scroll option. |
scrollTop |
number (optional) |
A vertical scroll option. |
The interface reference does not specify defaults, units, coordinate frame, or whether the numbers represent absolute positions or deltas. Treat them as numeric arguments and do not assume a particular final scroll position based on the number alone.
2. Runnable Puppeteer example
Install Puppeteer in a Node.js project with npm install puppeteer. Save this as an ES module, for example scroll.mjs, and run it with node scroll.mjs. Replace the URL and selector with a page and target you control.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({headless: true});
try {
const page = await browser.newPage();
await page.goto('https://example.com', {waitUntil: 'domcontentloaded'});
const target = page.locator('h1');
// Illustrative numeric argument only; the reference does not define
// whether 100 is an absolute position or a delta.
await target.scroll({scrollTop: 100});
console.log('Explicit locator scroll completed');
} finally {
await browser.close();
}
The scroll() method accepts an optional read-only options object and returns Promise<void>. Omitting the object is a valid documented call shape: await page.locator('h1').scroll(). The reference does not promise a particular result for a missing property, so verify behavior against the version you run when the exact position matters.
3. Explicit scrolling versus automatic viewport handling
These are related but distinct mechanisms:
| Mechanism | Use it when | What the docs establish |
|---|---|---|
locator.scroll(options) |
You explicitly want to invoke the locator scroll operation. | Accepts optional LocatorScrollOptions; resolves to void. |
locator.setEnsureElementIsInTheViewport(value) |
You want to configure whether locator actions prepare the target for viewport interaction. | Returns a cloned locator. The default is true, which scrolls the element into the viewport if it is not already there. |
elementHandle.scrollIntoView() |
You are already using an element handle and need its into-view method. | It scrolls the element into view through the automation protocol client or an element scrollIntoView() call. |
For a click on an offscreen locator, let the default viewport preparation do its job:
const button = page.locator('button.save');
await button.click();
To turn the automatic behavior off for a locator, use the cloned locator returned by the configuration method:
const buttonWithoutAutoScroll = page
.locator('button.save')
.setEnsureElementIsInTheViewport(false);
await buttonWithoutAutoScroll.click();
Setting this to false means the locator is not configured to scroll the element into view when needed. If the action requires a visible, interactable target, it may then fail; use the default unless you have a reason to control viewport preparation yourself.
4. Selecting the target locator
Create a locator with page.locator(selector). CSS selectors work directly. Puppeteer’s selector syntax also supports text, accessibility role and name, XPath, and combinations that cross shadow roots. Prefer a selector that uniquely identifies the intended element and remains stable across page changes.
// CSS selector
const save = page.locator('[data-testid="save"]');
// Other supported selector forms depend on Puppeteer's selector syntax.
// Check the selector guide for the exact syntax supported by your version.
Reference: Page.locator(). If multiple elements can match, refine the selector rather than assuming which match will be acted on.
5. Choosing the right method
- You need an element action such as click or fill: use a locator and keep the default ensure-in-viewport behavior.
- Your flow explicitly calls for locator scrolling: call
locator.scroll(options)and pass the documented numeric fields as needed. Do not infer undocumented coordinate semantics. - You already have an ElementHandle: use
scrollIntoView()when the intended behavior is specifically to bring that element into view. - You need an exact page or nested-container scroll position: the cited option reference alone is insufficient to define that behavior. Check the implementation and documentation for your exact installed version, then validate against the page’s scroll containers.
6. Edge cases and practical notes
- Nested scroll containers: the cited API references do not spell out detailed behavior for nested containers. A target can be within the browser viewport yet clipped by an inner scrolling panel. Reproduce the case in the target page and confirm which container moves.
- Horizontal scrolling:
scrollLeftis the horizontal option name, but the interface reference does not define coordinate semantics or outcomes. - Page layout changes: content may shift after fonts, images, or asynchronous components load. Wait for the relevant page state or target selector before interacting, then perform the locator action.
- Sticky headers and overlays: being in the viewport does not ensure the target is unobstructed. An overlay can still block a click; dismiss it or select the intended target after the page reaches the expected state.
- Version differences: the interface and related APIs may be shown under different current or archived documentation versions. Pin and inspect the Puppeteer version your application actually uses.
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
scroll is not a function |
The value is not a Puppeteer Locator, or the installed version/API differs from the reference. | Confirm it came from page.locator(...) and inspect the installed Puppeteer version and its API reference. |
| The action times out or the target is not found | The selector does not match yet, is incorrect, or points to content not currently present. | Check the selector against the page, wait for the expected state, and use a stable selector. |
| Click works without an explicit scroll | This is expected when default viewport preparation brings the target into view. | Keep the automatic behavior if it meets the requirement; call scroll() only when the workflow needs an explicit scroll call. |
| Disabling viewport preparation makes an action fail | The target remains outside the usable viewport or is otherwise not interactable. | Use the default true setting, or arrange the page state before acting. |
| The page moves, but not to the position expected from the number | The reference does not define whether the number is a delta, absolute position, or what coordinate frame applies. | Do not derive an exact position from the type declaration. Consult version-specific implementation details and validate on the page. |
| The target is in view but the click is intercepted | A sticky element, modal, or overlay covers it. | Handle the overlay and then retry against the intended target; scrolling alone does not guarantee an unobstructed click. |
8. Performance, reliability, and cost
The documented scroll method is one awaited browser automation operation. The cited references publish no timing benchmarks or cost figures, so none should be inferred. For reliability, prefer locator actions and their default viewport handling for normal interactions, synchronize on the page state your task actually needs, use stable selectors, and avoid depending on undocumented numeric semantics. Close the browser in a finally block so exceptions do not leave a process running.
9. Or skip the browser setup
If the goal is a page screenshot rather than controlling a browser session, ScreenshotNeo is a website screenshot API and MCP server: one GET request returns an image or PDF. Its browser setup can be skipped for a straightforward capture.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo and get 1,000 screenshots a month free, with no card.
10. FAQ
Does LocatorScrollOptions include a behavior or alignment setting?
The referenced interface lists only the optional numeric fields scrollLeft and scrollTop.
Does scrollTop: 100 mean move down 100 pixels?
The cited interface does not establish units or whether the value is a position or delta. Do not assume it means 100 pixels of movement.
Should I call scroll() before every click?
No. Locator viewport preparation is enabled by default and brings an offscreen element into the viewport for locator actions.
Is scrollIntoView() the same API?
No. It is a separate ElementHandle method documented specifically for scrolling an element into view.
Which Puppeteer version should I follow?
Use the documentation matching your installed package. The cited interface page identifies version 25.4.0, while related API pages may display another version.


