🐍 Python improvements
- New FormData class for building multipart/form-data request bodies — pass to api_request_context.post(form=…) etc.
- expect.soft(...) soft assertions collect multiple failures in a test instead of stopping at the first one. Requires up-to-date pytest integration to work.
- All
timeoutparameters now acceptdatetime.timedelta— applies wherever a timeout is taken, e.g. page.goto(), locator.click(), expect(...).to_be_visible(). - Async context manager support across more APIs —
async withnow works for objects returned from screencast.show_actions(), screencast.show_overlays(), etc. - page.expect_request(...) and page.expect_response(...) now accept async predicates.
- Typed overloads for expect_event / wait_for_event so the event payload type is inferred per event name.
🌐 HAR recording on Tracing
tracing.start_har() / tracing.stop_har() expose HAR recording as a first-class tracing API, with the same content, mode and url_filter options as record_har:
context.tracing.start_har("trace.har")
page = context.new_page()
page.goto("https://playwright.dev")
context.tracing.stop_har()🪝 Drop API
New locator.drop() 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:
page.locator("#dropzone").drop(
files={"name": "note.txt", "mime_type": "text/plain", "buffer": b"hello"},
)
page.locator("#dropzone").drop(
data={
"text/plain": "hello world",
"text/uri-list": "https://example.com",
},
)🎯 Aria snapshots
- expect(page).to_match_aria_snapshot() now works on a Page, in addition to a Locator — equivalent to asserting against
page.locator("body"). - New
boxesoption on locator.aria_snapshot() / page.aria_snapshot() appends each element's bounding box as[box=x,y,width,height], useful for AI consumption.
New APIs
Browser, Context and Page
- Event browser.on("context") — fired when a new context is created on the browser.
- BrowserContext now mirrors lifecycle events from its pages: browser_context.on("download"), browser_context.on("frameattached"), browser_context.on("framedetached"), browser_context.on("framenavigated"), browser_context.on("pageclose"), browser_context.on("pageload").
Locators and Assertions
- New option
descriptionin page.get_by_role() / locator.get_by_role() / frame.get_by_role() / frame_locator.get_by_role() for matching the accessible description. - New option
pseudoin expect(locator).to_have_css() reads computed styles from::beforeor::after. - New option
stylein locator.highlight() applies extra inline CSS to the highlight overlay, plus new page.hide_highlight() to clear all highlights.
Network
- web_socket_route.protocols() returns the WebSocket subprotocols requested by the page.
- New option
no_defaultsin browser_type.connect_over_cdp() 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.
Errors
- New web_error.location() mirrors console_message.location().
- console_message.location() now exposes
line/columnproperties (line_number/column_numberare deprecated).
🛠️ Other improvements
- Trace Viewer adds a pretty-print toggle for JSON / form request and response bodies in the network details panel.
Breaking Changes ⚠️
- Removed long-deprecated
handleoption onbrowser_context.expose_binding()andpage.expose_binding().
Browser Versions
- Chromium 148.0.7778.96
- Mozilla Firefox 150.0.2
- WebKit 26.4
This version was also tested against the following stable channels:
- Google Chrome 147
- Microsoft Edge 147