ScreenshotNeo

BlogGuides

Puppeteer Mouse Wheel Options Explained

Learn what Puppeteer’s mouse wheel options do, how to position the pointer, and how to verify whether a wheel event actually scrolled the page.

By the ScreenshotNeo team4 October 20267 min read

page.mouse.wheel() sends wheel input through Puppeteer’s mouse. Its documented options are optional numeric deltaX and deltaY values. A wheel event does not guarantee that content scrolls: the pointer must be over the intended region, and the page may handle, cancel, or reinterpret the input as zoom.

This guide covers the API, runnable examples, pointer positioning, verification, common failures, and practical limits. Puppeteer’s API reference documents the method signature and says it dispatches a mousewheel event; its options reference lists the two optional numbers without documenting defaults. See the Puppeteer Mouse.wheel() reference and MouseWheelOptions reference.

1. What the wheel options mean

Option Type Practical use
deltaX Optional number Horizontal wheel input.
deltaY Optional number Vertical wheel input.

The interface reference identifies each property as an optional number, but does not specify a default. Pass the delta you need explicitly rather than depending on an assumed default.

For example, a positive or negative delta expresses wheel input in a direction; the browser and page determine what that input does. A negative deltaY appears in Puppeteer’s own zoom example, but no value guarantees a fixed scroll distance. Treat the values as input, not as a measurement of the resulting content movement.

2. Minimal runnable example

Install Puppeteer in a Node.js project with npm install puppeteer. Save this as wheel.js and run node wheel.js. Puppeteer launches its managed browser, opens a page, sends vertical wheel input, and closes the browser.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    await page.mouse.wheel({ deltaY: 100 });
  } finally {
    await browser.close();
  }
})();

This demonstrates the call shape. A short page such as example.com may have nowhere to scroll, so the event can be sent without visible movement. For a real target, wait for the relevant content and position the pointer over its scrollable area.

3. Position the pointer over the target

Wheel input is delivered at the mouse’s current position. Puppeteer’s documented example gets an element’s bounding box, moves the pointer to its center, and then sends wheel input. Coordinates are main-frame CSS pixels relative to the viewport’s top-left. The API’s mouse events are synthetic and do not reproduce every detail of a physical mouse.

const target = await page.$('#results');
if (!target) {
  throw new Error('Could not find #results');
}

const box = await target.boundingBox();
if (!box) {
  throw new Error('#results is not visible in the layout');
}

await page.mouse.move(
  box.x + box.width / 2,
  box.y + box.height / 2
);
await page.mouse.wheel({ deltaY: 250 });

Use a selector for the region that should receive the input. If the page has nested scroll containers, hovering over the intended container matters: the page may scroll a different ancestor, or none at all.

4. Horizontal, vertical, and combined input

Pass deltaY for vertical input and deltaX for horizontal input. You can provide both when the interaction calls for diagonal input.

// Vertical wheel input
await page.mouse.wheel({ deltaY: 300 });

// Horizontal wheel input
await page.mouse.wheel({ deltaX: 180 });

// Both components
await page.mouse.wheel({ deltaX: 80, deltaY: 160 });

These examples show requested input values only. Page event handlers, browser behavior, zoom settings, scroll boundaries, and the layout can all affect the outcome. Do not infer actual direction or distance from the delta alone.

5. Verify whether the page actually scrolled

A wheel event and a scroll event are different. A wheel event may not scroll anything, and scrolling can also happen without a wheel event—for example, through keyboard input or JavaScript. To test content movement, observe scrollTop or scrollLeft on the relevant element.

const initial = await page.$eval('#results', element => ({
  top: element.scrollTop,
  left: element.scrollLeft,
}));

const target = await page.$('#results');
const box = await target.boundingBox();
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.wheel({ deltaY: 250 });

await page.waitForFunction(() => {
  const element = document.querySelector('#results');
  return element && element.scrollTop !== 0;
}, { timeout: 2000 }).catch(() => {});

const final = await page.$eval('#results', element => ({
  top: element.scrollTop,
  left: element.scrollLeft,
}));
console.log({ initial, final });

For a reusable check, compare the values before and after and assert the change your test expects. The example’s wait condition assumes a starting scrollTop of zero; if the element may already be scrolled, compare against initial.top instead. For the main document, inspect document.scrollingElement. See MDN’s guidance on the wheel event.

6. Event handling and cancellation

The page can register a wheel handler that changes application state, cancels the event, or uses it for zoom. A canceled wheel event does not perform the browser’s default scroll or zoom action. Some browsers may make only the first event in a sequence cancelable; passive listeners can also affect whether the browser waits for a handler before scrolling. These details are page and browser behavior, not extra Puppeteer wheel options.

If the application intentionally handles wheel input, test the application’s resulting state or scroll position rather than assuming the browser’s default action will occur.

7. Troubleshooting

Symptom Likely cause What to check
The call resolves but the page does not move. A wheel event is not proof of scrolling; the page may be at its boundary, unscrollable, or handling the event. Check the intended element’s scrollTop/scrollLeft, scroll range, and wheel handlers.
The wrong region scrolls. The pointer is over a different element or nested scroll container. Move to the target element’s bounding-box center and confirm its coordinates are in the viewport.
The page zooms instead of scrolling. The page or browser interprets wheel input as zoom. Inspect page handlers and browser zoom behavior; verify scroll offsets rather than judging by the event delta.
boundingBox() returns null. The element is detached or has no layout box, often because it is hidden. Wait for the element, verify it is visible, and reacquire it after navigation or DOM replacement.
The test is flaky near the bottom or top. The element has reached a scroll boundary, or asynchronous content changes its scroll range. Record the starting offset, wait for content readiness, and assert a bounded expected change rather than a fixed distance.
A wheel listener runs but default scrolling does not. The handler may cancel the event, or application code may own the interaction. Inspect the handler and whether it calls preventDefault(); validate the application state it is meant to update.

8. Reliability, performance, and cost

page.mouse.wheel() is a single input dispatch, not a guarantee that the target has finished loading or that an animation has completed. For reliable automation, wait for the target element and relevant content first, send input while the pointer is over the correct region, then wait for an observable result such as a changed scroll offset or newly rendered content. Avoid fixed sleeps when a state-based wait is available.

Large deltas and rapid repeated calls can produce outcomes that depend on the page’s handlers and browser behavior. Use the smallest input sequence that matches the user interaction you need to model, and assert the resulting state. The dossier provides no benchmark or fixed throughput figure for wheel input; performance depends on the browser, page work, and waits in the surrounding script.

For cost, Puppeteer itself is an open-source browser automation library; the actual runtime costs depend on where and how you run the browser. The API documentation and event references cited here do not establish a universal hosting price.

9. Or skip the browser setup

If your goal is to capture a page image or PDF rather than automate wheel interaction, ScreenshotNeo provides a website screenshot API and MCP server. Its API documentation covers the available capture options. Here is a one-request example:

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}`);
await import('node:fs/promises').then(fs => 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 step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Every feature is on every plan.

Sign up free for 1,000 screenshots a month, with no card required.

10. FAQ

Does page.mouse.wheel() return the new scroll position?

No. The method returns a promise for completion of the input dispatch. Read the relevant element’s scroll offset separately.

Can wheel input trigger browser zoom?

It can, depending on browser and page behavior. Puppeteer’s documented example uses a negative vertical delta for a zoom demonstration, which is a reminder that wheel input does not mean scrolling in every context.

Are the wheel deltas pixels of guaranteed scrolling?

No. They are input values; the actual page result can differ or be absent.

Can Puppeteer wheel outside the main page?

The Mouse API describes coordinates in main-frame CSS pixels relative to the viewport. The method is intended for page mouse input, not a guarantee of operating-system-level pointer behavior.