Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWhen 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.
#1 Best Overall
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.
Rank #2
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.
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.
Rank #4
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.
Best Value
- 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.
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 withPromise.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.
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-VerdictandX-Billedheaders. - An MCP server lets AI agents, including Claude and Cursor, take screenshots with
take_screenshot, inspect pages withget_page_info, and capture PDFs withcapture_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.
Quick Recap
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.

