ScreenshotNeo

BlogGuides

Puppeteer Locator Click Options Explained

Learn which options `page.locator(selector).click()` accepts, how inherited mouse settings work, and where to configure readiness, timeouts, and cancellation.

By the ScreenshotNeo team4 October 20268 min read

page.locator(selector).click(options) accepts a LocatorClickOptions object, defined as ClickOptions & ActionOptions. The useful options are count and delay for mouse behavior, offset and experimental debugHighlight for click position and debugging, and signal to abort the action. Locator readiness and timeout settings belong to locator methods, not to the click options object.

The Puppeteer API pages cited here cover versions 25.9.0 through 25.12.0. Check the documentation and TypeScript definitions for your installed version if an option differs.

What options does Puppeteer locator click accept?

The type relationship explains where each setting comes from:

LocatorClickOptions = ClickOptions & ActionOptions
ClickOptions extends MouseClickOptions
Option What it controls Default or behavior
count Number of clicks to perform 1
delay Time in milliseconds between mouse press and release Optional
offset Click point relative to the top-left of the element’s border box Optional
debugHighlight Temporarily highlights the click location for debugging Experimental; highlight lasts 10 seconds
signal Abort signal for the locator action Optional

debugHighlight may not work on every page, and its highlight does not persist across navigation. Treat it as a debugging aid, not a production guarantee. The signal field comes from ActionOptions, while the mouse settings come through ClickOptions.

Runnable JavaScript example

This CommonJS example starts a local HTTP server, opens it in Puppeteer, clicks a button twice with a press-to-release delay, and closes the browser and server. Install Puppeteer with npm install puppeteer, save as locator-click.cjs, then run node locator-click.cjs.

const http = require('node:http');
const puppeteer = require('puppeteer');

(async () => {
  const server = http.createServer((_req, res) => {
    res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
    res.end(`<!doctype html>
      <button id="target" onclick="this.dataset.clicks = Number(this.dataset.clicks || 0) + 1">
        Click me
      </button>`);
  });

  await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
  const address = server.address();
  const browser = await puppeteer.launch({ headless: true });

  try {
    const page = await browser.newPage();
    await page.goto(`http://127.0.0.1:${address.port}`);

    await page.locator('#target').click({ count: 2, delay: 100 });

    const clicks = await page.locator('#target').getProperty('dataset');
    console.log('Click action completed.');
    await clicks.dispose();
  } finally {
    await browser.close();
    await new Promise((resolve, reject) =>
      server.close((error) => error ? reject(error) : resolve())
    );
  }
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

The click options object can contain inherited fields alongside locator action settings such as an abort signal. For example, { count: 2, delay: 100, signal } is one object; a timeout is not another valid click field.

Double-click, delay, and click position

How do I double click with Puppeteer locator?

Set count: 2 to request two clicks:

await page.locator('button').click({ count: 2 });

The default count is one. Use the option for a double-click interaction when the page responds to repeated click events. Do not assume that every site treats two clicks as a double-click gesture; the page’s event handling determines the effect.

What does delay mean?

delay is the number of milliseconds between mouse press and release. It changes the duration of each mouse click; it is not a wait before Puppeteer starts the action.

await page.locator('button').click({ delay: 150 });

What does offset mean in Puppeteer click options?

offset specifies a point relative to the top-left of the element’s border box. Use it when the center is not the intended target, such as clicking a particular region inside a large element. The exact shape of the Offset value is versioned API detail, so use the type definitions for your installed Puppeteer release.

// The point object uses the Offset type from your installed Puppeteer version.
await page.locator('.canvas').click({ offset: { x: 20, y: 15 } });

Offsets can miss if the element changes size or layout between locating it and clicking. Prefer a stable, specific target where possible.

Abort a click with an AbortSignal

ActionOptions provides an optional signal. Aborting it cancels the locator action. This can be useful when a surrounding operation is cancelled or its deadline has passed.

const controller = new AbortController();
const clickPromise = page.locator('#submit').click({ signal: controller.signal });

// Elsewhere, when the action should be cancelled:
controller.abort();

try {
  await clickPromise;
} catch (error) {
  console.error('Locator click was cancelled or failed:', error);
}

In real code, connect the controller to the event that owns cancellation. Avoid aborting immediately after starting the action unless cancellation is the intended behavior.

Readiness and timeout are locator settings

Locator clicks handle readiness automatically. Puppeteer’s interaction guide describes the click as ensuring the element is in the viewport, waiting for visibility and enabled state, and waiting for a stable bounding box across two consecutive animation frames. If the action cannot proceed because the element is not ready, locator actions are retried.

These behaviors are not fields in click(options). Locator methods configure them. The following example deliberately disables several readiness checks; do this only when the changed waiting behavior is what you need:

const locator = page.locator('#submit')
  .setEnsureElementIsInTheViewport(false)
  .setVisibility(null)
  .setWaitForEnabled(false)
  .setWaitForStableBoundingBox(false);

await locator.click();

To set a timeout, use setTimeout(timeout). It returns a cloned locator with a total timeout for locator actions. By default, the timeout comes from Page.getDefaultTimeout(); passing 0 disables the timeout.

await page.locator('#submit').setTimeout(5000).click();

This is not equivalent to click({ timeout: 5000 }). Adding a timeout property to the click options object is not the documented way to configure locator action timeouts.

Locator.click versus Page.click

API Options type Behavior to keep in mind
page.locator(selector).click(options) LocatorClickOptions Locator interaction with readiness checks and retry behavior
page.click(selector, options) ClickOptions Scrolls into view if needed, clicks the center, and clicks the first match if several elements match

These APIs have different option types. Do not assume signal from LocatorClickOptions is accepted by Page.click; check that method’s signature. Prefer a locator when you want its readiness checks and retry behavior, and be specific about the target if a selector can match more than one element.

Navigation can race with a click if code waits for navigation only after clicking. Start both operations together:

await Promise.all([
  page.waitForNavigation(),
  page.locator('a.next-page').click(),
]);

ScreenshotNeo: inspect the result of an automated click

When a click succeeds but the rendered page still needs visual inspection, ScreenshotNeo is a website screenshot API and MCP server for developers. It can capture the resulting page as PNG, JPEG, WebP, or PDF. The API supports custom JavaScript, CSS, waits, viewport settings, and element capture, which can help capture a particular post-interaction state.

Or skip the browser setup

For a direct screenshot, make one request to the ScreenshotNeo API:

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 require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and each response reports the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.

Troubleshooting

Symptom Likely cause Fix
TypeScript rejects an option The installed Puppeteer typings differ from the API version in a guide, or the option belongs to another method. Check the API docs and type definitions matching the installed version. Confirm the receiver is a locator and that the field belongs to LocatorClickOptions.
timeout is reported as an unknown property Timeout was added to the click options object. Configure it with locator.setTimeout(milliseconds), then call click().
The element is not clickable or the action keeps retrying The target may be hidden, disabled, moving, outside the viewport, or covered by another element. Check the page state and selector. Let the locator readiness behavior work; only disable checks when you understand the effect.
The click lands in the wrong place An offset is relative to the element border box and may no longer match after layout changes. Use a stable target or recalculate the offset for the current element dimensions.
The click works but navigation wait times out The navigation wait may have started after the click, or the interaction may update content without navigation. Start click and navigation wait together with Promise.all; use the appropriate wait for non-navigation updates.
debugHighlight is not visible The feature is experimental and may not work on a given page; it lasts only 10 seconds and does not persist through navigation. Use it only as a temporary aid, and inspect the target through other debugging methods if it is unavailable.
An abort throws from the click promise The supplied signal was aborted while the action was pending. Handle cancellation in the surrounding control flow and avoid reusing an already-aborted signal for a later action.

Performance, reliability, and cost

The options mainly affect how a click is dispatched. A nonzero delay lengthens each press-and-release cycle, and count repeats it. Use only the count and delay the page interaction requires. Locator readiness checks and retries improve robustness when the page is still settling; disabling them changes that tradeoff and can make an interaction happen before the target is ready.

Puppeteer itself has no per-click service charge described by these API references. Operational cost comes from the browser and infrastructure running the automation. Reuse browser processes where appropriate, close pages and browsers when finished, and use action timeouts and cancellation to keep stuck work bounded. Confirm API details against the version pinned by the project.

FAQ

Does locator click wait for an element to be visible?

Yes. Locator click waits for visibility and other readiness conditions by default; visibility behavior can be configured on the locator.

Can I pass a timeout directly to click?

Use setTimeout() on the locator. Timeout is not a documented field of LocatorClickOptions.

Does count: 2 always trigger a double-click handler?

It asks Puppeteer to perform two clicks. The page’s event handling determines whether those clicks produce the behavior you expect.

Should I use debugHighlight in production?

It is documented as experimental debugging behavior, so it is best suited to temporary investigation rather than relying on it in production flows.

Official Puppeteer references