Struggling to select dynamic IDs with Puppeteer for checkbox clicks

I’m trying to use Puppeteer to click checkboxes next to person names. The problem is that each person has a unique ID that changes every time the page loads. I’ve attempted to use a selector with a regex pattern, but it’s not working. Here’s what I’ve tried:

const selector = '#id^="/^[A-Za-z0-9_]+-[0-9]+/g"';
await page.click(selector);

This gives me an error saying it’s not a valid selector. I’ve checked my regex, and it seems to work fine when testing separately:

const id = '9538-0';
const regex = /^[A-Za-z0-9_]+-[0-9]+/g;
const found = id.match(regex);
console.log(found); // [ '9538-0' ]

The HTML structure looks like this:

<span _ngcontent-ng-c184323="" class="recipient-item-desktop">JOHN DOE (98765432)</span>
<span _ngcontent-ng-c184323="" class="recipient-item-desktop">XYZ</span>
<span _ngcontent-ng-c184323="" class="recipient-item-desktop">$10.00</span>

I’m using JavaScript with Node.js v20.16.0 and Puppeteer version 23.0.2. Any ideas on how to click these checkboxes with changing IDs? Thanks for any help!

hey, have u tried using the aria-label attribute? sometimes it’s more stable than IDs. you could do smthing like this:

await page.click([aria-label*='${personName}']);

This targets checkboxes with aria-labels containing the person’s name. it’s worked for me in similiar situations. just make sure the aria-labels are actually there and unique enough.

I’ve dealt with similar challenges when automating dynamic web pages. One approach that’s worked well for me is using data attributes instead of IDs. You could ask your dev team to add consistent data attributes to the checkboxes, like ‘data-person-name’. Then you can target them reliably:

await page.click(`[data-person-name='${personName}']`);

If modifying the HTML isn’t an option, you might try a more complex selector that combines multiple attributes:

const selector = 'span.recipient-item-desktop:has-text("JOHN DOE") ~ input[type="checkbox"]';
await page.click(selector);

This looks for the span with the person’s name, then finds the adjacent checkbox. It’s more robust against ID changes. Just make sure to handle cases where the text might not match exactly (like partial matches or extra whitespace).

I’ve encountered similar issues with dynamic IDs in Puppeteer. Instead of relying on IDs, you might want to use more stable attributes or the structure of the HTML. Based on your provided HTML, you could try selecting the checkboxes using the text content of the adjacent span elements.

Here’s an approach you could try:

const personName = 'JOHN DOE';
const xpath = `//span[contains(text(), '${personName}')]/preceding-sibling::input[@type='checkbox']`;
await page.$x(xpath).then(elements => elements[0].click());

This XPath selector looks for a span containing the person’s name and then selects the preceding checkbox input. It’s more resilient to ID changes. Remember to replace ‘JOHN DOE’ with the actual name you’re looking for.

If the structure is consistent, you could also use a combination of CSS selectors and text content matching:

await page.evaluate((name) => {
  const spans = document.querySelectorAll('.recipient-item-desktop');
  for (let span of spans) {
    if (span.textContent.includes(name)) {
      span.previousElementSibling.click();
      break;
    }
  }
}, 'JOHN DOE');

This approach might be more flexible if the exact structure varies.