Behavior changes
serve: the--http-max-concurrentdefault now follows--cdp-max-connections(8× it, between 40 and 256). With the default 16 connections it is 128.fetch --dump markdownnow asks the server for markdown (Accept: text/markdown,...). Atext/markdownresponse is dumped as-is. Not sent with--dump-selector,--wait-selectoror--wait-script.Accessibility.getPartialAXTreenow honorsfetchRelatives, as Chrome does: it returns the node and its relatives, no longer the whole subtree. UsegetFullAXTreeorgetChildAXNodesfor a subtree.DOM.querySelectorwith no match now returnsnodeId: 0instead of an error, as Chrome does.- Touch event handlers (
ontouchstart, …) are removed fromdocumentand elements: Lightpanda doesn't emulate a touch device. navigator.sendBeaconnow checks its arguments. Beacons are still not sent unless--load-resources beaconis set.- The HTTP cache database is deleted and rebuilt when its schema version changes.
waitForStatenow reports a timeout instead of always answering that the page reached the state.- MCP over HTTP: a request on a session closed with
DELETEnow gets a 404 instead of starting a new session. fetch()andnew Request()with a body on GET or HEAD now throw aTypeError.- Scripts inserted from an isolated world (Playwright
setContent,appendChild) now run in the main world. - Event listeners now run in their own world's context, so Playwright's
focus()andselectOption()fire React'sonFocus/onChange.
New Web APIs
AudioContext(WAV only)- Payment Request API:
PaymentRequest,PaymentResponseand their events, behaving like Chrome with no payment app installed NavigateEventonnavigation(intercept()is not implemented)PerformanceNavigationTimingentry for the documentdocument.execCommand:insertText,delete,forwardDelete,selectAll,insertLineBreak, and thestyleWithCSS,useCSSanddefaultParagraphSeparatorsettings. Other commands returnfalseimage.decode()HTMLElement.isContentEditable(real value),HTMLElement.spellcheck,document.designModeTouchconstructor andTouchEventtouch listselementFromPoint/elementsFromPointonShadowRoot- SVG
getBBox() HTMLFrameElement,SecurityPolicyViolationEvent, a stubPath2Dnavigator.mimeTypes(emptyMimeTypeArray)img.sizes;link.relList.supports()fordns-prefetch,preconnectandprefetchHTMLFieldSetElement.elements;abbr,mark,small,wbrand other HTMLElement-only tags are nowHTMLElementinstead ofHTMLUnknownElementonmouseenterandonmouseleavehandlers- Web Crypto:
raw-secretandraw-publickey formats;CryptoKeyis now serializable (structuredClone,postMessage, IndexedDB) MessagePortis now transferableTextDecoderStreamdecodes every encodingTextDecodersupports, with state kept across chunksXMLSerializernow writes XML instead of HTML- WebMCP follows the current spec:
document.modelContext,getTools(),toolchange,registerToolreturns a promise - CSS: native nesting, color parsing, more known properties (
CSS.supports, unknown property errors)
Web API behavior / fixes
- Layout: flex-shrink, horizontal margins,
left/right/inset, and widths from text measurement. Widths are relative to the containing box. Out-of-flow children no longer size their parent, and block boxes start at their parent's left edge positionis now read from stylesheets, not only from the inline style (offsetParent,getComputedStyle)- An iframe without size is now 300×150, and its box is the frame's viewport, so Playwright can click inside it
Range.getClientRects()now returns one rect per selected element or text nodeelementFromPointreturnsnulloutside the viewport- Textarea
scrollHeightnow counts its text, for auto-sizing textareas - Typing and
Input.insertTextnow insert text intocontenteditableelements anddesignModedocuments; Ctrl-A selects all - Selectors:
:in-range/:out-of-range,:default,:scopeon a document;:required/:optionalonly on form controls;[attr^=""],[attr$=""]and[attr*=""]match nothing - Forms:
stepMismatch, Chrome-liketype=emailvalidation (withmultiple),readonlyfields skip validation, emptyactionmeans the document's URL margin,padding,insetandborder-*shorthands now expand into longhandsstyle.x = nullandsetProperty(name, null)now remove the declaration- Media queries accept fractional lengths (
max-width: 767.98px) - Changing a
<style>'s text now clears the style cache - Un-rendered light DOM (slot fallback with assigned content, unslotted children) is now treated as hidden
- A closed
<details>keeps its loose text out ofinnerText <a>and<area>URL setters keep userinfo and reject invalid values; better URL port handlingnavigation.navigate()with a fragment now updateslocationand the entry URLdatasetrejects invalid names and maps a leading capital todata--isEqualNodecompares namespace URIsDOMTokenList.forEachsees mutations made by its callbackselect/selectionchangeevents are now dispatched asynchronously;eventPhaseisAT_TARGETin direct dispatch<dialog>:show()on an open dialog does nothing,closefires asynchronouslyxhr.responseType = 'document'now parses HTML into anHTMLDocumentinnerHTML = ""on an<html>element creates<head>and<body>document.fonts.load()no longer fires load events when there are no font facesnavigator.appVersionnow starts with5.0- Properties moved to the right interfaces (e.g.
titleonDocument); the global's prototype is nowWindow.prototype new WebSocket(url, ['a', 'a'])throws aSyntaxError- A string longer than V8 accepts throws a
RangeErrorinstead of aborting import()of a module that threw rejects with the module's exception- Inline scripts report errors at their position in the document
- Timers run on the initial
about:blankpage - Pending timer cap raised from 8192 to 65536
Scripts
- The parser runs microtasks before preparing a
<script>, so aMutationObservercan change its type first - Dynamic scripts with
async=falserun in order; dynamic scripts can't bedefer; inline modules run like external ones - Already-fetched async scripts now run from a task, after the markup that follows them
<script src="">fireserrorinstead of fetching the page
Cookies / HTTP
- A non-secure origin can't set or overwrite a
Securecookie (RFC 6265bis) - The cookie jar evicts old cookies past Chrome's limits instead of failing the response
- A cookie with neither a name nor a value is ignored; IP addresses are each their own site
- The HTTP cache skips
Rangerequests and URLs with userinfo;Varymatching fixed --http-cache-set-cookie=skip|store|stripadded (experimental,storeandstripneed--experimental-features)- DNS lookups are shared across connections
- The robots.txt cache now expires after 24 hours
- Web Bot Auth:
Signature-Agentis the quoted origin, and each signed request has a nonce
CDP
- File downloads (
Browser.setDownloadBehavior), saved to disk or streamed - Accessibility domain completed:
getRootAXNode,getAXNodeAndAncestors,getChildAXNodes; shadow DOM is now walked in the AX tree Page.setDocumentContent(Puppeteerpage.setContent())Performance.getMetrics(Timestamp,JSHeapUsedSize,JSHeapTotalSize)Input.setInterceptDragsandInput.dispatchDragEventCSS.getComputedStyleForNodeDOM.getContentQuadsandDOM.getBoxModelfor text nodesPage.navigateToHistoryEntryrestores a same-document entry in placeFetch.fulfillRequestnow stores the response's cookiesNetwork.loadingFinished.encodedDataLengthnow reports the bytes received- An unknown context returns Chrome's error code and message
/json/protocolupdated
Tools / MCP
downloadtool, streamed to diskpageToolsandcallPageTool: list and call the page's WebMCP toolsclassify,acceptCookiesandlogintools (TypeSafe Jev withTYPESAFE_API_KEY)- MCP
runtool: run a PandaScript by source or by path - MCP stdio:
notifications/cancelledstops the in-flight tool call tree: ARIAcheckedandexpandedstatesinteractiveElementsreports whether an element is in a fixed or sticky overlay- Structured data: microdata
- A missing required argument is now named in the error;
nullmeans unset - A
backendNodeIdwhose node left the document is rejected - Markdown: empty code spans dropped, no inline markup inside code
- Redacted dumps keep an empty password field empty
Agent
- xAI (Grok) provider,
XAI_API_KEY - LLMD provider and Parallel search (
PARALLEL_API_KEY) - REPL tool commands take a prompt (
/click the add to cart button), recorded with explicit selectors for/save - The REPL exits when its terminal goes away
- Ctrl-C and timeouts now stop a script that loops after an
await
WebDriver
POST /session/{id}/window
Performance / stability
- Compiled scripts (classic and modules) are stored in the HTTP cache
- Single-threaded arena allocator (~10% faster on WPT)
- Faster V8 ↔ Zig calls (~10%)
- Faster style matching, selector lists, class and sibling selectors,
getTag() - Inline transforms no longer drop the cascade's memos
- Cookie jar stored per site
- Arenas free blocks they can't keep instead of keeping them in place
- Response bodies are no longer buffered in the transfer's arena
- Faster startup on macOS
- Crash and UAF fixes:
call_arenain nested calls, EventSource double abort,document.write, structured-clonedFileList,DataCloneErrormessages, WebMCP tool errors, stale tool registry nodes
Security
- brotli updated to 1.2.1
Build
- Nix package and dev shell