ScreenshotNeo

BlogHow-to

How to Tap an Element in Puppeteer

Use Puppeteer’s tap APIs for touch input: select an element, tap its center, or target viewport coordinates. Learn when to use locators, mouse clicks, and device emulation.

By the ScreenshotNeo team4 October 20266 min read

Use await page.tap(selector) to tap the first element matching a selector. Puppeteer scrolls it into view if needed and taps its center. For most element workflows, Puppeteer recommends a locator: await page.locator(selector).tap(). A tap sends touch input; page.click() sends mouse input.

1. Install Puppeteer and run a basic tap

Install Puppeteer in a Node.js project:

npm install puppeteer

Save this as tap.mjs and run it with node tap.mjs. It opens a page, waits for a button, taps it, and closes the browser even if an error occurs.

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'});
  await page.locator('button.submit').tap();
} finally {
  await browser.close();
}

Replace button.submit with a selector that identifies the intended control on the page. The example assumes the target is a button; selectors can also target links and other elements that respond to touch.

2. Choose the right tap or click API

Need API Behavior
Tap an element using a selector page.tap(selector) Scrolls into view if needed; taps the first match at its center.
Tap an element with locator waiting page.locator(selector).tap() Locator interactions wait for the element and an actionable state.
Tap a held element handle elementHandle.tap() Scrolls into view and taps the handle’s center; errors if detached.
Tap a point in the viewport page.touchscreen.tap(x, y) Sends touchstart and touchend at horizontal and vertical coordinates.
Click with mouse input page.click(selector) Uses mouse input rather than touch input.

Prefer the locator form for routine interactions because it handles waiting for the target to become available and actionable. Use page.tap(selector) when its concise selector-based behavior is suitable. Choose touch or mouse based on the input behavior under test; a mouse click is not a substitute when the page specifically needs touch events. See the official Puppeteer interaction guide and Page.tap reference.

3. Tap by coordinates or an element handle

Use coordinate tapping when the test already knows a point in the viewport, such as a position calculated by another step. Coordinates are viewport positions, not document coordinates.

await page.touchscreen.tap(120, 340);

The Touchscreen API dispatches touchstart and touchend. Coordinates can become stale when the viewport, scroll position, or layout changes, so prefer an element selector when possible. See the Touchscreen.tap reference.

If you already hold an element handle, tap it directly:

const button = await page.$('button.submit');
if (!button) {
  throw new Error('Submit button was not found');
}
await button.tap();

Reacquire the handle after navigation or a page update that may replace the element. A detached handle cannot be tapped.

4. Emulate a mobile device before navigation

When testing a mobile layout, configure device emulation before loading the site. Emulation sets the user agent and viewport; applying it after navigation can change page behavior. Use a device name available in the KnownDevices export in the Puppeteer version installed by your project.

import puppeteer, {KnownDevices} from 'puppeteer';

const browser = await puppeteer.launch({headless: true});
try {
  const page = await browser.newPage();
  await page.emulate(KnownDevices['iPhone 17 Pro']);
  await page.goto('https://example.com', {waitUntil: 'domcontentloaded'});
  await page.locator('button.submit').tap();
} finally {
  await browser.close();
}

Check the Page.emulate reference and your installed package’s device list if that preset is unavailable.

5. Wait for the result and handle failures

A tap only performs the input action. If the page navigates or updates asynchronously, wait for that result explicitly. For navigation triggered by a tap, start waiting before the tap so the navigation is not missed:

const navigation = page.waitForNavigation();
await page.locator('a.next-page').tap();
await navigation;

For an in-page update, wait for a visible result or a changed selector with the appropriate locator wait supported by your Puppeteer version. Set timeouts to match the page’s behavior rather than adding arbitrary long delays.

6. Troubleshooting

Symptom Cause Fix
Selector tap throws because no element was found The selector is wrong, or the target has not appeared yet. Inspect the selector and page state; use a locator interaction that waits for the target, or wait for the application state that creates it.
The wrong matching element is tapped page.tap(selector) uses the first match when several elements match. Narrow the selector to a unique element or use a locator scoped to the intended container.
ElementHandle.tap() fails after a page update The referenced node was detached from the DOM. Find the element again after the update and tap the new handle, or use a locator.
Tap handler does not run as expected The test sends touch input, but the page or test expects mouse input, or vice versa. Use tap() for touch behavior and click() for mouse behavior; verify the event type expected by the application.
Mobile page has the wrong layout Emulation was applied after navigation, or the chosen preset is unavailable. Emulate before goto() and confirm the preset exists in the installed Puppeteer version.
Coordinate tap hits the wrong spot Scrolling, resizing, or layout changes made the coordinates stale. Recalculate viewport coordinates immediately before tapping, or target the element by selector.

7. Reliability, performance, and cost

For reliable tests, target a unique element, wait for the page state that makes it actionable, and avoid retaining handles across DOM replacement. Locator-based interactions reduce timing errors by waiting for the target and its actionable state. Coordinate taps are more sensitive to viewport and layout changes. Emulating the target device before navigation helps ensure the page is rendered in the intended context.

Tap calls themselves are small browser automation actions; total runtime is usually governed by browser startup, navigation, application rendering, and any waits. Reuse a browser process across a suite when appropriate, close it in cleanup, and avoid fixed sleeps where a state-based wait is available. Puppeteer requires a compatible browser runtime; account for the installation and execution cost of that environment. The cited API documentation does not provide a fixed performance benchmark or service price.

8. Or skip the browser setup

If the task is to capture a page rather than test its touch response, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. It captures pages but does not perform or verify a Puppeteer touch interaction.

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

9. FAQ

Does page.tap() physically touch a device?

No. It sends touch input through Puppeteer’s browser automation interface; it does not operate a physical phone.

Should I use page.tap() or a locator?

Use a locator for typical element interactions because it waits for the target and actionable state. Use page.tap(selector) when the direct selector method fits your flow.

Can I tap an element outside the viewport?

The selector and element-handle tap methods scroll the target into view if necessary. Coordinate taps address a viewport point, so scroll to the intended location first.

Does a tap submit a form?

It can if the tapped element’s page behavior submits the form. The tap API sends input; application behavior and any resulting navigation or update should be awaited separately.