ScreenshotNeo

BlogHow-to

How to Tap the Screen with Puppeteer

Use Puppeteer’s touchscreen API for coordinate taps, or choose a locator or element tap when you know which page element to activate.

By the ScreenshotNeo team4 October 20267 min read

Use await page.touchscreen.tap(x, y) to tap a point on the page with Puppeteer. For example, await page.touchscreen.tap(120, 240) sends a touch start and touch end at that position. If you mean “activate this button” rather than “tap this exact coordinate,” start with a locator: await page.locator('button').click(). When the target must receive touch input, an element tap targets its center and scrolls it into view if needed.

This guide shows coordinate taps, mobile device emulation, element-oriented alternatives, and practical fixes for common problems. The API details below are based on the Puppeteer Touchscreen.tap reference and related official guides; check the documentation for your installed Puppeteer version if a signature or device preset differs.

1. Choose the right interaction

Goal Use What it targets
Tap a particular screen position page.touchscreen.tap(x, y) The supplied horizontal and vertical coordinates.
Activate a known DOM element in the usual way page.locator(selector).click() An element selected by CSS; locators wait for action preconditions such as visibility, enabled state, viewport presence, and stability.
Send touch input to a known DOM element Element tap, such as elementHandle.tap() where available The element’s center, after scrolling it into view when needed.

Use a coordinate tap when the position itself matters, when testing a touch surface, or when you do not have a useful selector. Use a locator for ordinary element activation. Choose an element tap when the target should receive touch input but you can identify it in the DOM. An element tap can throw if the element becomes detached before the action completes.

See the official Page interactions guide for locator behavior and the ElementHandle.tap reference for element taps.

2. Run a coordinate tap

Install Puppeteer in a Node.js project, then save this as tap.js. The script opens a page, waits for it to load, taps at coordinates, and closes the browser even if navigation or the tap fails.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 390, height: 844, isMobile: true, hasTouch: true });
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

  // Coordinates are in the page viewport's CSS pixels.
  await page.touchscreen.tap(120, 240);
} finally {
  await browser.close();
}

Run it with node tap.js in a project configured for ES modules, or rename it to tap.mjs. Puppeteer’s tap API takes the horizontal and vertical position. The documented operation dispatches touchstart and touchend; it is a tap, not a swipe or a long press. See Touchscreen.tap(x, y).

Coordinate details

  • Origin: (0, 0) is at the top-left of the viewport. The x coordinate increases to the right and y increases downward.
  • Viewport-relative: choose coordinates against the current viewport, not the full document. A point outside the visible page area cannot target an off-screen element; scroll first or use an element-oriented action.
  • CSS pixels: coordinates are page positions, not screenshot image pixels. If you capture at a device scale factor greater than one, do not multiply the tap coordinates by that factor.
  • Timing: wait until the page and target are ready before tapping. For a known element, a locator’s readiness checks usually make this simpler.

3. Emulate a mobile device before navigating

If the site changes layout or behavior for a mobile browser, emulate a device before opening the URL. Puppeteer’s page.emulate(device) sets device metrics and the user agent. The device preset shown below follows the current official example; confirm that it exists in the KnownDevices export of the version installed in your project.

import puppeteer, { KnownDevices } from 'puppeteer';

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

Emulate before navigation when practical: changing page size can affect a site after it has loaded. If you set the viewport yourself, do that early as well. Puppeteer notes that changing isMobile or hasTouch can cause a reload in some cases. Refer to the official Page.emulate reference and Page.setViewport reference.

4. Use an element interaction when coordinates are not the requirement

Locator click for ordinary activation

await page.locator('button.submit').click();

Locators are Puppeteer’s recommended starting point for selecting and interacting with page elements. They wait for action preconditions, including that the target is visible, enabled, in the viewport, and stable. This helps avoid brittle scripts that guess a button’s position and then tap the wrong place after a responsive layout change.

Element tap for touch-specific behavior

When you need touch input on a DOM target, locate the element and use its tap method where supported by your installed API version:

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

An element tap scrolls the element into view when necessary, then taps its center. The handle can become stale if the page replaces the element, in which case the action may throw. Re-select the element after navigation or a UI rerender. See ElementHandle.tap.

5. Troubleshooting coordinate taps

Symptom Likely cause What to do
The tap has no visible effect The coordinates miss the target, the target is below the fold, or the page has not reached its interactive state. Confirm the current viewport size and target position. Wait for the relevant content, scroll the target into view, or use a locator/element tap.
The tap works on desktop but not in the mobile layout The page was navigated before mobile metrics or touch capability were configured. Set the viewport or call page.emulate() before navigation, then recompute coordinates for the emulated layout.
A button moved between runs Responsive layout, fonts, delayed content, or a popup changed the page geometry. Prefer a locator when testing button activation. For a coordinate test, wait for layout-affecting content and derive the point from the current viewport.
Element tap throws because the target is detached The page rerendered or replaced the element after it was selected. Wait for the updated UI and query the element again immediately before tapping.
The script reports a missing device preset The preset name differs in the installed Puppeteer version. Inspect that version’s KnownDevices values or use page.setViewport() with explicit metrics.
Changing viewport appears to reload the page Puppeteer documents that changing mobile or touch settings can reload in some cases. Configure those settings before navigation when possible, then wait for the page again.

6. Reliability, performance, and cost considerations

A coordinate tap is direct, but its correctness depends on stable geometry: viewport size, scroll position, responsive breakpoints, and anything that moves content. For a test whose purpose is the exact touch position, record those conditions and keep the page state predictable. For a test whose purpose is simply activating a control, locator readiness checks reduce dependence on guessed coordinates.

Mobile emulation is useful for exercising a mobile layout and supplying device metrics and a user agent, but it does not establish how a particular physical device will behave. Verify device-specific behavior on the actual target devices when that distinction matters. This dossier does not provide benchmark figures for tap speed or reliability, so none are claimed here.

Puppeteer is the DIY route and requires you to run and maintain the browser environment. Browser launch, page loading, and site-specific waiting contribute to the work and elapsed time; this guide does not assign a dollar cost or benchmark. If all you need is a saved screenshot rather than interactive browser control, a screenshot API can avoid setting up that browser flow.

Or skip the browser setup

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://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(`ScreenshotNeo request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Cookie banners are accepted like a visitor and removed along with 60+ known consent platforms, newsletter popups, and chat widgets before the shot; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed, and the response identifies the page verdict and billing status. Its MCP server lets AI agents using Claude, Cursor, or another MCP client take screenshots. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does page.touchscreen.tap(x, y) perform a long press?

No. The documented tap dispatches touchstart and touchend. It does not describe a hold duration.

Should I tap a button by coordinates in a test?

Only when the coordinate or touch position is part of what you need to test. For ordinary button activation, use a locator so Puppeteer can wait for the element’s action preconditions.

Do I need a physical touchscreen to use Puppeteer’s tap API?

The API sends touch input through Puppeteer; the documented workflow also supports device emulation. A physical touchscreen is not required for the code shown here.