Safari 27's four web extension upgrades — and our forecast missed them
Safari 27 web extensions get runtime.getDocumentId(), user-gesture propagation, a tabId for windows.create and error reporting. What landed, what to do.

Apple shipped Safari 27.0 on September 14. Three days later, WebKit published its Safari 27.0 feature roundup. Between the CSS and JavaScript headlines sat four changes for Safari 27 web extensions. If you ship a Safari build, all four deserve a look.
Here's the embarrassing part. When Chrome 154 shipped its async-listener fix last month, I could name the exact Chromium CL and the day our signal feed caught it. Safari 27 went the other way: our forecast pipeline first logged it on September 28, eleven days after the WebKit post. It never made a prediction (first_forecast_at was never set).
It wasn't hidden, either — Safari 27 had been in beta since June. My pipeline just doesn't watch Apple's release notes directly. That's a gap in my tooling, not proof that nobody saw it coming.
So here's the retrospective: what landed, how it compares, and what to do now.
What landed for Safari 27 web extensions
Per WebKit's post and Apple's Safari 27 release notes, Safari 27.0 adds:
runtime.getDocumentId()— returns the UUID of the document behind a window or a frame element (iframe,frame,embed,object).- Error reporting for extension scripts — Safari now reports uncaught exceptions and unhandled promise rejections from extension scripts.
- User-activation propagation — a user gesture now carries through
sendMessage(),connect(),postMessage(), andexecuteScript(). Gesture-gated actions, like media playback, can now work on the far side of a message hop. tabIdinwindows.create()— you can move an existing tab into a new window in one call.
The release also brings platform changes extension code can use: a rewritten ES module loader that fixes top-level await, ReadableStream async iteration and transfer via postMessage(), maxAge in the Cookie Store API, and Secure cookies on plain-HTTP loopback hosts.
Mostly catch-up, with one surprise
Two of the four close gaps you can see in MDN's compatibility data. The other two change how extensions behave and how you debug them.
windows.create({tabId}) is the classic case. MDN's compat data lists tabId in windows.create() for Chrome since version 10 and Firefox since 45. It's the obvious call for any tab manager that pops a tab out into its own window. On Safari, that flow needed its own code path until now.
runtime.getDocumentId() is the surprise, because it's new. Firefox only added it in Firefox 153, released July 21, 2026. Chrome doesn't have it: its runtime API reference exposes document IDs on objects like MessageSender, but no lookup method. MDN's browser-compat-data lists Chrome as unsupported.
So Safari is the second browser to ship it, two months after Firefox. For once, Safari isn't last.
User activation is the one I'd call a real bug-class killer. Before 27.0, Safari didn't carry a gesture through those messaging calls. So "click the popup, play media from the content script" could fail on Safari. You can't feature-detect that, so the usual fix was a weaker Safari build.
And error reporting? Small bullet, real daily impact: a script that throws without a trace is the worst bug to chase.
What our catalog can and can't count
Careful here, because this number is easy to misread. Our catalog tracks the Chrome Web Store, Firefox Add-ons and Edge Add-ons — not Safari. So I can't count the Safari extensions these changes touch.
What I can count is the Manifest V3 pool on those three stores: 336,628 MV3 listings with a combined ~3.78 billion store-reported users. That's context, not an "affected" count. A listing on two stores counts twice. Users are summed per listing, so one person with five extensions counts five times.
The largest listings in that pool include uBlock Origin Lite, AdGuard AdBlocker, Adblock Plus, Grammarly, Google Translate, Microsoft Single Sign-On, McAfee WebAdvisor and Claude. Our data doesn't show which of them ship a Safari build. If yours does, you may get to delete some Safari-only branches.
One more number: 20,002 of those listings (~230M combined users) were already flagged unavailable in their store at our last scan. No Safari API helps an extension that's gone. Worth a quick check of your own toolbar (browse the catalog).
The honest caveat
Four platform changes don't add up to a Safari audience. Shipping to Safari still means the conversion toolchain, Xcode, Apple's review process and a separate distribution channel. None of that got cheaper with 27.0. What got cheaper is the code: fewer if (isSafari) { degrade() } branches, fewer stripped features, fewer "works in Chrome" tickets.
My read: API friction was one reason developers skipped Safari, and some of it just left the building.
What to do now
- Feature-detect, don't version-sniff.
typeof globalThis.browser?.runtime?.getDocumentId === "function"is the safe check. Chrome doesn't ship the method, and older Safari versions stay in the wild. - Already ship a Safari build? Test it on Safari 27.0 this week. Gesture-gated flows that used to fail may just work, and the new error reporting may surface bugs that were always there.
- Never shipped to Safari? Re-run the ROI math. The API gaps are smaller now; what's left is mostly packaging and review cost.
- Starting a fresh MV3 manifest? My free Manifest V3 generator checks it against Chrome, Firefox and Edge store policy as you type. Safari isn't one of its targets, so you'd still run the result through Apple's converter. The
@extenshi/cliscanner runs a pre-publish security scan before you upload — 3 free scans with a free account, one-time, then prepaid packs.
See where your extension stands in the catalog → — its manifest version and store status on Chrome, Firefox and Edge.
Sources
- WebKit Features for Safari 27.0 — WebKit blog, September 17, 2026
- Safari 27 Release Notes — Apple Developer, released September 14, 2026
- runtime.getDocumentId() — MDN
- windows.create() — MDN
- Firefox 153 release notes for developers — MDN
- chrome.runtime API reference — Chrome for Developers
- webextensions/api/runtime.json — MDN browser-compat-data (GitHub)
Catalog numbers come from Extenshi's scans of MV3 listings and their store availability on the Chrome Web Store, Firefox Add-ons and Edge Add-ons, as of October 2026; counts shift as we re-scan. We don't track Safari. Technical claims come from the cited sources, which we don't independently verify. Naming an extension reflects its size in our catalog, not an accusation of wrongdoing. Spot an error? Tell us at [email protected].
Related Articles
Chrome 154 landed MV3's lost-event fix — for up to 276,820 Chrome extensions that can't use it yet
Chrome 154 shipped the async_listener_registration manifest key for MV3 service workers. Here's what landed, who it covers, and why you shouldn't switch yet.

Chrome's native browser namespace: what cross-browser extension devs should do now
Chrome added a native, promise-based browser.* namespace in 148. Across the 235,887 Chrome extensions we track, here's what it changes — and what to do.
Extension frameworks in 2026: how to pick the right one for your next project
WXT, Plasmo, CRXJS, Extension.js, and Bedframe — five browser extension frameworks compared by build time, bundle size, and maintenance health in 2026.
Sleeper extensions go cross-browser: how to find hidden malware in your Firefox, Chrome, and Edge add-ons
17 malicious sleeper extensions found across Firefox, Chrome, and Edge with 840K downloads. They hid malware in images for up to 5 years undetected.