The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use a Puppeteer locator to click a link; use page.$$eval() to collect link destinations. If a click may navigate, start page.waitForNavigation() and the click together with Promise.all() so the navigation wait cannot miss the event.
Find link destinations without clicking
When you need to inspect links rather than follow them, evaluate the anchors in the page and return serializable values such as strings and text:
As an Amazon Associate I earn from qualifying purchases.
const links = await page.$$eval('a', anchors =>
anchors.map(anchor => ({
text: anchor.innerText.trim(),
href: anchor.href,
}))
);
console.log(links);
anchor.href is the browser-resolved URL, so a relative link such as /pricing is returned as an absolute URL. If you need the literal attribute as written in the markup, read anchor.getAttribute('href') instead. $$eval() runs the function against all matching elements and returns its values; avoid returning DOM nodes themselves.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Read one matching link
Use $eval() when you need the first matching anchor. It passes that element to your function and throws if there is no match:
#1 Best Overall
const href = await page.$eval('a.primary-link', anchor => anchor.href);
For a defensive check, query first and handle the absent case:
const link = await page.$('a.primary-link');
if (!link) {
throw new Error('The expected link was not found');
}
const href = await link.evaluate(anchor => anchor.href);
Click a link with a Puppeteer locator
For interaction, Puppeteer recommends locators. They wait for the target to be available and check action preconditions such as visibility, enabled state, viewport position and a stable bounding box before acting.
await page.locator('a.primary-link').click();
Use a selector that identifies the intended link reliably. CSS is suitable for stable markup such as a.next-page. Puppeteer also supports selector extensions for text, accessibility, XPath and shadow-root traversal; use these when the page structure makes them a better fit, and verify the selector matches the intended link rather than a neighboring control.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Wait for navigation caused by the click
Start the navigation wait before the click can trigger it by awaiting both operations concurrently:
const [response] = await Promise.all([
page.waitForNavigation(),
page.locator('a.next-page').click(),
]);
console.log('Current URL:', page.url());
console.log('Navigation response:', response);
The navigation response can be null. Puppeteer treats History API URL changes as navigation, and hash or History API navigation may not produce a full document response. A successful click therefore does not guarantee a new document or a non-null response.
For single-page application updates
If the result you need is an application-state change rather than a document navigation, wait for that result directly—for example, a destination element to appear or the URL to meet a condition. Use waitForNavigation() when navigation itself is the success condition, not merely because a link was clicked.
Rank #3
Use this complete example
This example navigates to a page, gathers all resolved link URLs and then follows a selected link while waiting for navigation:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
const links = await page.$$eval('a', anchors =>
anchors.map(anchor => ({
text: anchor.innerText.trim(),
href: anchor.href,
}))
);
console.log('Links:', links);
const [response] = await Promise.all([
page.waitForNavigation(),
page.locator('a').click(),
]);
console.log('URL after click:', page.url());
console.log('Navigation response:', response);
} finally {
await browser.close();
}
})();
Replace https://example.com and the click selector with the page and link you intend to automate. If the page has multiple anchors, page.locator('a').click() may act on the wrong one; narrow the selector to a stable, link-specific selector.
Choose the right API for the job
| Goal | Use | Important behavior |
|---|---|---|
| Click and follow a link | page.locator(selector).click() |
Recommended interaction path; waits for readiness and checks action preconditions. |
| Collect many link destinations | page.$$eval('a', fn) |
Runs in the page and returns values for all matches. |
| Read one matching destination | page.$eval(selector, fn) |
Uses the first match and throws if none exists. |
| Wait for a navigation event | page.waitForNavigation() alongside the click in Promise.all() |
Response may be null for hash or History API changes. |
Troubleshoot link selection and navigation
The selector finds no link
- Check whether the page has rendered the link before querying it. A locator is generally preferable for an action because it waits for the element to become available.
- Confirm the selector identifies an anchor, not a button styled to look like a link.
- If the element is inside a frame, select the appropriate frame before querying it. If it is inside a shadow root, use Puppeteer’s supported shadow-root selector syntax where applicable.
- For
$eval(), handle the no-match case: it throws when no element matches.
The click hits the wrong link
A broad selector may match several anchors. Narrow it to a stable class, attribute or other distinguishing structure. When a page offers a meaningful accessible name or visible text, Puppeteer’s text or accessibility selector options may help make the target explicit.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
The navigation wait hangs or misses the event
Pair the wait and click in the same Promise.all(), with the wait listed before the click. If the click changes client-side state without navigation, wait for the relevant element or URL condition instead.
The wait resolves but the response is null
That can be expected for hash changes or History API URL changes. Check page.url() or the destination state your automation actually needs instead of assuming every navigation returns a document response.
Crashes, 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 minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11A lower-level click fails
page.click(selector) selects the first match, scrolls it into view and clicks its center; it throws if nothing matches. Puppeteer documents waitForSelector() as a lower-level option, but it does not automatically retry an action that fails. Prefer locator-based interaction unless you need a custom element-handle workflow.
Best Value
Or skip the browser setup
If the goal is a screenshot of a destination page rather than interactive browser automation, ScreenshotNeo can return an image or PDF from one GET request. It is a screenshot API, not a replacement for Puppeteer when you need to click through an interactive 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 and consent banners are accepted and removed, along with known newsletter popups and chat widgets, before capture; those steps can be turned off. Bot checks, blank pages, failed loads and cache hits are not billed, and response headers indicate 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 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for free.
Frequently Asked Questions
Does Puppeteer click the first matching link?
A locator selector should identify the link you intend to follow; with a broad selector, narrow it rather than relying on which match is chosen.
Recommended Free Tools
Can I use Puppeteer to extract links without opening them?
Yes. Use page.$$eval() to return anchor URLs as strings without clicking.
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.

