Power Your Software Testing with AI Agents and Cloud
The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. Test Intelligently and Ship Faster.
- TestMu AI (Formerly LambdaTest)
- /
- Blog
- /
- Playwright 1.64: What's New in the Latest Playwright Release
Playwright 1.64: What's New in the Latest Playwright Release
Playwright 1.64 adds WebMCP testing, locator.within(), --shuffle and 60 fps video. See what's new, what breaks on upgrade, and how to run 1.64 in the cloud.
Published on:
A routine dependency bump moves a suite to Playwright 1.64, and a test that passed yesterday fails without a single code change. The release changes several defaults at once, from the screen size that device descriptors report to whether an element inside a hidden iframe counts as visible.
Playwright 1.64 was released on October 7, 2026, with Chromium 156, Firefox 157 and WebKit 27.2.
Those defaults reach a lot of pipelines at once: the playwright package was downloaded 113,562,399 times in the week of October 6 to 12, 2026, according to the npm registry.
This guide covers what 1.64 adds, what breaks when you upgrade, and how to run a 1.64 suite on TestMu AI. If Playwright is new to you, start with the Playwright tutorial.
TL;DR
Playwright 1.64 is the October 7, 2026 release of Microsoft's Playwright test framework. It adds page.webmcp for testing the tools a page exposes to AI agents, locator.within() for column queries, a --shuffle flag for order-dependent tests, and VP9 video at custom frame rates. Install the 1.64.1 patch, released October 14.
- WebMCP testing: Playwright 1.64 adds page.webmcp.tools() and page.webmcp.callTool() to list and call the tools a page registers. Chromium needs the --enable-features=WebMCP launch flag, and with it on, Chromium 156 exposes the page-side API as document.modelContext.
- Drop-in upgrade: No. Playwright 1.64 forwards the emulated screen from device descriptors, treats elements in hidden iframes as hidden, lets --update-snapshots=missing pass, and compiles JSX in tests from tsconfig.json.
- locator.within(): The Playwright 1.64 locator.within() method combines two locators, and nth() or first() resolve inside each parent, so a cell locator within a row locator returns one column of a table.
- Shuffled runs: The npx playwright test --shuffle command runs tests in random order and prints a seed. Passing the seed back replays the same order, which exposes tests that depend on each other.
- Runs on TestMu AI: Yes. A Playwright 1.64.1 suite runs on the TestMu AI cloud grid through Playwright's connectOptions, while WebMCP specs stay in a local project marked default: false because they need a launch flag.
What Is New in Playwright 1.64?
The Playwright 1.64 release notes add WebMCP support, locator.within(), page.getByRef(), new test runner options and changes to video recording.
| Change | What it does | Who it helps |
|---|---|---|
| page.webmcp and frame.webmcp | Lists and calls the tools a page registers through the experimental WebMCP browser API | Teams whose pages expose tools to AI agents |
| locator.within() | Combines two locators you already have, with nth() and first() resolved inside each parent | Anyone querying tables, lists and repeated cards |
| page.getByRef() | Locates an element by the aria ref that page.ariaSnapshot() reports in 'ai' mode | Agents and tools that act on aria snapshots |
| testProject.default | Keeps a project in the config without running it on a plain npx playwright test | Teams that configure every browser but run one locally |
| --shuffle | Schedules tests in random order and prints a seed that replays the order | Suites with tests that depend on each other |
| lock in test.describe.configure() | Applies a named test lock to every test in a file or group | Tests that share an account or a global setting |
| Video fps, style and VP9 | Custom frame rates, CSS-styled action markers, and VP9 encoding for smaller files | Anyone recording runs for review or demos |
| toHaveScreenshot type: 'webp' | Stores every unnamed screenshot baseline as WebP | Repos carrying large PNG baselines |
| APIRequestContext cookies | addCookies(), cookies() and clearCookies() on a request context, mirroring BrowserContext | API tests that manage sessions |
| includeShadow, signCount, filteredProjects | Serializes open shadow roots in page.content(), sets a passkey signature counter, and lists the selected projects in global setup and reporters | Shadow DOM apps, WebAuthn tests and custom reporters |
How Do You Test WebMCP Tools With Playwright 1.64?
The WebMCP API lets web applications provide JavaScript-based tools to AI agents, each with a description and an input schema. Its specification is published by the W3C Web Machine Learning Community Group, with editors from Microsoft and Google, and it is not a W3C Standard nor on the W3C Standards Track.
For a tester, a WebMCP tool is a new surface to cover: an agent calls it instead of clicking through the UI, so a wrong schema or a broken handler fails the agent without any visible error on the page.
Playwright 1.64 adds page.webmcp and frame.webmcp so you can test those tools like any other part of the app. Chromium exposes WebMCP only when launched with --enable-features=WebMCP, one of its experimental Chrome flags, so give the spec its own project:
// playwright.config.ts (projects excerpt)
{
name: 'local-webmcp',
default: false,
testMatch: /webmcp/,
use: {
...devices['Desktop Chrome'],
launchOptions: { args: ['--enable-features=WebMCP'] },
},
},The spec registers a tool the way your app would, then lists it with tools() and calls it with callTool():
import { test, expect } from '@playwright/test';
test('add_to_cart tool is registered and callable', async ({ page }) => {
await page.goto('https://www.testmuai.com/selenium-playground/');
// Stand-in for your app's own registration code.
await page.evaluate(() => {
const modelContext = (document as any).modelContext ?? (navigator as any).modelContext;
modelContext.registerTool({
name: 'add_to_cart',
description: 'Adds a product to the cart by SKU.',
inputSchema: { type: 'object', properties: { sku: { type: 'string' }, qty: { type: 'number' } }, required: ['sku'] },
execute: async ({ sku, qty = 1 }) => ({ content: [{ type: 'text', text: `${sku} x${qty} added` }] }),
});
});
const tools = await page.webmcp.tools();
expect(tools.map(t => t.name)).toContain('add_to_cart');
const result = await page.webmcp.callTool('add_to_cart', { sku: 'IPOD-NANO', qty: 2 });
expect(result.content[0].text).toBe('IPOD-NANO x2 added');
});$ npx playwright test --project=local-webmcp
Running 1 test using 1 worker
ok 1 [local-webmcp] › tests\webmcp.spec.ts:3:5 › add_to_cart tool is registered and callable (733ms)
1 passed (1.9s)- Feature-detect the API - with the flag on, the Chromium 156 build bundled with Playwright 1.64 exposes the API as document.modelContext, the name the current draft uses, while Playwright's own WebMCP docs still name navigator.modelContext. Registration code that checks both keeps working across builds.
- Untrusted input - the WebMCP class docs say the page supplies tool names, descriptions, input schemas and results, so treat them as untrusted input.
- Browser support - Chromium needs the launch flag, Firefox needs the dom.modelcontext.enabled and dom.modelcontext.testing.enabled preferences, and WebKit does not implement WebMCP.
- Agents get the tools too - Playwright MCP offers page tools to the agent as webmcp_<tool> by default (--no-webmcp opts out), and playwright-cli lists and calls them with webmcp-list and webmcp-call. For a terminal-first alternative, compare Kane CLI vs Playwright MCP.
How Does locator.within() Change Column Queries?
locator.within() takes two locators you already have and reads in the natural order: this button, within that dialog. Relative locators such as nth() and first() resolve inside each parent separately, so a cell locator with nth(1) inside a row locator means the second cell of every row, not the second cell of the table.
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('https://www.testmuai.com/selenium-playground/table-sort-search-demo/');
await expect(page.getByRole('grid')).toBeVisible();
});
test('position column fills every row on page one', async ({ page }) => {
const positions = page.getByRole('gridcell').nth(1).within(page.getByRole('row'));
await expect(positions).toHaveCount(10);
await expect(positions.first()).toHaveText('Photographer');
});
test('search for London leaves only London offices', async ({ page }) => {
await page.getByRole('searchbox').fill('London');
const offices = page.getByRole('gridcell').nth(2).within(page.getByRole('row'));
await expect(offices).toHaveText(['London', 'London', 'London', 'London', 'London']);
});The table on this demo page is a DataTables grid. Once its script runs, the cells take the gridcell role and the table pages to 10 rows, so the spec waits for the grid role before it queries columns. A query for the cell role that runs before the switch matches the plain HTML table, and the same test then passes or fails depending on page speed.
page.getByRef() pairs with the aria snapshot that agents read: page.ariaSnapshot({ mode: 'ai' }) labels each element with a ref, and getByRef() turns a ref back into a locator.
test('fills the message form through aria refs', async ({ page }) => {
await page.goto('https://www.testmuai.com/selenium-playground/simple-form-demo/');
const snapshot = await page.ariaSnapshot({ mode: 'ai' });
const refFor = (text: string) =>
snapshot.split('\n').find(line => line.includes(text))!.match(/ref=(\w+)/)![1];
await page.getByRef(refFor('textbox "Please enter your Message"')).fill('Playwright 1.64');
await page.getByRef(refFor('button "Get Checked Value"')).click();
await expect(page.locator('#message')).toHaveText('Playwright 1.64');
});Refs are generated per snapshot, and on this page they look like f2e54 rather than e2, so read them from the snapshot on every run instead of hardcoding them. The same snapshot format drives Playwright agents, and the rest of the locator API is covered in Playwright locators.
What Changed in the Playwright Test Runner?
The runner changes target large configs and shared state: projects that stay configured but idle, a random test order, file-level locks, and smaller screenshot baselines.
Default Projects
testProject.default: false keeps a project in the config without running it on a plain npx playwright test, so a local run stays on one browser:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'chromium', use: devices['Desktop Chrome'] },
{ name: 'firefox', use: devices['Desktop Firefox'], default: false },
{ name: 'webkit', use: devices['Desktop Safari'], default: false },
],
});npx playwright test # runs chromium only
npx playwright test --project=firefox # runs firefox
npx playwright test --project="*" # runs all three, for example on CIPass --project="*" in CI, or a project marked default: false silently drops out of the pipeline. The new fullConfig.filteredProjects lists the selected projects in global setup, so a setup check can fail the run when a browser is missing. For how projects split browsers and environments, see Playwright projects.
Shuffled Test Order
--shuffle schedules tests in a random order and prints the seed at the start of the run. A test that passes only because another test ran first, for example one that relies on data an earlier test created, fails under some seeds. The run below is the suite from the cloud section of this guide:
$ npx playwright test --shuffle
Running 4 tests using 2 workers, shuffle seed 429272856
ok 2 [testmu-chrome] › tests\table.spec.ts:8:5 › position column fills every row on page one (2.3s)
ok 3 [testmu-chrome] › tests\table.spec.ts:14:5 › search for London leaves only London offices (2.1s)
ok 1 [testmu-chrome] › tests\form.spec.ts:3:5 › fills the message form through aria refs (3.6s)
ok 4 [testmu-chrome] › tests\form.spec.ts:14:5 › adds two values (2.2s)
4 passed (25.9s)
$ npx playwright test --shuffle 429272856 # replays the same orderKeep the seed with the CI log, because a failure that appears in one order cannot be reproduced without it. Order dependence is one source of Playwright flaky tests, and a nightly shuffled job finds it without slowing the merge gate.
HyperExecute, TestMu AI's test orchestration platform, works on the other half of the problem: it tracks which tests failed and reorders later runs so those tests run first, which surfaces a broken build sooner.
Locks and WebP Baselines
Test locks arrived in 1.63: tests that share a lock name never run at the same time, across files, workers and projects, while everything else stays parallel. In 1.64, test.describe.configure() applies a lock to every test in a file or group:
// tests/user-settings.spec.ts
test.describe.configure({ lock: 'user-settings' });Lock only the files that touch a resource you cannot duplicate, such as one test account, so the rest of the suite keeps its Playwright parallel testing speed.
For visual tests, the type option of toHaveScreenshot in testConfig.expect stores every unnamed baseline as WebP. Since 1.62, a snapshot named with a .webp extension is stored as lossless WebP, and this option extends that to unnamed ones:
// playwright.config.ts
export default defineConfig({
expect: {
toHaveScreenshot: { type: 'webp' },
},
});Switching formats means regenerating baselines once, so plan it as its own change, separate from the upgrade. The workflow for updating and reviewing baselines is in Playwright screenshot comparison.
What Is New in Playwright Video Recording?
Videos can now be recorded at a custom frame rate, and the overlays that mark each action are styled with plain CSS:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: {
mode: 'on',
size: { width: 1920, height: 1080 },
fps: 60,
show: {
actions: {
style: {
point: 'width: 20px; height: 20px; border-radius: 50%; background: red',
highlight: 'outline: 2px solid #333; background: rgba(0, 128, 255, .15)',
title: 'font-size: 16px',
},
},
},
},
},
});- Frame rate - the fps option works in testOptions.video, recordVideo and screencast.start(), and Firefox and WebKit currently capture up to 25 frames per second.
- Styling - style takes CSS for the point marker, the target highlight and the action title, and replaces the fontSize option, which is now deprecated.
- Cursor - the cursor stays visible at the last action point, survives navigations, and moves along an eased path.
- Encoding - videos use VP9 instead of VP8, which takes less CPU and produces smaller files at the same or better quality.
- Agents - every video option is also available in Playwright MCP and playwright-cli.
What Breaks When You Upgrade to Playwright 1.64?
These are the changes the release notes flag as breaking, plus a deprecation in the video options. Each can turn a green suite red after the upgrade:
| Change | What breaks in 1.64 | What to do |
|---|---|---|
| Device screen | ...devices['Desktop Chrome'] and similar descriptors now forward screen, so window.screen and media queries see the emulated size | Set screen: undefined to keep the old behavior while you review the diffs |
| JSX in tests | JSX follows the jsx, jsxFactory, jsxFragmentFactory and jsxImportSource options in tsconfig.json, defaulting to react/jsx-runtime | Check tsconfig.json before upgrading specs that contain JSX |
| --update-snapshots=missing | Tests that only create missing snapshots now pass; the old behavior is the mode called 'default' | If CI relied on that failure, add a step that fails when new snapshot files appear |
| Hidden iframes | Elements inside an iframe that is not visible count as hidden for actions, isVisible() and toBeVisible() | Fix tests that reached into a hidden frame instead of making it visible first |
| Video fontSize | Deprecated in favor of the style option | Move it to show.actions.style, for example title: 'font-size: 16px' |
Install Playwright 1.64.1 rather than 1.64.0. The patch fixes a regression in which Chromium 155 and later abort a preflighted cross-origin redirect whenever any route is registered (net::ERR_ABORTED), and a bug where _electron.launch intermittently loses a packaged app's first window since 1.64.0.
npm install -D @playwright/test@1.64.1
npx playwright install --with-deps
npx playwright --versionThe second command downloads the browsers that match the new version. For first-time setup on a new machine or CI image, follow the steps to install Playwright.
Note: Upgrading to Playwright 1.64? Run the upgraded suite in parallel on the TestMu AI cloud grid before you merge, so screen and hidden-iframe changes show up across browsers in one pass. Try TestMu AI free!
How Do You Run Playwright 1.64 on TestMu AI?
The Playwright test runner reaches TestMu AI through its own connectOptions: each worker opens its browser over a WebSocket endpoint that carries your capabilities, as the Playwright test runner docs describe. This config runs the specs from this guide on the grid and keeps the WebMCP spec on a local Chromium:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
const capabilities = {
browserName: 'Chrome',
browserVersion: 'latest',
'LT:Options': {
platform: 'Windows 11',
build: 'Playwright 1.64 Upgrade',
name: 'Playwright 1.64 suite',
user: process.env.LT_USERNAME,
accessKey: process.env.LT_ACCESS_KEY,
},
};
export default defineConfig({
testDir: './tests',
workers: 2,
projects: [
{
name: 'testmu-chrome',
testIgnore: /webmcp/,
use: {
connectOptions: {
wsEndpoint: `wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`,
},
},
},
{
name: 'local-webmcp',
default: false,
testMatch: /webmcp/,
use: {
...devices['Desktop Chrome'],
launchOptions: { args: ['--enable-features=WebMCP'] },
},
},
],
});Export LT_USERNAME and LT_ACCESS_KEY, then run npx playwright test --shuffle. The output in the shuffled test order section above comes from this config.
- Browser version - browserVersion: 'latest' resolves to Chrome 155 at the time of writing, the stable channel the 1.64 release was tested against, while a local run uses the bundled Chromium 156.
- What stays local - the WebMCP spec needs a Chromium launched with --enable-features=WebMCP, so it lives in a default: false project and runs with --project=local-webmcp.
- Session artifacts - Automation Cloud runs Playwright suites in parallel across 3,000+ browser and OS combinations and captures network logs, console logs, video, screenshots and command logs for every session, with no grid to maintain.
- Two kinds of video - set video: true in LT:Options and the grid records the whole session, separately from the Playwright video option covered above.
Let Claude Code write Playwright tests that actually pass.
Getting Started With Playwright 1.64
Install 1.64.1, run the full suite once with screen: undefined set, and compare the results with your last 1.63 run; the failures that remain point to the hidden-iframe and snapshot-mode changes. Then add --shuffle to a nightly job and keep the printed seed.
When the suite passes locally, move it to Playwright testing on TestMu AI and follow the guide to parallel testing with Playwright to spread it across the browsers your users run.
Author
Sri Harsha is Engineering Manager of the Open Source Program Office at TestMu AI, where he leads open-source engineering behind the Selenium and Appium automation grid and builds agentic AI systems for quality engineering. He is a member of the Selenium Technical Leadership Committee and a committer to WebdriverIO and Appium, and was recognized with the LambdaTest Delta Award 2023 for Best Contributor in open-source testing. He brings over 10 years of experience in software testing and automation, with earlier roles at EPAM Systems and ZenQ. Sri Harsha holds a B.Tech in Computer Science from Jawaharlal Nehru Technological University.
Reviewer
Vipul Verma is Group Senior Vice President of Engineering at TestMu AI, where he heads the entire engineering organization that builds KaneAI, HyperExecute, and the broader testing cloud. He brings 15+ years architecting, securing, and scaling large enterprise applications across multiple sites. Before TestMu AI he was India Head at LogicHub, where he built the India R&D site from the first employee to a 30-plus engineering team, and Principal Software Engineer at Sumo Logic, where he was the first engineer in the India office and shipped search-performance and pricing-model initiatives. Earlier he worked on trading platforms at Portware and D. E. Shaw. Vipul holds a B.Tech in Computer Science from IIT Kharagpur.
Playwright 1.64 FAQs
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance
- Advanced access controls
- Advanced data retention rules
- Advanced Local Testing
- Premium Support options
- Early access to beta features
- Private Slack Channel
- Unlimited Manual Accessibility DevTools Tests




