# WebAPK

> How Chrome on Android mints a signed APK from the manifest, what package identity, intent filters, and splash screen a WebAPK adds, and how updates propagate.

A WebAPK is the small, signed Android package Chrome generates when a user installs a PWA on Android, so the web app gets a real package name, an app-drawer entry, a Settings › Apps entry, and intent filters for its scope instead of a Home Screen shortcut. Chrome 57 introduced it; Samsung Internet mints its own equivalent; Firefox for Android and WebView install shortcuts only, and no desktop platform uses the model (compat dataset `webapk`).

## How it works

Installation runs through Google's minting service, which is why a WebAPK needs network access at install time:

1. The user accepts the install from `beforeinstallprompt`'s `prompt()`, the mini-infobar, or the menu.
2. Chrome sends the manifest URL, its parsed contents, and icon hashes to the WebAPK server.
3. The server returns an APK signed with its own key, containing only metadata: package name, label, icons, a splash screen, and an intent filter for the manifest `scope`.
4. Chrome installs it through Android's package installer; Android treats it as an app, so it appears in the app drawer and in Settings › Apps and can be uninstalled from either.

If the server is unreachable, Chrome falls back to a plain Home Screen shortcut; the page cannot tell which path was taken at install time, only afterwards (see the observed detail).

What the APK contributes, compared with a shortcut, is OS-level identity:

| Behaviour | WebAPK | Home Screen shortcut |
|---|---|---|
| Package name, app drawer, Settings › Apps entry | Yes (`org.chromium.webapk.<hash>`) | No; Home Screen only |
| Links into `scope` opened from other apps | Open in the WebAPK (intent filter) | Open in the browser |
| Splash screen | Built from `name`, `background_color`, and the 512 px icon | None |
| Recents entry | Separate task with the app's name and `theme_color` | Browser task |
| Install twice | Not possible; the existing package is reused | Possible; duplicates share one storage |
| Needs network at install | Yes | No |

The web content is still Chrome: the WebAPK launches `start_url` in a Chrome activity using the user's Chrome profile, so cookies, storage, service workers, and the Chrome version are the browser's. No native API beyond the web platform becomes available, and a Play listing requires a Trusted Web Activity instead.

## Manifest updates

Chrome re-reads the manifest when the installed app is launched and asks the minting server for a new APK when `name`, `short_name`, `icons`, `start_url`, `scope`, `display`, `orientation`, `theme_color`, or `background_color` changed; web.dev's WebAPKs article documents the check as throttled to about once a day and the new APK as installed in the background, so the change shows on a later launch. A changed `start_url` origin or a manifest that no longer parses stops updates rather than breaking the installed app.

## Examples

Both examples run in the page; the first exercises what the WebAPK draws before any page JavaScript, the second branches on the install kind.

### Manifest fields that drive the splash screen and task card

The splash screen is composed from three members and shown until first paint; `theme_color` colours the status bar and the recents card. Missing `background_color` yields a white splash, and an icon smaller than 512 px is scaled up.

```json
{
  "name": "Trail Notes",
  "short_name": "Trails",
  "start_url": "/?source=webapk",
  "scope": "/",
  "display": "standalone",
  "background_color": "#101820",
  "theme_color": "#101820",
  "icons": [
    { "src": "/icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" },
    { "src": "/icons/any-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
```

The `?source=webapk` query on `start_url` is the conventional way to count launches from the installed app in analytics; it also makes the installed app's first request distinguishable in server logs, which is otherwise identical to a tab's.

### Detecting the installed context and the shortcut fallback

`display-mode: standalone` is `true` in a WebAPK, in a shortcut whose manifest asked for `standalone`, and in a TWA, so it answers "installed?" but not "which install?". The referrer separates the TWA case; a shortcut is the remainder once the WebAPK's intent capture is ruled out by the absence of deep-link launches.

```js
const standalone = matchMedia('(display-mode: standalone)').matches;
const fromTwa = document.referrer.startsWith('android-app://');
const launchedFromLink = new URL(location.href).searchParams.get('source') !== 'webapk' && standalone;

if (!standalone) {
  // Browser tab: install UI may be shown once beforeinstallprompt fires.
} else if (fromTwa) {
  // Play-distributed TWA: Digital Goods API may be available.
} else if (launchedFromLink) {
  // Opened through the scope intent filter: only a WebAPK does this.
} else {
  // Launched from the icon: WebAPK or shortcut; behave the same.
}
```

Treating the last two branches alike is the safe choice: a shortcut-installed user has the same web capabilities, only without the OS integration, and nothing in the page should break for them.

:::observed
After installing a PWA from Chrome on Android (English UI), Settings › Apps lists it under its manifest `name`, and tapping it shows a package name beginning `org.chromium.webapk.`, which is the prefix web.dev's WebAPKs article documents for minted packages; a Home Screen shortcut created by Firefox for the same site appears nowhere in Settings › Apps. Opening a link inside the manifest `scope` from another app launches the WebAPK directly, with the splash screen in `background_color`, instead of a Chrome tab.
:::

## See also

- [WebAPKs on Android](https://web.dev/articles/webapks) (web.dev)
- [Installation](https://web.dev/learn/pwa/installation) (web.dev)
- [WebAPK browser support](/compatibility/webapk/)
- [Trusted Web Activity](/reference/installation/twa/)
- [beforeinstallprompt event](/reference/installation/install-prompt/)
- [The N+1 install problem](/reference/installation/n-plus-one/)
- [PWAs on Chrome for Android](/reference/platforms/chrome-android/)