ScreenshotNeo

BlogHow-to

How to Move a Touch Point with Puppeteer

Start a touch with Puppeteer, move the returned touch handle, and end the gesture. See runnable code, the direct API alternative, and fixes for common issues.

By the ScreenshotNeo team4 October 20265 min read

To move a touch point with Puppeteer, start a touch with page.touchscreen.touchStart(x, y), call move(x, y) on the returned handle, then call end() to release it:

const touch = await page.touchscreen.touchStart(startX, startY);
await touch.move(endX, endY);
await touch.end();

Keep the handle for the whole gesture so the start, moves, and release belong to the same touch. Puppeteer also provides page.touchscreen.touchMove(x, y), which moves the first active touch. The browser may optimize event delivery, so one API call does not guarantee one page-level touchmove event. See the official touchStart, TouchHandle, and touchMove documentation.

Runnable Puppeteer example

This Node.js example opens a page, starts a touch, moves it through intermediate points, releases it, and closes the browser. Replace the example URL and coordinates with a page and target geometry from your own test.

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 touch = await page.touchscreen.touchStart(80, 120);
  try {
    await touch.move(100, 140);
    await touch.move(130, 170);
    await touch.move(160, 200);
  } finally {
    await touch.end();
  }
} finally {
  await browser.close();
}

Save it as move-touch.js in a project with Puppeteer installed and run it with Node.js. The finally blocks ensure the browser closes and the active touch is released even if a move fails. Coordinates are numeric x/y arguments; use the current Puppeteer API documentation and inspect your page’s viewport and target geometry when deciding which values to send.

Move the first active touch directly

If you want to use the touchscreen lifecycle directly, call touchStart, make one or more touchMove calls, and finish with touchEnd:

await page.touchscreen.touchStart(80, 120);
try {
  await page.touchscreen.touchMove(120, 160);
  await page.touchscreen.touchMove(160, 200);
} finally {
  await page.touchscreen.touchEnd();
}

Use this form when the first active touch is the one you intend to move. The handle form is often easier to reason about because each operation is tied to the handle returned by touchStart. The API documentation does not establish a performance difference between these approaches.

Send a path with intermediate points

Some interfaces respond to movement along a path rather than only its final position. Keep one touch active and send successive coordinates before ending it:

const touch = await page.touchscreen.touchStart(80, 120);
try {
  for (const [x, y] of [[100, 140], [130, 170], [160, 200]]) {
    await touch.move(x, y);
  }
} finally {
  await touch.end();
}

This sends a sequence of Puppeteer move calls; it does not promise that the page will receive the same number of touchmove events. The Puppeteer documentation specifically notes that browser optimizations, including Chrome throttling, can affect event emission. Assert the interface’s resulting state or a meaningful event sequence instead of assuming a one-to-one count.

Configure the page and coordinates

  • Choose a viewport early. If your test changes mobile or touch viewport properties, do so before relying on page state. Puppeteer’s Page documentation notes that changing viewport isMobile or hasTouch settings can reload a page in some cases. See the Puppeteer Page documentation.
  • Measure the target in the page you are testing. Confirm the element’s position and the viewport geometry before choosing the touch coordinates. The cited method signatures accept numeric x/y values; consult the documentation for your installed Puppeteer version for coordinate details.
  • Start before moving. A move is meaningful only while a touch is active. End the same gesture when it is complete.
  • Keep setup and assertions separate. Wait for the target page state your test requires, perform the gesture, then inspect the resulting application state.

Common errors and fixes

Symptom Likely cause Fix
The move has no effect No touch was started, or the wrong touch is active. Call touchStart first. Prefer the returned handle’s move method when you need to keep operations tied to that touch.
The page observes fewer move events than expected The browser optimized or throttled touch-move dispatch. Do not assert one page event per call. Check the interaction’s final state or a meaningful sequence instead. See Puppeteer’s touchMove caveat.
The gesture affects the wrong part of the page The coordinates do not match the current target geometry or viewport. Inspect the page and viewport used by the test, then update the coordinates. Recheck after navigation or layout changes.
The page reloads during viewport setup A mobile or touch viewport property changed after page creation. Set the intended viewport properties early in setup. Puppeteer’s Page docs describe reload behavior for some viewport changes.
The gesture remains active after an exception The code exited before the release call. Put end() or touchEnd() in a finally block so cleanup runs after a failed move.

Performance and reliability notes

Each awaited move adds an ordered step to the gesture, which helps make the sequence clear but does not control how many page events the browser emits. Add intermediate points only when the interaction needs a path. For reliable automation, wait for the page’s required starting state, release the touch in cleanup code, and assert the resulting behavior rather than event counts that browser optimization can change. The cited API documentation does not provide a benchmark or a cost model for these calls.

Or skip the browser setup

If your goal is to capture a page after checking its result, ScreenshotNeo can return a screenshot from one API request. This does not perform a touch gesture; it provides a screenshot without requiring you to set up a browser capture flow.

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

See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before capture; 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, and paid plans start at $5 for 3,000.

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

FAQ

Should I use the touch handle or touchscreen.touchMove()?

Use the handle when you want the start, movement, and release tied to the touch returned by touchStart. Use touchscreen.touchMove() when working with the first active touch through the touchscreen API.

Does every move call trigger a page touchmove event?

No. Browser optimizations can reduce emitted events, as the Puppeteer API documentation notes.

Can I move a touch before starting one?

No active touch exists to move until you start one. Begin with touchStart, then move and end the active touch.

Can ScreenshotNeo test the touch interaction?

No. ScreenshotNeo captures a page; use Puppeteer to perform the touch gesture itself.