Skip to content

The State of Progressive Web Apps in 2026

Progressive Web Apps in September 2026 are easier to install and harder to define than at any point since the term was coined. Apple removed every installability requirement on iPhone and iPad, Chromium rebuilt how installed apps update, move between origins and get installed in the first place, and Firefox came back to desktop web apps after four years without them. This post goes through what each engine shipped between early 2025 and September 2026, what still separates the platforms, and which pending decisions will shape the next year.

Key takeaways

  • Installation stopped being a quality gate. Since iOS and iPadOS 26 every site added to the Home Screen opens as a web app by default, Chrome can install any page from its menu, and Firefox on Windows pins any site to the taskbar. The manifest and the service worker now improve an app instead of qualifying it.
  • Apple shipped the most PWA-relevant changes of the period: Declarative Web Push (Safari 18.4 on iOS, 18.5 on macOS), Open as Web App by default (iOS 26), and the service worker Static Routing API (Safari 27).
  • Chromium focused on the lifecycle of installed apps: unthrottled manifest update checks (Chrome 144), same-site origin migration (Chrome 150), scope_extensions (Chrome 139), link capturing on by default on desktop (Chrome 138–140), and native notification attribution on macOS (Chrome 152).
  • Site-initiated installation is the open fight. navigator.install() has an intent to ship on desktop in Chrome 156, WebKit's standards position is oppose, and Mozilla has no position.
  • Firefox is back on the desktop, on Windows only. Taskbar web apps arrived in Firefox 143 and reached the Microsoft Store build in Firefox 150. There's still no install event and no manifest-driven integration.
  • The gaps are the same ones as in 2023: background execution, OS integration and hardware APIs remain Chromium-only (Firefox's add-on-gated Web Serial is the one exception), and iOS still has no install API at all.

The period at a glance

The table lists the changes from January 2025 to September 2026 that affect how you build, install, update or re-engage users with a PWA. Dates are stable-channel releases. Each row links to the page on this site that covers the feature in depth.

Date Engine Change Covered in
March 31, 2025 WebKit Safari 18.4: Declarative Web Push for Home Screen web apps, Wake Lock fixed in Home Screen web apps, Cookie Store API Web Push on iOS & Safari
May 12, 2025 WebKit Safari 18.5: Declarative Web Push on macOS Same
August 5, 2025 Blink Chrome 139: scope_extensions ships on desktop after an origin trial Advanced & Integration Members
September 15, 2025 WebKit Safari 26 / iOS 26: every site added to the Home Screen opens as a web app iOS & iPadOS
September 16, 2025 Gecko Firefox 143: web apps pinned to the Windows taskbar Desktop Platforms
December 2, 2025 Blink navigator.install() origin trial starts (Chrome and Edge 143) Install Prompts & Custom UI
December 12, 2025 WebKit Safari 26.2: Navigation API; iOS 26.2 allows alternative browser engines in Japan Platform Support
January 13, 2026 Blink Chrome 144: manifest update checks on every page load, name and icon changes offered for review App Identity & Updates
April 21, 2026 Gecko Firefox 150: taskbar web apps in the Microsoft Store build Installation by Platform
June 30, 2026 Blink Chrome 150: same-site origin migration (migrate_from, migrate_to) App Identity & Updates
August 25, 2026 Blink Chrome 152: notifications from installed PWAs on macOS carry the app's name and icon Notifications
September 14, 2026 WebKit Safari 27: service worker Static Routing API Static Routing API
September 2026 Blink Intent to ship navigator.install() and <install> on desktop in Chrome 156 Install Prompts & Custom UI

Current stable releases when this post was written: Chrome 154 (September 22, 2026), Edge 153, Firefox 156 (September 15, 2026), Safari 27 (September 14, 2026) and Samsung Internet 30, which is built on Chromium 143. That last detail matters more than it looks: a Blink feature that shipped in Chrome 144 or later, including the new manifest update behavior, doesn't reach Samsung Internet users until Samsung rebases.

Apple: installation is no longer a gate

For fifteen years, a site had to ask to be a web app on iOS: first with the apple-mobile-web-app-capable meta tag, later with a manifest display of standalone or fullscreen. Anything else added to the Home Screen was a bookmark that opened Safari. In 2025 and 2026 Apple dismantled that model and added the two features developers had asked for most: push that can't be silently lost, and a way to keep the service worker off the critical path.

iOS 26: every Home Screen site is a web app

Safari 26, shipped with iOS and iPadOS 26 on September 15, 2025, changed the default of Add to Home Screen. WebKit's release post: "By default, every website added to the Home Screen opens as a web app. If the user prefers to add a bookmark for their browser, they can disable 'Open as Web App' when adding to Home Screen." And, in a sentence that ends a long-running debate: "There are now zero requirements for 'installability' in Safari."

Three consequences are easy to miss:

  1. Sites that never considered being an app now are one. A Home Screen web app has no back button, no reload button and no address bar. If your site relies on browser chrome for navigation, a user who adds it to the Home Screen gets a trapped experience. iOS & iPadOS covers in-app back navigation, out-of-scope links (which open in an in-app Safari view) and the OAuth pitfalls that follow.
  2. Push became available to manifest-less sites. Web Push on iOS still requires a Home Screen web app, but any site can now become one. A site that registers a service worker, or uses the declarative window.pushManager described below, can subscribe once the user adds it with the toggle on.
  3. The user decides, not the manifest. A user can create a bookmark for a site that declares standalone, and a web app for a site that declares nothing. Detect the context at runtime with display-mode and navigator.standalone instead of assuming.

What didn't change: installation is still manual, from the Share sheet, with no beforeinstallprompt or appinstalled event. Other iOS browsers have been able to add web apps since iOS 16.4, and the result is always the same WebKit web app, with its own storage, its own permissions and cookies copied from the browser once at creation (iOS 17.2 and later).

Safari 26 also changed how theme-color works: MDN records that "from Safari on iOS 26, the theme color is only used for installed web apps". In tabs, Safari derives its toolbar tint from the page itself. If you tuned theme-color for the Safari tab bar, that tuning now only applies inside the installed app.

The Mac got the same model two years earlier. Safari 17 on macOS Sonoma lets users add any site to the Dock, "even if the site does not have a manifest file (or legacy meta tags)", and Safari 18 made in-scope links from other apps open in the Dock app. Apple's platforms now treat installation as a purely user-initiated act with no criteria at all.

Declarative Web Push: push that survives without a service worker

WebKit introduced Declarative Web Push on March 27, 2025. It shipped in Safari 18.4 for Home Screen web apps on iOS and iPadOS 18.4 (March 31, 2025) and in Safari 18.5 on macOS (May 12, 2025). The idea is simple: the push payload describes the notification, and the browser shows it without running any JavaScript.

declarative-message.json
{
  "web_push": 8030,
  "notification": {
    "title": "Your order has shipped",
    "body": "Order 8812 is on its way.",
    "navigate": "https://shop.example/orders/8812",
    "lang": "en-US",
    "dir": "ltr",
    "tag": "order-8812",
    "data": { "orderId": 8812 }
  },
  "mutable": false,
  "app_badge": 3
}

The web_push: 8030 key opts the message into declarative handling, and notification.title and notification.navigate are required. WebKit's motivations explain why this matters more on Apple platforms than elsewhere:

  • The silent push penalty goes away. WebKit gives a service worker 30 seconds to call showNotification() for every push, and removes the origin's push subscriptions after the third push that doesn't produce one. A declarative message always has something to show, so it's exempt.
  • Subscriptions outlive the service worker. Intelligent Tracking Prevention can delete a site's service worker registration. A subscription created with window.pushManager doesn't depend on one, and WebKit says that "the removal of that service worker registration will not affect the associated push subscription".
  • It's cheaper. On iOS, an immutable declarative message is displayed by the system daemon without starting a web content process.

With "mutable": true, a service worker still receives a push event (with event.notification set and event.data null) and may replace the proposed notification, for example to decrypt an end-to-end encrypted preview. If it throws or times out, Safari shows the declarative notification anyway. That is the UNNotificationServiceExtension model from native iOS, brought to the web.

Two practical details from Web Push on iOS & Safari: WebKit's parser is stricter than the specification (a wrong type anywhere turns the message into a classic push, and the silent push rule applies again), and the placement of mutable and app_badge moved after the first release. Validate payloads on the server.

Only Safari ships the declarative format. Because it's plain JSON inside an ordinary encrypted push, you can still send it to every browser: Chrome and Firefox deliver it to your service worker's push handler, which can build the notification from the same fields. Sending one format everywhere is the pragmatic 2026 default.

Safari 27: static routing on Apple platforms

Safari 27, released on September 14, 2026 with iOS 27, iPadOS 27 and macOS 27, shipped the service worker Static Routing API. Chrome has had it since 123 (March 2024). A worker declares routing rules during install, and the browser applies them without starting the worker, which removes worker startup cost from the requests you route to the network or the cache.

sw.js
self.addEventListener("install", (event) => {
  // InstallEvent.addRoutes(): Chrome 123+, Safari 27+. Firefox exposes install
  // as a plain ExtendableEvent, so the method is undefined there.
  if (typeof event.addRoutes === "function") {
    event.waitUntil(
      event.addRoutes([
        // API calls never need the worker: go straight to the network.
        { condition: { urlPattern: new URLPattern({ pathname: "/api/*" }) }, source: "network" },
        // Navigations: race the network against the fetch handler.
        { condition: { requestMode: "navigate" }, source: "race-network-and-fetch-handler" },
      ]).catch((error) => {
        // A rejected route list must not fail the install: fall back to fetch handling.
        console.warn("Static routes rejected:", error);
      }),
    );
  }
});

self.addEventListener("activate", (event) => {
  // Navigation preload covers browsers without static routing (Firefox 99+).
  // Only enable it if your fetch handler reads event.preloadResponse for
  // navigations; otherwise every navigation pays for a request nobody uses.
  event.waitUntil(self.registration.navigationPreload?.enable() ?? Promise.resolve());
});

With WebKit and Blink both shipping it, static routing moved from a Chromium optimization to something most of your mobile traffic can use. Mozilla's standards position is positive, but Firefox has no implementation, so every route must still be handled correctly by your fetch handler. Static Routing API covers the rule syntax, the limits Safari 27 enforces, and the Resource Timing fields that tell you which source served a request.

WebKit's Safari 27 feature post contains no entries about Home Screen or Dock web apps, and no push-specific changes. The other additions relevant to PWAs are smaller:

  • Transferable streams. ReadableStream can now be transferred with postMessage(), so a page and its service worker can hand each other a stream instead of buffering a whole body. WritableStream and TransformStream are still not transferable in Safari. Safari 27 also adds ReadableStream.from() and for await...of over a ReadableStream, which simplify streaming responses.
  • maxAge in cookieStore.set(), which the Cookie Store API now supports in every engine (Chrome 145, Firefox 148, Safari 27, according to MDN).
  • Secure cookies on http://localhost, which removes one difference between local development and production.
  • ariaNotify(), which MDN's data lists in Safari 27 (after Chrome 141 and Firefox 150), for announcing status changes such as "sync complete" to screen readers without a live region (see Accessibility).

What Apple still doesn't do

The list of missing features on iOS is almost unchanged since 2023:

  • No install API. No beforeinstallprompt, no appinstalled, and WebKit opposes the Web Install API. Instructions are the only option, which Install Prompts & Custom UI shows how to build well.
  • No background execution except push. No Background Sync, Periodic Background Sync or Background Fetch. Offline writes have to be flushed when the app is launched or becomes visible.
  • No OS integration from the manifest. No share_target, file_handlers, protocol_handlers or shortcuts on iOS (macOS Dock apps have supported shortcuts since Safari 17.4), and no background_color splash.
  • No notification actions. Safari ignores actions, image, badge and requireInteraction.
  • No Fugu hardware APIs. No Web Bluetooth, WebUSB, Web Serial, WebHID or Web NFC.

None of this is new, and none of it has a public timeline. Plan for it as a permanent condition.

Alternative engines: allowed, but not for web apps

The EU's Digital Markets Act has allowed alternative browser engines on iOS since iOS 17.4 (March 5, 2024), and Japan's Mobile Software Competition Act followed with iOS 26.2 (December 12, 2025). Neither changes what a PWA runs on. After the iOS 17.4 beta episode, Apple committed that Home Screen web apps "continue to be built directly on WebKit and its security architecture", and it hasn't documented any way for another engine to power them.

The question may be academic for now anyway. Open Web Advocacy reported in July 2025 that, fifteen months after the DMA came into force, no browser vendor had ported a competing engine to iOS, and its June 2026 post described only a Blink prototype from Microsoft's Edge team running on iOS 26.5.1. For planning, every iOS user in every region gets WebKit's feature set. Platform Support has the entitlement requirements and the regional details.

Chromium: rebuilding the lifecycle of installed apps

Blink shipped fewer headline capabilities in this period than in the Project Fugu years. Most of its work went into what happens around an installed app: how it's installed, how it updates, which URLs belong to it and how it moves.

The Web Install API and the <install> element

beforeinstallprompt has two limits. It fires only when Chromium's heuristics decide the current page is promotable, and it can only install the document the user is looking at. Microsoft's Web Install API removes both: navigator.install() installs the current app, or another app identified by its manifest URL, from a user gesture. The WICG <install> element is a browser-rendered button backed by the same algorithm.

The timeline, from Install Prompts & Custom UI and Chrome Platform Status:

Milestone navigator.install() <install>
Developer trial Chrome 139 desktop, behind a flag Behind a flag
Origin trial Chrome and Edge 143 to 148, extended through 150 Chrome and Edge 148 to 153
Design change Edge 153 deprecated the document-URL form in favor of { manifest } Trial attributes installurl/manifestid replaced by manifest/manifestId
Intent to ship Desktop, Chrome 156 Desktop, Chrome 156
Android No milestone No milestone

Chrome 156 is scheduled for stable on October 20, 2026. Chrome Platform Status lists WebKit's position as oppose and Gecko's as no signal. WebKit's argument is that installation is a user decision whose flow should start in browser UI, not on a web page, which is consistent with how Apple designed Add to Home Screen and Add to Dock.

Experimental

As of September 2026, neither navigator.install() nor <install> is enabled by default in any stable browser. The API shape changed twice during the trials. Feature-detect, keep beforeinstallprompt and manual instructions as fallbacks, and check the explainer before shipping code against it.

If Chrome 156 ships it, your install button needs three paths, in this order:

install.js
// Picks the best install mechanism available. Call from a click handler:
// every path below needs transient user activation.
let deferredPrompt = null;
window.addEventListener("beforeinstallprompt", (event) => {
  event.preventDefault(); // keep the event for our own button (Chromium)
  deferredPrompt = event;
});

export async function installApp() {
  // 1. Web Install API (Chromium, experimental). The manifest must declare "id".
  if ("install" in navigator) {
    try {
      await navigator.install();
      return "installed";
    } catch (error) {
      if (error.name === "AbortError") return "dismissed"; // user said no
      // DataError: manifest fetch/parse/id problem. NotAllowedError: no gesture.
      console.warn("navigator.install() failed:", error.name, error.message);
      // Activation was consumed, so the fallback below may be rejected as well.
    }
  }

  // 2. beforeinstallprompt (Chromium, when the browser considers the page promotable).
  if (deferredPrompt) {
    const promptEvent = deferredPrompt;
    deferredPrompt = null; // prompt() works once per event
    await promptEvent.prompt();
    const { outcome } = await promptEvent.userChoice;
    return outcome === "accepted" ? "installed" : "dismissed";
  }

  // 3. Everything else: Safari on iOS and macOS, Firefox. Show instructions.
  return "instructions";
}

The cross-origin form (navigator.install({ manifest })) is the part with no precedent: an app catalog or a suite's portal could install sibling apps on other origins, after the browser asks for the web-app-installation permission for the calling origin. Whether that's a useful distribution channel or an abuse vector is exactly what WebKit and Chromium disagree about.

Manifest updates stop being a guessing game

Before 2026, updating an installed desktop app's name, icons or other manifest members was slow and opaque: Chrome checked at most once a day, only under specific conditions, and a changed name or icon produced a blocking confirmation dialog. From Chrome 144 on desktop, as the Chrome team announced in January 2026:

  • Every page load checks. Whenever a page that links a manifest with a matching id becomes the primary page of a tab or app window, Chrome schedules an update check. No daily throttle, no requirement that the page be start_url or run in the app window.
  • Most members apply silently and immediately, including start_url, scope, display, display_override, theme_color, background_color, shortcuts, share_target, file_handlers, protocol_handlers, launch_handler and scope_extensions.
  • Name and icon changes become a suggestion. They're stored as a pending update and offered as Review app update in the app menu. The user can accept or ignore it. Icon changes under 10% pixel difference apply silently, at most once a day.
  • Icons are compared by manifest entry, not by bytes. Replacing the file behind an unchanged URL does nothing. Publish new icons under new URLs.

The design follows the manifest specification's split between security-sensitive members (what the user recognizes the app by) and everything else. For you it means manifest changes now reach desktop users within a page load, which makes it practical to roll out features like Window Controls Overlay or new file handlers to existing installs. Android still updates through the WebAPK minting service, at most daily. App Identity & Updates has the full comparison rules and the testing switches.

Origin migration in Chrome 150

Moving an installed app to a new origin used to mean asking every user to uninstall and reinstall. Chrome 150 (June 30, 2026) shipped PWA origin migration on desktop (MDN's compatibility data lists the manifest members from Chrome 149) for moves within the same site (same eTLD+1), such as www.example.com/social/ to social.example.com. The new manifest names the old app in migrate_from and must declare an explicit id. The old origin confirms the move in /.well-known/web-app-origin-association by listing the new app's id with "allow_migration": true, the same file format scope_extensions uses. An optional migrate_to in the old manifest lets Chrome discover the migration during an update check without the user ever visiting the new origin.

The limitation is significant: storage and permissions don't move. The explainer puts local data out of scope and says permissions aren't migrated in the initial version. The new origin starts with empty IndexedDB and Cache Storage and has to ask for notification permission again. Plan a migration like a new install that happens to keep its place on the user's taskbar.

Two changes on desktop Chromium made installed apps own their URLs more completely:

  • scope_extensions (Chrome 139, after an origin trial) lets one app span several origins. Each extra origin confirms the association with a web-app-origin-association file keyed by the app's manifest id. Navigations across those origins stay inside the app window instead of showing the out-of-scope bar. The shipped syntax ({"type": "origin", "origin": ...}) differs from the origin trial's, and the trial's *. wildcards are ignored. Chrome Platform Status records desktop only; MDN's data also lists Android, which this site recommends treating as untested until you've verified link handling there. See Advanced & Integration Members.
  • Link capturing on by default on Windows, macOS and Linux. After a staged rollout that began in Chrome 134, link capturing became the default in Chrome 138 for apps that declare launch_handler.client_mode and in Chrome 140 for all installed apps. It applies only to navigations that would open a new browsing context (links that open a new tab or window, and links from other apps) and fall within an installed app's scope; the user can opt out per app. Same-tab navigations aren't captured. launch_handler decides which window receives the launch. On ChromeOS link capturing is available but off by default per app. Protocol Handlers & Launch Handling shows how to handle launches with launchQueue.

Together with Safari 18's link handling on macOS, this brings desktop web apps close to how Android WebAPKs have captured links through intent filters for years.

Notifications, windows and the rest of Chrome's year

Smaller changes that matter for installed apps:

  • Chrome 152 (August 2026) attributes notifications from installed PWAs on macOS to the app itself, under its own name and icon, instead of to "Google Chrome". The app gets its own entry in macOS notification settings. Two side effects: requireInteraction is no longer supported on macOS, because persistence becomes the user's per-app Banners or Alerts choice, and badges from installed PWAs on macOS now need notification permission. See Notifications and Badging API.
  • Chrome 152 also shipped window-drag: move | none from CSS Basic User Interface Level 4 and made app-region an alias of it, which standardizes the drag regions Window Controls Overlay apps depend on.
  • Chrome 146 stopped re-delivering the last LaunchParams to launchQueue on reload, fixing a long-standing source of duplicate file opens.
  • Background Fetch survived a deprecation attempt. Chromium engineers posted an intent to deprecate in November 2025, citing usage below 0.00002% of page loads. It didn't reach consensus and the API stays, but Chrome 149 rejects backgroundFetch.fetch() called from a service worker by default (NotAllowedError, with a temporary enterprise policy to lift it), and Chrome Platform Status lists CORS and Local Network Access enforcement for background fetches in Chrome 154, the current stable release. Background Fetch covers the changes.

Isolated Web Apps: still managed-only

Isolated Web Apps, Chromium's signed and packaged apps with access to Direct Sockets and Controlled Frame, remain an enterprise feature. Google's documentation lists them as supported only on ChromeOS, installed by administrators through policy, and since Chrome 143 only for apps on Google's allowlist. ChromeOS 150 added user installs, but only where the administrator allows them. Windows support in enterprise-managed Chrome has been announced and then postponed: an earlier edition of Google's enterprise release notes targeted Chrome 150, and the current notes list it for Chrome 161. There is still no path for an unmanaged consumer device. Isolated Web Apps covers the model and its status.

Firefox: back on the desktop, on one platform

Mozilla removed Firefox's experimental desktop "Site Specific Browser" in Firefox 86 (February 2021). For more than four years desktop Firefox had no way to run a site as an app. That changed in two steps:

  • Firefox 143 (September 16, 2025): "On Windows, Firefox now supports running websites as web apps pinned directly to the taskbar." The windows are simplified Firefox windows that keep access to installed add-ons. The Microsoft Store build was excluded.
  • Firefox 150 (April 21, 2026) made web apps available to Windows users who installed Firefox from the Microsoft Store.

Firefox's source documentation, where the feature is called Taskbar Tabs, fills in the rest. It's enabled by default on Windows, present but disabled by default on Linux behind browser.taskbarTabs.enabled, and unavailable on macOS, because the Dock assumes each visible application is a separate process, while Firefox web apps share the browser's process and profile. Each web app is keyed by a Firefox-generated identifier rather than your manifest id, and tied to the container it was created in. Firefox reads name, start_url and the scope from your manifest if there is one. MDN's data says these windows match display-mode: minimal-ui.

What Firefox deliberately doesn't offer: no beforeinstallprompt, no appinstalled, no shortcuts, no file or protocol handling, and no documented manifest update pipeline. This is the Safari model (the user pins a site; the site can't ask) more than the Chromium model.

Gecko's platform work in the same period closed several smaller gaps that affect PWAs:

Firefox release Change relevant to PWAs
144 screen.orientation.lock() on Android and Windows tablets; same-document View Transitions
147 Module service workers (type: "module"), Navigation API
150 Taskbar web apps in the Microsoft Store build; ariaNotify()
151 Web Serial on desktop, gated behind a site-permission add-on
152 Notification actions, NotificationEvent.action and Notification.maxActions

Module service workers in Firefox 147 matter more than their size suggests: with Chrome 91 and Safari 15 already supporting them, navigator.serviceWorker.register(url, { type: "module" }) finally works in every current engine, and build tools no longer need a classic-script fallback for current browsers. Firefox ESR releases before 147 still lack them.

Firefox for Android is unchanged: manifest-based installs create a Firefox-badged launcher shortcut that opens in a standalone activity, not a WebAPK.

Capabilities that shipped in 2025–2026

The table collects the features that shipped by default in at least one stable engine during the period and that PWA developers are likely to use. Versions are first stable releases.

Capability Chromium Firefox Safari Notes
Declarative Web Push ❌ ❌ ✅ 18.4 iOS, 18.5 macOS Home Screen web apps only on iOS
NotificationOptions.navigate ❌ 🧪 preview ✅ 18.4 Opens the URL without notificationclick
Static routing (addRoutes()) ✅ 123 ❌ ✅ 27 Firefox position positive, no implementation
Module service workers ✅ 91 ✅ 147 ✅ 15 Now in every engine
Navigation API ✅ 102 ✅ 147 ✅ 26.2 Now in every engine; useful for in-app back buttons
Cookie Store API ✅ 87 ✅ 140 ✅ 18.4 Now in every engine; maxAge in Chrome 145, Firefox 148, Safari 27
Notification actions ✅ 48 ✅ 152 ❌ Read Notification.maxActions for the limit (2 in Chromium)
scope_extensions ✅ 139 desktop ❌ ❌ New syntax, not the origin trial's
Manifest update review flow ✅ 144 desktop ❌ ❌ Name and icon changes need user review
Origin migration (migrate_from) ✅ 150 desktop ❌ ❌ Same-site only; storage doesn't move
Native notification attribution on macOS ✅ 152 – ✅ web apps since 17 Chrome: installed PWAs only
Web Serial ✅ 89 desktop, 148 Android ⚠️ 151 (desktop; add-on gated) ❌ Safari opposes; Firefox requires a site-permission add-on
Screen Wake Lock in Home Screen web apps – – ✅ 18.4 Worked only in tabs on iOS 16.4 to 18.3
Web apps without a manifest ✅ menu install (128) ✅ 143 Windows ✅ 17 macOS, 26 iOS User-initiated in every engine

Support data as of September 2026. Check MDN and caniuse for live data, and Platform Support for the full matrix.

What's still missing in 2026

The capability gap between engines is narrower than it was, but its shape hasn't changed. Everything below is either Chromium-only or absent everywhere.

Background execution

Background Sync, Periodic Background Sync and Background Fetch are Chromium-only, and Mozilla's standards positions on the two sync APIs are negative, citing tracking concerns. On iOS, the only way to run code while the app isn't in the foreground is to handle a push. The durable pattern is an IndexedDB outbox flushed on launch, visibilitychange and online, with Background Sync as an enhancement where it exists. Offline-First Data & Sync builds it.

Installation you can trigger

Only Chromium lets a page trigger installation, through beforeinstallprompt today and possibly navigator.install() from Chrome 156. Safari (on every Apple platform) and Firefox have no install event and no stated plan to add one. The "zero requirements" model makes installation easier for users and harder to promote: you can explain it, but you can't offer a button that does it.

OS integration from the manifest

share_target, file_handlers, protocol_handlers, launch_handler, display_override, Window Controls Overlay and the rich install UI (screenshots, description) are Chromium-only, and several are split further: share_target works on Android and ChromeOS but not on Windows or macOS, and file_handlers only on desktop. Safari reads a small subset of the manifest (name, start_url, scope, display, id, theme color and icons when there's no apple-touch-icon), and desktop Firefox treats the manifest as a source of a name and a start URL.

Badging on Android and Linux

The Badging API resolves on Chrome for Android and on Linux without doing anything. Android shows a notification dot instead, and Linux has no system-level badging API. Keep counts visible in your own UI.

Hardware and high-trust APIs

Web Bluetooth, WebUSB, WebHID and Web NFC remain Chromium-only, with negative positions from WebKit and, for most, Mozilla. Web Serial's arrival in Firefox 151 on desktop, gated behind a site-permission add-on, is the first crack in that pattern, but Safari opposes it. Raw sockets exist only for Isolated Web Apps, which consumers can't install. Hardware & Device APIs has the per-API status.

Consistency of installed-app behavior

Even the features that work everywhere behave differently once installed. Safari's web apps get their own storage container (cookies copied once at creation), while Chromium and Firefox web apps share the browser profile. Uninstalling deletes data only in Safari by default. Manifest updates reach installed apps within a page load on desktop Chromium, within about a day on Android, and through no documented mechanism on Safari or Firefox. Installation by Platform documents each combination; test the ones your analytics say matter.

What the changes mean for a PWA you ship today

A few practical adjustments follow from the period's changes:

  1. Design for being installed even if you never ask for it. iOS 26, Chrome's Install page as app and Firefox's taskbar pinning mean any page can end up in a standalone window. Provide in-app navigation back to the start, handle out-of-scope links, and test your site as an installed app on iOS.
  2. Set a stable manifest id now. Chrome's update pipeline, origin migration, scope_extensions, the Web Install API and iOS's Focus sync all key off it. Without an explicit id, it defaults to start_url, and changing that later creates a new app.
  3. Version icon URLs. With Chrome 144's comparison by manifest entry, a new icon under an old URL never reaches installed users.
  4. Send push payloads in the declarative format. It protects Safari subscriptions from the silent push penalty and costs nothing in other browsers, as long as your service worker parses the same JSON.
  5. Add static routes for requests the worker doesn't need. Chrome and Safari both honor them, and they're ignored safely elsewhere. Keep navigation preload for Firefox.
  6. Feature-detect installation in layers. navigator.install() where it exists, beforeinstallprompt where it fires, instructions everywhere else, with separate wording for iOS, macOS Safari and Firefox on Windows.
  7. Re-check what "installed" means in your analytics. On iOS 26 and later, Home Screen launches include sites whose authors never shipped a manifest. Don't count only display-mode: standalone: MDN's compatibility data notes that in an iOS web app whose manifest declares standalone, display-mode: fullscreen matches and standalone doesn't (WebKit bug 264218), and Firefox taskbar windows report minimal-ui. Test standalone, fullscreen and minimal-ui plus navigator.standalone. Analytics for PWAs covers display-mode segmentation.

What to watch in the next twelve months

These are the decisions and releases most likely to change the picture by September 2027. None has a guaranteed outcome.

  • Chrome 156 and the Web Install API. Whether navigator.install() and <install> ship on October 20, 2026 as the intent states, whether Android follows, and whether Edge ships them in the same release. With WebKit opposed and Mozilla silent, a Chromium-only install API would be the clearest example yet of the engines diverging on what an installed web app is.
  • Mozilla's position on Web Install and on macOS web apps. Firefox's documentation names the process model as the obstacle on macOS. A change there would make installation available in all three engines on every desktop.
  • Declarative Web Push beyond Safari. The format has been merged into the Push API editor's draft, and MDN lists Notification.navigate as a Firefox preview feature. A second implementation would make the declarative format the default way to send push.
  • Static routing in Firefox. Mozilla's position is positive and the implementation bug is open. Shipping it would make static routing a cross-browser baseline.
  • Background Fetch after Chrome 154's CORS and Local Network Access changes, and whether Chromium revisits its deprecation. Any Chromium-only background API with tiny usage is at risk, and that's an argument for keeping foreground fallbacks for all of them.
  • Alternative engines on iOS. If a Blink or Gecko browser ships in the EU or Japan, its users get that engine's features in the browser, but Home Screen web apps stay on WebKit unless Apple changes its architecture. Watch for any documentation from Apple that changes that last point.
  • Isolated Web Apps outside ChromeOS. Enterprise-managed Windows support slipped from Chrome 150 to Chrome 161 in Google's enterprise release notes, so it's unlikely before early 2027. Wider availability would bring raw sockets and Controlled Frame to a larger, but still managed, audience.

The bottom line

In 2026 the question "does this browser support PWAs?" has a clear answer everywhere: yes, all three engines run service workers, cache offline, send push and let users put a web app on their home screen, taskbar or Dock. The interesting questions have moved one level down: who may trigger installation, how an installed app updates and changes identity, and whether background and OS integration APIs ever leave Chromium. Build a baseline that works in WebKit, add Chromium's integrations as enhancements, and keep feature detection at every boundary, because the most important change of the next year, a site-initiated install API, is likely to exist in only one engine.

Further reading

On this site

External references