# PWAs on iOS and Safari

> How PWAs install and run on iOS and iPadOS: Add to Home Screen, the Open as Web App switch, Web Push and badging for Home Screen apps, and storage limits.

On iOS and iPadOS a PWA is a Home Screen web app: the user adds the site from the Share
sheet, and from then on it opens outside the browser with its own App Switcher entry, and
can use service workers, Web Push, and badging if the site implements them. There is no
programmatic install step, so the platform work is teaching the gesture and designing for
what WebKit ships in each release.

## How it works

Three OS releases define the behaviour a site sees: iOS 16.4 (2023-03) made third-party
browsers and manifests part of the flow, iOS 18.4 (2025-03) added Declarative Web Push,
and iOS 26 (2025-09) made "open as a web app" the default for every added site.

### The Add to Home Screen gesture

Apple's iPhone guide
[Turn a website into an app in Safari on iPhone](https://support.apple.com/guide/iphone/open-as-web-app-iphea86e5236/ios)
documents the path in Safari (English UI): tap the Share button, scroll the list of
actions, tap **Add to Home Screen**, leave **Open as Web App** turned on, then tap **Add**.
If **Add to Home Screen** is missing from the sheet, the user restores it through **Edit
Actions** at the bottom of the list. The icon exists only on the device where it was added.

Since iOS and iPadOS 16.4 a third-party browser can offer the same action if, per the
[WebKit announcement](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/),
the app holds the `com.apple.developer.web-browser` managed entitlement, a `WKWebView`
showing an `http:` or `https:` document is in the Share sheet's `activityItems`, and the
device is not a Shared iPad.

### What decides web app versus bookmark

On iOS 16.4 through 18 the manifest decided: a site whose manifest set `display` to
`standalone` or `fullscreen` opened as a web app no matter which browser added it, and a
site without such a manifest (and without the legacy web-app-capable meta tag) became a
Home Screen bookmark that opens in the user's default browser.

iOS 26 and iPadOS 26 moved the decision to the user. WebKit's
[Safari 26.0 notes](https://webkit.org/blog/17333/webkit-features-in-safari-26-0/) state
that by default every website added to the Home Screen opens as a web app, that the user
can disable "Open as Web App" while adding to get a bookmark instead, and that there are
"zero requirements for installability" in Safari. A manifest still shapes the result: icons
declared in it are used, and `display`, `name`, and `start_url` apply.

### Icons and identity

Manifest icons have been read since iOS 15.4, but an `apple-touch-icon` link takes
precedence when both are present. With no icon at all, iOS 16.4 and later draw a monogram
from the first letter of the site's name on a colour taken from the site. The manifest
`id` member (16.4+) is combined with the name the user typed at add time to tell multiple
installs of one site apart, which is what lets Focus silence one copy and not another.

### APIs gated to the installed context

Web Push, the Notifications API, and the Badging API work in Home Screen web apps from
iOS 16.4; a Safari tab on iOS has none of them. Notification permission must be requested
in response to a user gesture such as a tap on a subscribe button, and `setAppBadge()`
changes the stored count even before permission is granted, showing it on the icon once
notifications are allowed. Declarative Web Push (iOS and iPadOS 18.4, macOS 15.5) adds
`window.pushManager` and displays notifications without a service worker; the original
push flow still subscribes through a service worker registration.

### Storage

Browser-stored data is best-effort unless the origin calls `navigator.storage.persist()`,
and Safari answers that call from the user's interaction history without showing a prompt.
With cross-site tracking prevention on, Safari deletes an origin's script-created data
after seven days of browser use with no tap or click on that origin; cookies set by the
server survive (MDN,
[Storage quotas and eviction criteria](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria)).
From iOS 17 a Home Screen web app gets the browser-app quota of about 60 % of the disk per
origin, not the 15 % an embedded `WKWebView` gets.

## Examples

Both snippets run in a Safari tab and in the Home Screen web app; the branches are what
differ.

### Subscribing to push with the declarative manager first

Which `PushManager` the page gets depends on the flavour available. The declarative one
hangs off `window` and needs no service worker; the original one lives on a registration
and has to wait for an active worker.

```js
subscribeButton.addEventListener('click', async () => {
  if (!('PushManager' in window) || !('Notification' in window)) {
    // A Safari tab on iOS, or any browser without push: offer an in-app inbox.
    showInAppInbox();
    return;
  }

  let pushManager;
  if ('pushManager' in window) {
    pushManager = window.pushManager; // Declarative Web Push, iOS 18.4+
  } else if ('serviceWorker' in navigator) {
    await navigator.serviceWorker.register('/sw.js');
    pushManager = (await navigator.serviceWorker.ready).pushManager;
  } else {
    showInAppInbox();
    return;
  }

  if ((await Notification.requestPermission()) !== 'granted') return;

  await pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: VAPID_PUBLIC_KEY,
  });
});
```

WebKit rejects a subscription without `userVisibleOnly: true`, as Chrome and Edge do. The
declarative path also requires the declarative JSON payload on the server side; see
[iOS Safari push](/reference/notifications/ios-safari-push/).

### Showing the install hint only in a browser tab

The `display-mode` media feature reports the current presentation, not how the page was
launched, so test for the one mode an install hint belongs in rather than listing the
modes it does not.

```js
const inBrowserTab =
  typeof window.matchMedia === 'function' &&
  window.matchMedia('(display-mode: browser)').matches;

if (inBrowserTab) {
  // No install event exists on iOS: explain Share > Add to Home Screen yourself.
  showAddToHomeScreenHint();
} else {
  // Home Screen web app, fullscreen, or an engine that cannot answer: no hint.
  hideInstallHint();
}
```

A page that entered fullscreen through the Fullscreen API also stops matching `browser`,
which is the right outcome here: an overlay on top of a fullscreen video is worse than a
missed hint.

## Observed behaviour

`beforeinstallprompt` is listed by MDN with no Safari or Safari on iOS version, so the only
install UI is the Share sheet, whose labels changed with iOS 26.

:::observed
Safari on iOS 26 (English UI): the Share sheet action is labelled "Add to Home Screen";
the following screen carries a switch labelled "Open as Web App", on by default, and an
"Add" button. With the switch off, the result is a Home Screen
bookmark that opens in the default browser; with it on, the icon opens the site without
Safari UI. Documented in Apple's
[Turn a website into an app in Safari on iPhone](https://support.apple.com/guide/iphone/open-as-web-app-iphea86e5236/ios)
and WebKit's Safari 26.0 feature post.
:::

Because the switch is per add, two users can add the same URL and get different
behaviour; detect `display-mode` at runtime instead of assuming the manifest won.

## See also

- [iOS Add to Home Screen](/reference/installation/ios-add-to-home-screen/)
- [iOS Safari push](/reference/notifications/ios-safari-push/)
- [Badging](/reference/installation/badging/)
- [Storage persistence](/reference/storage/persistence/)
- [PWAs on Safari for macOS (Dock apps)](/reference/platforms/macos-safari/)
- [Web Push for Web Apps on iOS and iPadOS](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/) (webkit.org)
- [Meet Declarative Web Push](https://webkit.org/blog/16535/meet-declarative-web-push/) (webkit.org)
- [WebKit Features in Safari 26.0](https://webkit.org/blog/17333/webkit-features-in-safari-26-0/) (webkit.org)
- [Turn a website into an app in Safari on iPhone](https://support.apple.com/guide/iphone/open-as-web-app-iphea86e5236/ios) (support.apple.com)