Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When several elements share a class, add a reliable condition that identifies the one you want, then click it with a Puppeteer locator. For example, filter by distinctive text:

await page
  .locator('.item')
  .filter(el => el.textContent?.trim() === 'Target')
  .click();

Replace .item and Target with values from the page you are automating. This is a pattern, not a universal selector: the right condition depends on the page’s markup and on which attribute, text, or relationship is stable.

Why a shared class can click the wrong element

A CSS class is not necessarily unique. If several elements match .item, page.click('.item') clicks the first matching element. It does not infer which item you intended. If no element matches, the call throws. The Puppeteer Page.click() reference documents this behavior.

Use a selector or locator that adds an actual discriminator: a stable attribute, a meaningful parent-child relationship, distinctive text, or—only when order is meaningful—a position. Puppeteer recommends locators for selecting and interacting with elements. Its locator actions wait for documented readiness conditions, including visibility, enabled state, viewport position, and a stable bounding box, and retry if the action fails because the element is not ready. See the Puppeteer page interactions guide.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a reliable way to identify the target

Filter by distinctive text

When the target’s text distinguishes it from other elements with the shared class, filter the locator:

await page
  .locator('.item')
  .filter(el => el.textContent?.trim() === 'Target')
  .click();

The filter predicate runs in the browser context. It can inspect the page’s elements, but it cannot directly access variables in your Node.js scope. If the predicate must use a value held in Node, use Puppeteer’s documented string-function pattern in the interaction guide. Text matching is only reliable when the chosen text is sufficiently distinctive; whitespace, nested text, localization, and duplicate labels can affect it.

Scope the child to a meaningful parent

If the intended item is inside a uniquely identified card, dialog, or section, combine that container with the child selector. For example:

await page.locator('.product-card[data-id="42"] .item').click();

This selector is appropriate only if the page actually has that attribute and relationship, and they remain stable. Treat the example markup as illustrative rather than a selector that works on an unspecified site.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use an accessible name and role when they identify the control

Puppeteer supports ARIA selectors based on computed accessible name and role. These can be useful when the control’s accessible identity is clearer and more stable than its DOM structure. Verify the actual name and role on the page before using a selector such as:

await page.locator('::-p-aria([name="Save changes"][role="button"])').click();

The interaction guide also documents text, XPath, and shadow-DOM selector facilities. Choose them when they express the real target condition more clearly than a CSS selector.

Use position only when order carries meaning

An index or nth-style selection can address one of several matches, but it is fragile if items are inserted, removed, or sorted. Use position only when the page’s order is part of the intended behavior and is stable for your task. Otherwise, a positional selector can silently click a different item after a page change.

Inspect matches before clicking

When you are unsure what a selector matches, query all matches and inspect the count before choosing or refining it:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition
const matches = await page.$$('.item');
console.log(matches.length);

page.$$(selector) returns an array of matching elements, including an empty array when nothing matches. page.$(selector) returns the first match or null, while $eval runs a callback on the first match and throws if there is none. These query methods help you inspect the DOM; a query by itself does not provide the locator’s interaction-readiness behavior. If you use lower-level element handles, dispose of handles that are no longer needed. See the Puppeteer Page API.

Wait for navigation when the click changes pages

If clicking the target triggers navigation, start waiting for it at the same time as the click so the wait is not started too late:

const [response] = await Promise.all([
  page.waitForNavigation(),
  page.locator('.item')
    .filter(el => el.textContent?.trim() === 'Target')
    .click(),
]);

Adapt the locator to your target. Puppeteer documents the concurrent Promise.all([waitForNavigation(), click()]) pattern in its Page.click() reference.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common failures and how to fix them

  • The wrong item is clicked: A direct page.click('.item') uses the first match. Add a meaningful discriminator and confirm that it identifies the intended element.
  • The filter matches nothing or the wrong text: Check the element’s actual text, including nested content and whitespace. If text is duplicated or changes with localization, use a more stable attribute or parent relationship.
  • The target changes after page updates: Reconsider positional selection or selectors tied to incidental DOM structure. Prefer an attribute, accessible identity, or container relationship that represents the target’s meaning.
  • The click fails because the element is not ready: Prefer a locator for interaction; it waits for documented readiness checks and retries when the action fails because the element is not ready. A raw query only finds matching elements.
  • The navigation wait hangs or misses the transition: For a navigation-triggering click, start waitForNavigation() and the click together with Promise.all.
  • The sample selector does not work on your page: Inspect the page’s DOM and confirm the text, attributes, frame, and shadow-root structure. A selector cannot be made universal without the target page’s markup.

Or skip the browser setup

If your task is to capture a page rather than interact with one of its elements, ScreenshotNeo provides a screenshot API and MCP server. A single request can return a screenshot or PDF; this example saves the response as a WebP file. See the ScreenshotNeo documentation for request options.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
  • Cookie and consent banners are accepted before capture, and 60+ known consent platforms, newsletter popups, and chat widgets are removed; each of these steps can be turned off.
  • Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses include X-Page-Verdict and X-Billed headers.
  • An MCP server lets AI agents, including Claude and Cursor, take screenshots with take_screenshot, inspect pages with get_page_info, and capture PDFs with capture_pdf.
  • The free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots.

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

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.