Selecting and interacting with text-containing elements using Puppeteer

Hey everyone! I’m trying to figure out how to use Puppeteer to click on elements that contain specific text. I’ve looked through the docs but can’t seem to find a straightforward way to do this.

Here’s what I’m working with:

<section class="content">
  <button>Click me</button>
  <a href="#">Learn more</a>
  <span>Important info</span>
</section>

What I’m hoping to do is something like:

await page.clickText('Click me', '.content');

Is there a built-in method for this in Puppeteer? Or do I need to come up with a custom solution? Any tips or code snippets would be super helpful. Thanks in advance!

I’ve had success using XPath selectors for this kind of task. Here’s a snippet that might help:

const xpath = `//button[contains(text(), 'Click me')]`;
await page.waitForXPath(xpath);
const elements = await page.$x(xpath);
if (elements.length > 0) {
  await elements[0].click();
} else {
  console.log('Element not found');
}

This approach is quite flexible. You can adjust the XPath to target different element types or use more complex conditions. It’s also generally faster than evaluating JavaScript on the page, especially for larger DOMs.

Remember to handle potential errors and timeouts appropriately in your actual implementation. Good luck with your project!

hey mikechen! i’ve dealt with this before. puppeteer doesn’t have a built-in method for clicking by text, but you can use page.evaluate() to run custom js. something like:

await page.evaluate((text) => {
const el = […document.querySelectorAll(‘*’)].find(e => e.textContent.includes(text));
el && el.click();
}, ‘Click me’);

hope that helps!

While Puppeteer doesn’t offer a direct method for clicking elements by text content, you can create a custom function to achieve this. Here’s an approach I’ve found effective:

async function clickByText(page, text, selector = '*') {
  await page.waitForSelector(selector);
  await page.evaluate((text, selector) => {
    const elements = document.querySelectorAll(selector);
    for (const el of elements) {
      if (el.textContent.trim() === text) {
        el.click();
        return;
      }
    }
    throw new Error(`Element with text '${text}' not found`);
  }, text, selector);
}

You can then use it like this:

await clickByText(page, 'Click me', '.content');

This function is more precise than a simple ‘includes’ check and allows you to specify a parent selector for better performance on large pages.