·5 min read
Playwright 1.64 adds WebMCP. What changes for your tests?
Decide whether WebMCP affects your tests, then check website actions with Playwright 1.64.

Published: · 3 min read
Select each row’s third table cell with Playwright 1.64 within(). Run the complete example and compare the result with a table-wide nth(2).
On this page
Playwright 1.64 adds within(), a shortcut for selecting inside each chosen row.
A locator (finds page elements) describes which cells or rows to use.
Here, the task is checking one item name from every stock row.
Use nth(2) to choose the third matching cell. Counting starts at zero.
With within(rows), Playwright makes that choice separately inside each row.
That helps when your check should include every displayed row.
A table-wide nth(2) checks just one cell.
The public example contains the table, tests, and setup instructions.
All data is synthetic, meaning made-up sample data.
The tests load local HTML, the page's structure, without application network requests.
Use Node.js 24, which runs JavaScript locally, and npm, which installs project packages.
The project pins Playwright to 1.64.1.
git clone https://github.com/antongulin/anton-qa-resources.git
cd anton-qa-resources/posts/playwright-within-table-cells
npm ci
npx playwright install chromium
npm run verify
On Linux, missing browser system packages may require this installation command:
npx playwright install --with-deps chromium
Installation creates a local package folder and downloads the Chromium browser.
The runner may also create local test-result files.
The third cell contains the item name:
| SKU | Bin | Item |
|---|---|---|
| T-101 | North | Apricot |
| T-202 | West | Blueberry |
| T-303 | East | Coconut |
SKU means product code. Bin names the stock location.
This is the complete table.html fixture, the example's page:
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Synthetic stock table</title>
<table>
<caption>Synthetic stock</caption>
<thead>
<tr><th>SKU</th><th>Bin</th><th>Item</th></tr>
</thead>
<tbody>
<tr><td>T-101</td><td>North</td><td>Apricot</td></tr>
<tr><td>T-202</td><td>West</td><td>Blueberry</td></tr>
<tr><td>T-303</td><td>East</td><td>Coconut</td></tr>
</tbody>
</table>
</html>
The table's body is tbody. Selecting its rows leaves out the header row.getByRole('cell') finds ordinary table cells.
This is the first complete test from tests/table.spec.js:
import { readFileSync } from 'node:fs';
import { test, expect } from '@playwright/test';
test('P1: select the third cell within each row, compared with global nth', async ({ page }) => {
await page.setContent(readFileSync(new URL('../table.html', import.meta.url), 'utf8'));
const rows = page.locator('tbody').getByRole('row');
const cells = page.getByRole('cell');
const thirdInEachRow = cells.nth(2).within(rows);
const thirdInTable = cells.nth(2);
await expect(rows).toHaveCount(3);
await expect(thirdInEachRow).toHaveCount(3);
await expect(thirdInEachRow).toHaveText(['Apricot', 'Blueberry', 'Coconut']);
await expect(thirdInTable).toHaveCount(1);
await expect(thirdInTable).toHaveText('Apricot');
console.log(`within each row: ${JSON.stringify(await thirdInEachRow.allTextContents())}`);
console.log(`global nth(2): ${JSON.stringify(await thirdInTable.allTextContents())}`);
});
cells.nth(2).within(rows) selects Apricot, Blueberry, and Coconut.
The test checks both the number of selected cells and their text.
It compares the same table with cells.nth(2), which selects only Apricot.
Both choices work. They answer different questions about the page.
Use the per-row choice when every row belongs in your check.
The verified run used Node.js 24.21.0, Playwright 1.64.1, and Chromium.
Both tests passed, with these printed values:
within each row: ["Apricot","Blueberry","Coconut"]
global nth(2): ["Apricot"]
varied rows: ["Coconut","Apricot","Coconut"]
The second test changes row order and repeats an item name.
Its rows contain five, three, and four ordinary cells.
The result still follows each row's third cell, in document order.
The full test file includes that second case.
These checks cover Chromium and rows with at least three ordinary cells.
Merged cells need a separate check. This example does not measure speed.
The number 2 still depends on the cell's position.
If the table changes, review whether the third cell still means the same thing.
Earlier Playwright versions could select columns through other patterns.within() makes this per-row choice explicit. It does not always mean less code.
Try the complete example with your table's structure.
The official documentation explains the selection rule.
The 1.64 release notes introduce the shortcut.
Anton Gulin is the AI QA Architect, the first person to claim this title on LinkedIn. He builds AI-powered test automation systems where AI agents and human engineers collaborate on quality. Former Apple SDET (Apple.com / Apple Card pre-release testing). Find him at anton.qa or on LinkedIn.
Get notified when I publish something new, and unsubscribe at any time.
·5 min read
Decide whether WebMCP affects your tests, then check website actions with Playwright 1.64.

·5 min read
Try a small PDF filename test with Claude Code. Write and run tests, inspect the failure, and stop before changing the code.

·4 min read
Choose fields, getters, or methods for Playwright locators without confusing stored locators with stored elements.
