October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

How to Click a Specific Element When Class Names Are Shared in Puppeteer

When several elements share a class, narrow the Puppeteer locator with a condition that identifies the intended target. Learn text filtering, match inspection, navigation waits, and common fixes.

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.

Use a Puppeteer locator with a condition that identifies the element you mean—such as distinctive text or a stable parent relationship—instead of clicking the shared class alone. A locator can filter matching elements and wait for the target to be ready before clicking it.

Click the matching element by a distinguishing condition

For example, if several elements have the class item and the intended one contains the text “Target,” filter the locator by that text:

As an Amazon Associate I earn from qualifying purchases.

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

Replace .item and 'Target' with a selector and condition from your page. This is a pattern, not a universal selector: without the page’s markup, no one can know which condition uniquely identifies your target. Puppeteer’s interaction guide recommends locators for selecting and interacting with elements. The filter callback runs in the browser context, so it cannot directly access Node.js variables. If the predicate needs a value from Node, use Puppeteer’s documented string-function pattern for passing it.

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

Choose a selector that identifies the intended element

Prefer a stable attribute or meaningful parent

If the target has a stable, unique attribute, or sits inside a uniquely identifiable card, dialog, or section, use that relationship to narrow the selector. For instance, .product-card[data-id="42"] .item is appropriate only if that attribute and structure actually exist and remain meaningful on the page. Avoid relying on generated classes or incidental structure when a more stable identifier is available.

Filter by text when the label is distinctive

Text filtering is useful when the target’s text distinguishes it from the other matches. Check for duplicate labels, whitespace, nested text, and localization: any of these can make a text-only condition ambiguous or fragile. If necessary, combine the text condition with a more specific parent or attribute.

Use accessibility information when it is distinctive

Puppeteer supports ARIA selectors based on computed accessible name and role. Use one when the target’s role and accessible name reliably identify it, and confirm those values on the page first. For example:

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

Use position only when order is meaningful

An index or nth-style choice can select a particular match, but it identifies the element by its current position, not by what the element is. Use it only if the order itself is stable and significant; inserted, removed, or sorted items can silently change what that position means.

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

Check how many elements match

When you are unsure whether your selector is unique, inspect its matches with Puppeteer’s query API:

const matches = await page.$$('.item');
console.log(matches.length);

page.$$() returns an array of all matching elements; an empty array means there were no matches. page.$() returns the first match or null, while page.$eval() runs a callback on the first match and throws if none exists. These APIs help inspect or query the DOM, but a query by itself does not provide the locator’s interaction-readiness checks. Dispose of element handles when finished with lower-level handle workflows.

Why a bare shared-class click can hit the wrong item

page.click('.item') scrolls the matched element into view and clicks its center. If multiple elements match, Puppeteer’s documented behavior is to click the first one; if none match, the call throws. That may be different from the intended target even though the selector is valid.

Locators are more expressive for this task: they can filter candidates and automatically wait for documented readiness conditions, including visibility, enabled state, viewport position, and bounding-box stability. Locator actions are retried when an action fails because the element is not ready. A locator still needs a condition that identifies the right element; waiting does not make an ambiguous selector unique.

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

Wait for navigation when the click changes pages

If clicking the target triggers navigation, wait for it concurrently with the click so the navigation does not race ahead of the wait:

Best Value
The SQL Programming Language: .
  • Used Book in Good Condition
const [response] = await Promise.all([
  page.waitForNavigation(),
  page.locator('.item').filter(el => el.textContent?.trim() === 'Target').click(),
]);

Use this only when the click is expected to navigate. Adapt the locator condition to the actual target. For interactions that update the current page without navigation, wait for an appropriate page condition instead.

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

Troubleshoot a click that fails or targets the wrong element

  • The wrong repeated item is clicked: The selector likely matches several elements. Add a real discriminator, such as a stable attribute, parent relationship, or distinctive text filter.
  • The locator finds no target: Confirm the selector, text, and accessible name against the rendered page. Consider whether content has loaded yet or whether the element is inside a frame or shadow root.
  • The text filter matches more than one item: Add another condition, such as a meaningful container or attribute. Text is not inherently unique.
  • A positional choice changes after page updates: Replace it with an identity-based condition unless the ordering is intentionally part of the requirement.
  • The element is found but not ready to click: Prefer a locator interaction over a raw query, and verify that the target becomes visible and enabled in the page state.
  • The click triggers navigation but the script misses it: Start waitForNavigation() together with the click using Promise.all().
  • The example works nowhere else unchanged: That is expected; selectors and labels must reflect the target page’s DOM, frame, and shadow-root structure. Puppeteer also documents text, ARIA, XPath, and shadow-DOM selector facilities when CSS alone is not suitable.

Or skip the browser setup

If you need a screenshot rather than an interactive click, ScreenshotNeo can capture a page with one GET request. It is not a replacement for Puppeteer when your task requires clicking an element and then interacting with the page.

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

See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed along with supported newsletter popups and chat widgets before capture; those cleanup steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 shots a month without a card; paid plans start at $5 for 3,000 shots.

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

Sign up for ScreenshotNeo’s free plan: 1,000 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.