How do I correctly get the inner text of child elements in Playwright?

I’m trying to get the innerText of child <h4> elements for a list of elements selected by a common data-testid in Playwright:

const headers = await page.$$("data-testid=my-custom-id");

const rawData = await Promise.all(headers.map(async (header) => {
    return await (await header.$('h4')).innerText;
}));

console.log(rawData);

Problem: When I log rawData, I get [AsyncFunction: innerText] instead of the actual text.

In your code, innerText is a function, so you need to call it with ():

const headers = await page.$$("data-testid=my-custom-id");

const rawData = await Promise.all(
  headers.map(async (header) => {
    const h4 = await header.$("h4");
    return await h4.innerText(); // <--- call it as a function
  })
);

console.log(rawData);

The key difference: innerText is not a property, it’s an async method, so omitting () gives you the function itself.

Playwright’s locator API can get all inner texts in one call without mapping manually:

const rawData = await page.locator('[data-testid="my-custom-id"] h4').allInnerTexts();
console.log(rawData);

This avoids the Promise.all and map boilerplate and works efficiently even if some elements appear/disappear dynamically.

If you want to extract text via page context, you can use evaluate:

const rawData = await page.$$eval(
  '[data-testid="my-custom-id"] h4',
  elements => elements.map(el => el.innerText)
);

console.log(rawData);

This runs in the browser context and directly returns an array of strings, which is very fast for scraping scenarios.