NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
NuGet · #1460 most downloaded on NuGet
Playwright enables reliable end-to-end testing for modern web apps. This is a utility package used by the Microsoft.Playwright.NUnit and Microsoft.Playwright.MSTest packages.
Last release 14 days ago
23 Sep 2026
Ships fairly regularly
a new release about every 6 weeks
Rarely documented
notes for 11 of 46 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
59 releases · first in 2022
Page.FrameLocator() and Frame.FrameLocator() called without a selector search in any frame of the subtree, so you no longer need to locate the iframe
Page.FrameLocator() and Frame.FrameLocator() called without a selector search in any frame of the
subtree, so you no longer need to locate the iframe first:
// Finds the button in any frame on the page.
await Page.FrameLocator().GetByRole(AriaRole.Button).ClickAsync();The rest of the locator resolves inside a single frame, just like a regular locator, and an error is thrown when it
matches elements in several frames.
New Locator.Visible returns a locator that matches only visible elements. It is the recommended
replacement for the :visible CSS pseudo-class:
await Page.Locator("button").Visible.ClickAsync();New AriaSnapshots and ScreenSnapshots options of Tracing.StartAsync() capture an aria snapshot and a screenshot of the page on every action:
await context.Tracing.StartAsync(new()
{
Snapshots = true,
AriaSnapshots = true,
ScreenSnapshots = true
});With aria and screen snapshots recorded, the new Display Aria mode in the trace viewer shows the action screenshot
side by side with the aria snapshot, and hovering an aria node highlights it on the screenshot.
HttpCredentialsList now also accepts an array of credentials. The first entry matching the request origin is used, and entries without an origin match any request.Opfs includes the origin private file system in the storage state, so it can be persisted and restored into later contexts.pwsh bin/Debug/netX/playwright.ps1 install --no-remove keeps the browsers of other Playwright installations instead of removing them.pwsh bin/Debug/netX/playwright.ps1 codegen --http-credentials records against pages behind HTTP authentication.This version was also tested against the following stable channels:
One column per quarter.
page.screenshot() and locator.screenshot() can now capture screenshots in the WebP format — Playwright infers the format from a .webp file extension,
page.screenshot() and locator.screenshot() can now capture screenshots in the WebP format — Playwright infers the format from a .webp file extension, or you can set the type explicitly. Quality 100 (the default) is lossless, while lower values use lossy compression:
await Page.ScreenshotAsync(new() { Path = "homepage.webp", Quality = 50 });Scroll option (Auto | None) on actions to opt out of Playwright's automatic scroll-into-view.navigator.clipboard no longer read or overwrite the clipboard of the machine running them.This version was also tested against the following stable channels:
New Credentials virtual authenticator, available via BrowserContext.Credentials , lets tests register passkeys and answer navigator.credentials.create
New Credentials virtual authenticator, available via BrowserContext.Credentials, lets tests register passkeys and answer navigator.credentials.create() / navigator.credentials.get() ceremonies in the page — no real hardware key required, works in all browsers:
var context = await browser.NewContextAsync();
// Seed a passkey your backend provisioned for a test user.
await context.Credentials.CreateAsync("example.com", new()
{
Id = credentialId,
UserHandle = userHandle,
PrivateKey = privateKey,
PublicKey = publicKey,
});
await context.Credentials.InstallAsync();
var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com/login");
// The page's navigator.credentials.get() is answered with the seeded passkey.You can also let the app register a passkey once in a setup test, read it back with Credentials.GetAsync(), and seed it into later tests — see Credentials for details.
New WebStorage API, available via Page.LocalStorage and Page.SessionStorage, reads and writes the page's storage for the current origin:
await page.LocalStorage.SetItemAsync("token", "abc");
var token = await page.LocalStorage.GetItemAsync("token");
var items = await page.SessionStorage.ItemsAsync();ArtifactsDir in BrowserType.ConnectOverCDPAsync() controls where artifacts such as traces and downloads are stored when attached to an existing browser.Cursor in Screencast.ShowActionsAsync() controls the cursor decoration rendered for pointer actions.OnFrame callback in Screencast.StartAsync() now receives a Timestamp of when the frame was presented by the browser.This version was also tested against the following stable channels:
Removed long-deprecated Handle option on BrowserContext.ExposeBindingAsync and Page.ExposeBindingAsync .
Expect() overloads now accept a custom message that is prepended to any failure, giving extra context in test reports:
await Expect(page.Locator("#status"), "Should be logged in").ToBeVisibleAsync();When the assertion fails, the message is prefixed:
Should be logged in
Locator expected to be visible
Tracing.StartHarAsync() / Tracing.StopHarAsync() expose HAR recording as a first-class tracing API, with the same Content, Mode and UrlFilter options as RecordHar:
await context.Tracing.StartHarAsync("trace.har");
var page = await context.NewPageAsync();
await page.GotoAsync("https://playwright.dev");
await context.Tracing.StopHarAsync();New Locator.DropAsync() simulates an external drag-and-drop of files or clipboard-like data onto an element. Playwright dispatches dragenter, dragover, and drop with a synthetic [DataTransfer] in the page context — works cross-browser and is great for testing upload zones:
await page.Locator("#dropzone").DropAsync(new() {
Files = new FilePayload() {
Name = "note.txt",
MimeType = "text/plain",
Buffer = Encoding.UTF8.GetBytes("hello"),
},
});
await page.Locator("#dropzone").DropAsync(new() {
Data = new Dictionary<string, string> {
["text/plain"] = "hello world",
["text/uri-list"] = "https://example.com",
},
});Page.Locator("body").Boxes option on Locator.AriaSnapshotAsync() / Page.AriaSnapshotAsync() appends each element's bounding box as [box=x,y,width,height], useful for AI consumption.Page now implements IAsyncDisposable — pages can be used with await using for automatic cleanup.Description in Page.GetByRole() / Locator.GetByRole() / Frame.GetByRole() / FrameLocator.GetByRole() for matching the accessible description.Pseudo in Expect(locator).ToHaveCSSAsync() reads computed styles from ::before or ::after.Style in Locator.HighlightAsync() applies extra inline CSS to the highlight overlay, plus new Page.HideHighlightAsync() to clear all highlights.NoDefaults in BrowserType.ConnectOverCDPAsync() disables Playwright's default overrides on the default context (download behavior, focus emulation, media emulation), so attaching to a user's daily-driver browser doesn't disturb its state.Handle option on BrowserContext.ExposeBindingAsync and Page.ExposeBindingAsync.This version was also tested against the following stable channels:
New Page.Screencast API provides a unified interface for capturing page content with:
New Page.Screencast API provides a unified interface for capturing page content with:
Screencast recording — record video with precise start/stop control, as an alternative to the recordVideoDir option:
await page.Screencast.StartAsync(new() { Path = "video.webm" });
// ... perform actions ...
await page.Screencast.StopAsync();Action annotations — enable built-in visual annotations that highlight interacted elements and display action titles during recording:
await page.Screencast.ShowActionsAsync(new() { Position = "top-right" });ShowActionsAsync accepts Position ("top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"), Duration (ms per annotation), and FontSize (px). Returns a disposable to stop showing actions.
Visual overlays — add chapter titles and custom HTML overlays on top of the page for richer narration:
await page.Screencast.ShowChapterAsync("Adding TODOs", new() {
Description = "Type and press enter for each TODO",
Duration = 1000,
});
await page.Screencast.ShowOverlayAsync("<div style=\"color: red\">Recording</div>");Real-time frame capture — stream JPEG-encoded frames for custom processing like thumbnails, live previews, AI vision, and more:
await page.Screencast.StartAsync(new() {
OnFrame = frame => SendToVisionModel(frame.Data),
});Agentic video receipts — coding agents can produce video evidence of their work. After completing a task, an agent can record a walkthrough video with rich annotations for human review:
await page.Screencast.StartAsync(new() { Path = "receipt.webm" });
await page.Screencast.ShowActionsAsync(new() { Position = "top-right" });
await page.Screencast.ShowChapterAsync("Verifying checkout flow", new() {
Description = "Added coupon code support per ticket #1234",
});
// Agent performs the verification steps...
await page.Locator("#coupon").FillAsync("SAVE20");
await page.Locator("#apply-coupon").ClickAsync();
await Expect(page.Locator(".discount")).ToContainTextAsync("20%");
await page.Screencast.ShowChapterAsync("Done", new() {
Description = "Coupon applied, discount reflected in total",
});
await page.Screencast.StopAsync();The resulting video serves as a receipt: chapter titles provide context, action annotations highlight each interaction, and the visual walkthrough is faster to review than text logs.
Page.Locator("body").AriaSnapshotAsync().Depth and Mode in Locator.AriaSnapshotAsync().Filter in Page.ConsoleMessagesAsync() and page.pageErrors() controls which messages are returned.Live in Tracing.StartAsync() for real-time trace updates.ArtifactsDir in BrowserType.LaunchAsync() to configure the artifacts directory.New Browser.BindAsync() API makes a launched browser available for playwright-cli, @playwright/mcp, and other clients to connect to.
Bind a browser — start a browser and bind it so others can connect:
var serverInfo = await browser.BindAsync("my-session", new() {
WorkspaceDir = "/my/project",
});Connect from playwright-cli — connect to the running browser from your favorite coding agent.
playwright-cli attach my-session
playwright-cli -s my-session snapshotConnect from @playwright/mcp — or point your MCP server to the running browser.
@playwright/mcp --endpoint=my-sessionConnect from a Playwright client — use API to connect to the browser. Multiple clients at a time are supported!
var browser = await chromium.ConnectAsync(serverInfo.Endpoint);Pass Host and Port options to bind over WebSocket instead of a named pipe:
var serverInfo = await browser.BindAsync("my-session", new() {
Host = "localhost",
Port = 0,
});
// serverInfo.Endpoint is a ws:// URLCall Browser.UnbindAsync() to stop accepting new connections.
Run npx playwright-cli show to open the Dashboard that lists all the bound browsers, their statuses, and allows interacting with them:
This version was also tested against the following stable channels:
New 'system' theme option follows your OS dark/light mode preference
Thanks to @cpAdm for contributing these improvements!
BrowserType.ConnectOverCDPAsync() now accepts an IsLocal option. When set to true, it tells Playwright that it runs on the same host as the CDP server, enabling file system optimizations.
_react and _vue selectors. See locators guide for alternatives.:light selector engine suffix. Use standard CSS selectors instead.Devtools from BrowserType.LaunchAsync() has been removed. Use Args = new[] { "--auto-open-devtools-for-tabs" } instead.After 3 years of being deprecated, we removed Page.Accessibility from our API. Please use other libraries such as Axe if you need to test page accessi…
Starting with this release, Playwright switches from Chromium, to using Chrome for Testing builds. Both headed and headless browsers are subject to this. Your tests should still be passing after upgrading to Playwright 1.57.
We're expecting no functional changes to come from this switch. The biggest change is the new icon and title in your toolbar.
If you still see an unexpected behaviour change, please file an issue.
On Arm64 Linux, Playwright continues to use Chromium.
After 3 years of being deprecated, we removed Page.Accessibility from our API. Please use other libraries such as Axe if you need to test page accessibility. See our Node.js guide for integration with Axe.
Steps in Locator.ClickAsync() and Locator.DragToAsync() that configures the number of mousemove events emitted while moving the mouse pointer to the target element.Event BrowserContext.BackgroundPage has been deprecated and will not be emitted. Property BrowserContext.BackgroundPages will return an empty list
input placeholderAutomatic ToBeVisibleAsync() assertions: Codegen can now generate automatic ToBeVisibleAsync() assertions for common UI interactions. This feature can
ToBeVisibleAsync() assertions: Codegen can now generate automatic ToBeVisibleAsync() assertions for common UI interactions. This feature can be enabled in the Codegen settings UI.Microsoft.Playwright.Xunit.v3Microsoft.Playwright.MSTest.v4This version was also tested against the following stable channels:
Nothing published for this version
Nothing published for this version
Nothing published for this version
New cookie property PartitionKey in browserContext.cookies() and browserContext.addCookies() . This property allows to save and restore partitioned co
New cookie property PartitionKey in browserContext.cookies() and browserContext.addCookies(). This property allows to save and restore partitioned cookies. See CHIPS MDN article for more information. Note that browsers have different support and defaults for cookie partitioning.
New option --user-data-dir in multiple commands. You can specify the same user data dir to reuse browsing state, like authentication, between sessions.
pwsh bin/Debug/netX/playwright.ps1 codegen --user-data-dir=./user-datapwsh bin/Debug/netX/playwright.ps1 open does not open the test recorder anymore. Use pwsh bin/Debug/netX/playwright.ps1 codegen instead.
This version was also tested against the following stable channels:
New method Locator.Describe() to describe a locator. Used for trace viewer.
New method Locator.Describe() to describe a locator. Used for trace viewer.
var button = Page.GetByTestId("btn-sub").Describe("Subscribe button");
await button.ClickAsync();pwsh bin/Debug/netX/playwright.ps1 install --list will now list all installed browsers, versions and locations.
This version was also tested against the following stable channels:
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →