Skip to content

Platform in Platforms

PWAs on Chrome and Android (WebAPK, TWA)

Published Updated

On an Android device with Google Mobile Services (GMS), installing a PWA from Chrome produces a WebAPK: a small APK that Chrome requests from a Google server and installs, so the app gets a launcher entry, a row in Android’s app settings, and intent filters for its scope. Without GMS, Chrome adds a browser-badged home screen shortcut instead, and a Google Play listing needs the same web app wrapped in a Trusted Web Activity (TWA).

The form of install depends on the browser, not on the site. On Android, Chrome on GMS devices and Samsung Internet on Samsung devices are the two browsers that install PWAs as WebAPKs; Firefox, Edge, Opera, and Chrome on devices without GMS add a shortcut that opens the site in the browser (Making PWAs installable, MDN). Chrome for Android installs on every Android release it runs on, back to Jelly Bean.

  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Android)Yes57mediumsource12
  1. Generates a WebAPK via Google's minting server at install time.
  2. No cross-browser compatibility dataset (BCD/caniuse) covers WebAPK; version verified from Chrome Platform Status.

Source data: /compatibility/webapk.json · Global usage: 64 % (StatCounter 2026-05)

Source: spec · Last verified 2026-07-16 · Confidence: medium (computed from sources)

Trusted Web Activity is a separate mechanism with its own dataset:

  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Android)Yes72mediumsource123
  1. Per Chrome's documentation, Trusted Web Activity is available in Chrome on Android from version 72.
  2. No cross-browser compatibility dataset (BCD/caniuse) covers TWA; version verified from Chrome's own documentation.
  3. The same documentation notes other browsers may implement the same protocol, but does not itself document TWA support in any other browser.

Source data: /compatibility/twa.json · Global usage: 64 % (StatCounter 2026-05)

Source: spec · Last verified 2026-09-09 · Confidence: medium (computed from sources)

What Chrome needs before it offers an install

Section titled “What Chrome needs before it offers an install”

Chromium browsers, including Chrome, Samsung Internet, and Edge, promote a site for installation only when its manifest has name or short_name, icons with a 192px and a 512px entry, start_url, display or display_override, and prefer_related_applications either false or absent. The page must be served over https, or from localhost or 127.0.0.1 during development; file:// does not count, even though it is a secure context. A service worker is not required for installability. Chrome for Android, Chrome for desktop, Edge for desktop, and Safari for desktop also let the user install a site that has no manifest at all; the manifest’s job is to make the browser promote the install and to shape the result.

The user-facing path in Chrome for Android (English UI) is the three-dot More menu, then Install and create shortcut, then Install (Chrome Help). A page can also open the same dialog itself from a beforeinstallprompt handler; the code is under “Examples”.

Chrome builds the WebAPK from the manifest and other metadata (WebAPKs on Android, web.dev). Once installed:

  • The app opens in the Chrome the user installed it from, not in a WebView.
  • It registers intent filters for every URL inside scope. With "scope": "/app/", tapping a link to /app/read/book opens the app; /help/ opens a browser tab.
  • Permissions are not granted at install. Android grants native apps notification permission on install, but a WebAPK must request it at runtime, through Chrome’s own prompts and settings.
  • Storage is the browser profile’s storage. Cookies, IndexedDB, Cache Storage, and the service worker registration are shared with Chrome; clearing Chrome’s site data clears the installed app too.
  • WebAPKs generated by Chrome 71 or later show a larger icon on the splash screen when the manifest ships a 512px icon.
  • The generated APK is not accepted by Google Play. A Play listing is what a TWA is for.

Chrome for Android schedules a manifest fetch on launch if the last check is more than 24 hours old, and may stretch the interval to 30 days after a failed fetch (How Chrome handles updates to the web app manifest, web.dev). A change to name, short_name, icons, background_color, display, orientation, scope, shortcuts, start_url, theme_color, or web_share_target queues a new WebAPK, which Chrome requests once every app window is closed and the device is plugged in and on Wi-Fi. Renaming or moving the manifest file can stop updates altogether, and a manifest that carries per-user values regenerates the APK for no benefit.

A TWA opens your origin from an Android app you publish, through a protocol built on Custom Tabs, available in Chrome 72 and later (Trusted Web Activities, developer.chrome.com). The app and the site must be linked with Digital Asset Links; when they are, the content renders fullscreen in the user’s browser, with no browser UI. The host app has no direct access to cookies or localStorage, so state passes through URLs (query parameters and intent URIs). On a Chrome older than 72 the same app falls back to a Custom Tab with a plain toolbar. Bubblewrap is the Node.js CLI that generates the Android project; the packaging steps are on the Trusted Web Activity (TWA): PWAs in the Play Store entry.

Both examples run unchanged in a browser tab, in a WebAPK, and in a desktop app window; the feature checks decide what the user sees.

beforeinstallprompt fires on window once Chrome has decided the page is installable, usually during page load, with no guaranteed timing. Keep the button hidden until the event arrives, because the event is Chromium-only:

  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Android)Yes68mediumsource—
Chrome (Desktop)Yes73mediumsource—
Edge (Desktop)Yes79mediumsource—
Safari (iOS)No—mediumsource1
Safari (macOS)No—mediumsource2
Firefox (Desktop)No—mediumsource3
Samsung InternetYes9.0mediumsource—
  1. No beforeinstallprompt; install is manual via the Share sheet → Add to Home Screen.
  2. Install is via the File → Add to Dock menu, not the web event.
  3. No manifest-based desktop install path.

Source data: /compatibility/install-prompt.json · Global usage: 72 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-06-24 · Confidence: medium (computed from sources)

<button id="install" hidden>Install</button>
let installPrompt = null;
const installButton = document.querySelector('#install');
window.addEventListener('beforeinstallprompt', (event) => {
event.preventDefault(); // suppress Chrome's own install UI
installPrompt = event; // keep the event for the click handler
installButton.removeAttribute('hidden');
});
installButton.addEventListener('click', async () => {
if (!installPrompt) return;
const consumedPrompt = installPrompt;
installButton.disabled = true; // no second click while the dialog is open
try {
const result = await consumedPrompt.prompt();
console.log(`Install prompt was: ${result.outcome}`); // "accepted" or "dismissed"
} finally {
installPrompt = null; // the instance is consumed on every exit path
installButton.disabled = false;
installButton.setAttribute('hidden', '');
}
});

prompt() has to run inside a user-activation handler and may be called once per BeforeInstallPromptEvent instance (BeforeInstallPromptEvent: prompt() method, MDN), which is why the handler retires the event in finally rather than only after a successful prompt. On iOS the event does not exist, so the button stays hidden there and the user installs from the Share menu.

display-mode reports the mode the browser applied, which can differ from the manifest’s display when the browser does not support the requested value (display-mode, MDN). It describes presentation, not install state, so use it to adjust the UI, not as an installation API:

function applyDisplayMode(installButton) {
if (!('matchMedia' in window)) {
// matchMedia is unavailable: leave the button hidden and rely on the browser's menu.
installButton.hidden = true;
return;
}
if (window.matchMedia('(display-mode: standalone)').matches) {
installButton.hidden = true; // already running as an app window
}
}

A standalone match means the page is not in a normal tab; it does not prove a WebAPK exists, because the same media query matches a desktop app window and a Home Screen web app on iOS.

The WebAPK update cycle is visible on-device, which is the quickest way to tell a stale manifest from a cache problem.

Uninstalling goes through Android, not Chrome: Settings > Apps > See all apps, tap the web app, then Uninstall (English UI, Chrome Help). When a developer changes the app’s name, Chrome shows the new name to the user with OK to accept or Uninstall app to remove it; a rename that imitates another app is treated by Chrome Help as a sign the developer may be malicious.

Specifications

SpecificationStatus
None.