Playwright 1.63: Locks, Richer Traces, and Easier Test Maintenance
Explore the key features of Playwright 1.63 — test locks, visible locators, iframe searches, and more detailed reports for your test suite.
Marcos Franco
QA Engineer & Mentor
Playwright 1.63 brings improvements that solve common pain points in automation suites: concurrency over shared data, duplicate elements on screen, hard-to-locate iframes, and unclear diagnostics when a test fails.
This release isn’t focused on a single big API. Instead, it refines the day-to-day work of anyone maintaining E2E tests in real projects: it preserves parallelism where it’s safe and adds more context to investigate failures faster.
In this article, we’ll explore the most important new features and understand when it’s worth adopting them.
1. Test locks: parallelism without data conflicts
Running tests in parallel makes the pipeline faster, but can cause instability when two tests modify the same resource.
Some common scenarios:
- Two tests change the settings of the same account.
- Multiple scenarios use the same test user.
- An external integration has a request limit.
- Data creation depends on a single resource, like a coupon or a schedule.
Previously, the solution usually involved reducing the number of workers, running part of the suite in serial mode, or creating manual controls. With test locks, you simply declare which tests cannot run at the same time.
import { test, expect } from '@playwright/test';
test(
'should update user settings',
{ lock: 'user-settings' },
async ({ page }) => {
await page.goto('/settings');
await page.getByLabel('Receive notifications').uncheck();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('Settings saved')).toBeVisible();
},
);
Any test using the same lock (user-settings) will wait for its turn. Everything else continues running in parallel, across files, workers, and projects.
Applying a lock to a group of tests
When all scenarios in an area share the same resource, the lock can go on the describe:
import { test } from '@playwright/test';
test.describe('account settings', { lock: 'user-settings' }, () => {
test('should change language', async ({ page }) => {
// ...
});
test('should change notifications', async ({ page }) => {
// ...
});
});
A test can also declare more than one lock. Use this to protect genuinely shared dependencies — not as a replacement for data isolation. Whenever possible, prefer creating independent users and data per test.
2. Finding elements in iframes with less code
Many modern applications use iframes for payments, authentication, chat, or third-party widgets. Until now, you had to locate the iframe first and then search for the element inside it.
In Playwright 1.63, page.frameLocator() and frame.frameLocator() can be called without a selector. In that case, Playwright searches across frames in the current tree:
await page.frameLocator().getByRole('button', { name: 'Pay now' }).click();
This is useful when the desired element exists in a single iframe and the iframe selector is fragile, dynamic, or not meaningful.
The rest of the locator still needs to find the element within a single frame. If the search matches more than one iframe, Playwright throws an error to prevent clicking the wrong element.
For more complex flows, or when you need to explicitly state where the element comes from, continue using a selector for the iframe:
const paymentFrame = page.frameLocator('iframe[title="Secure payment"]');
await paymentFrame.getByLabel('Card number').fill('4242 4242 4242 4242');
3. locator.visible() for truly interactive elements
It’s common for a UI to keep hidden versions of the same button — for example, one for desktop and one for mobile. In those cases, a generic locator may find both elements, making the action ambiguous.
The new locator.visible() restricts the search to visible elements:
await page.locator('button').visible().filter({ hasText: 'Continue' }).click();
It is the recommended alternative to the CSS :visible pseudo-selector:
// Avoid this pattern in new tests.
await page.locator('button:visible').click();
// Prefer this instead.
await page.locator('button').visible().click();
That said, start with semantics-oriented locators like getByRole, getByLabel, and getByTestId. The visible() method is a useful refinement when there are multiple matches, not a reason to choose generic selectors.
Turn best practices into a real suite
The new APIs help, but the difference shows when they are part of a well-structured automation strategy: locator selection, test organization, reliable data, and CI integration.
If you want to learn Playwright with TypeScript in a practical way and build that foundation step by step, check out the Playwright course. If your challenge involves architecture decisions, career growth, or specific obstacles in your project, individual mentorship offers guidance tailored to your context.
4. Traces that combine screen, DOM, and accessibility
The Trace Viewer is already one of Playwright’s most valuable tools for investigating failures. In version 1.63, snapshot configuration now lets you choose exactly what gets captured at each action: DOM, ARIA tree, and screen.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
trace: {
mode: 'on-first-retry',
snapshots: {
dom: true,
aria: true,
screen: true,
},
},
},
});
With ARIA and screen snapshots enabled, the Trace Viewer’s Display Aria mode shows the visual capture alongside the accessibility tree. When you hover over an ARIA node, the corresponding element is highlighted in the image.
This is especially helpful when the failure is related to:
- Incorrect accessible names on buttons and fields.
- Elements visually present but absent from the accessibility tree.
- Role-based locators that don’t find the expected component.
- Differences between what the user sees and what assistive technologies interpret.
Use full captures intentionally. They make test artifacts richer, but may increase the volume of data generated in CI.
5. Reports with more context and focus on performance
Version 1.63 also improves the readability of long runs or intermittent failures.
Structured parameters in test.step()
It’s now possible to associate structured data with manual steps:
await test.step(
'perform login',
async () => {
await page.goto('/login');
await page.getByLabel('Email').fill('admin@example.com');
await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!);
await page.getByRole('button', { name: 'Sign in' }).click();
},
{ params: { profile: 'admin' } },
);
Reporters receive these parameters, and the HTML Report and Trace Viewer now display subtitles with information such as the locator or URL involved in the action. Avoid inserting passwords, tokens, or personal data in the parameters, as they may appear in execution artifacts.
Duration waterfall in the HTML Report
The HTML report now displays a duration waterfall next to test steps. This makes it easier to identify where a scenario is spending time: navigation, waiting for an API response, browser interaction, or a preparation step.
Perfetto reporter
For analyzing execution on a timeline, there’s a new built-in reporter:
npx playwright test --reporter=perfetto
It generates a file in Trace Event format, compatible with the Perfetto UI and chrome://tracing. Each worker appears on a separate track, which helps visualize bottlenecks and the degree of parallelism in the suite.
Other updates worth noting
Beyond the highlights, Playwright 1.63 includes useful changes for specific projects:
httpCredentialsnow accepts a list of credentials, choosing the first one compatible with the request origin.- Browser state can now include the Origin Private File System (OPFS), useful for applications that use this browser storage.
- New
dialogclosedevents onpageandbrowserContextnotify when a JavaScript dialog is accepted, dismissed, or closed. ariaSnapshotJSON()returns ARIA snapshots as JSON, a practical option for integrations and tools that process data programmatically.- API request methods accept a generic type to type the return of
response.json(). - New emulation options for
reducedMotion,forcedColors, andcontrast. --add-reporteradds a reporter from the command line without replacing reporters defined in the configuration file.npx playwright install --no-removepreserves browsers used by other Playwright installations on the machine.
Before updating: two compatibility notes
The update is straightforward, but it’s worth checking these points before promoting it to CI.
Experimental component testing packages
The packages @playwright/experimental-ct-react, @playwright/experimental-ct-react17, and @playwright/experimental-ct-vue will no longer receive updates. The recommended path is to migrate to the stories and galleries model, introduced in version 1.62.
If your team uses experimental component testing, plan this migration before becoming dependent on deprecated APIs.
Ubuntu 20.04 is no longer supported
Playwright 1.63 ends support for Ubuntu 20.04. Review Docker images, self-hosted runners, and legacy CI agents.
For Docker, keep the package and image versions aligned. For example:
image: mcr.microsoft.com/playwright:v1.63.0-noble
Pinning the tag avoids incompatibilities between the Playwright version installed in the project and the browser executables available in the container.
How to update to Playwright 1.63
In a TypeScript or JavaScript project using Playwright Test, update the dependency and browsers:
npm install -D @playwright/test@1.63.0
npx playwright install
Then run the suite locally and in CI:
npx playwright test
My suggestion is to update in a separate branch, validate the most critical tests, and only then start adopting the new APIs. Test locks tend to bring immediate value for suites suffering from concurrency; the trace and reporting features are excellent for reducing diagnosis time on future failures.
Conclusion
Playwright 1.63 doesn’t change how you write tests from scratch — it makes a good suite more reliable and easier to investigate.
Locks let you protect shared resources without sacrificing the entire parallel execution. Iframe searching and visible locators reduce code and ambiguity. The new traces and reports bring the technical diagnosis closer to what actually happened on screen.
For all the details and APIs in this version, check the official Playwright 1.63 release notes and the Docker documentation before updating your pipeline.
If updating to Playwright 1.63 sparked the desire to take your automation beyond isolated examples, the Playwright course with TypeScript is the next step to deepen your practice. And, to define a strategy compatible with your experience and goals in QA, check out individual mentorship.