Installation · API
getInstalledRelatedApps()
Published
navigator.getInstalledRelatedApps() resolves with the subset of the calling web app’s manifest related_applications that is installed on the device, so a site can hide its own install button or deep-link into a native counterpart. Chrome 84 and Samsung Internet 14 on Android report Play apps and installed PWAs; Chrome 85, Edge 85, and Opera 71 on Windows report UWP apps only, and the same browsers on macOS, Linux, and ChromeOS resolve with an empty array; Firefox and Safari have not implemented it (BCD api.Navigator.getInstalledRelatedApps).
Syntax
Section titled “Syntax”const apps = await navigator.getInstalledRelatedApps();The method is [SecureContext], so it is absent on plain HTTP origins, and it is defined only on Navigator, not on WorkerNavigator.
Parameters
Section titled “Parameters”None. The promise fulfils with an array of RelatedApplication dictionaries, one per installed match, each carrying the fields below.
| Field | Type | Description |
|---|---|---|
platform |
string |
The store or ecosystem: "play", "windows", "webapp", "chrome_web_store", "chromeos_play", "f-droid", or "amazon". Copied from the manifest entry. |
id |
string, optional |
The platform-specific identifier (Android package name, UWP package family name). |
url |
string, optional |
The entry’s url from the manifest; for "webapp" it is the related PWA’s manifest URL. |
version |
string, optional |
The installed version where the platform exposes one. |
A match requires both halves of the relationship: the manifest entry on the calling site, and a declaration on the other app pointing back. An Android app does so with Digital Asset Links (asset_statements in its resources, verified against the site’s /.well-known/assetlinks.json); a UWP app does so with URI handlers; a related PWA does so with a related_applications entry of its own, or with assetlinks.json when it is outside the caller’s scope.
Exceptions
Section titled “Exceptions”InvalidStateError: the method was called from a document that is not the top-level browsing context, such as an<iframe>, or from a document that is no longer fully active (spec, “getInstalledRelatedApps()” steps 1 and 2).TypeError: thrown synchronously in Firefox and Safari, wherenavigator.getInstalledRelatedAppsisundefined, and on insecure origins in every browser.
An empty array is not an error. It is the result when related_applications is missing, when nothing listed is installed, when the back-reference (asset links or URI handler) fails verification, and on Chromium desktop builds other than Windows.
Examples
Section titled “Examples”Both examples assume a manifest whose related_applications names the Android app com.example.app and the site’s own PWA.
Hiding the install button when the Play app is present
Section titled “Hiding the install button when the Play app is present”The manifest declares the relationship; the page checks it before deciding whether to show a web install affordance. Because the method only answers for the first three entries, list the apps that matter most first.
{ "related_applications": [ { "platform": "play", "id": "com.example.app", "url": "https://play.google.com/store/apps/details?id=com.example.app" }, { "platform": "webapp", "url": "https://example.com/manifest.json" } ], "prefer_related_applications": false}async function decideInstallUi() { const apps = await navigator.getInstalledRelatedApps(); if (apps.some((app) => app.platform === 'play')) { installButton.hidden = true; // the native app is already there openInAppLink.hidden = false; // offer the deep link instead } else if (apps.some((app) => app.platform === 'webapp')) { installButton.hidden = true; // this PWA is installed from another browser or profile }}Keep prefer_related_applications at false unless the native app should replace the PWA: when it is true, Chrome’s install UI offers the store listing instead of installing the web app.
Detecting support and falling back to the install prompt
Section titled “Detecting support and falling back to the install prompt”Where the method is absent or returns nothing, the page has no installed-state signal from other apps and should fall back to its normal install flow and to the display-mode check for its own installed state.
async function relatedAppInstalled() { if (!('getInstalledRelatedApps' in navigator)) return false; // Firefox, Safari, HTTP try { const apps = await navigator.getInstalledRelatedApps(); return apps.length > 0; } catch (error) { if (error.name === 'InvalidStateError') return false; // called inside an iframe throw error; }}
if (!(await relatedAppInstalled())) { showInstallAffordance(); // beforeinstallprompt flow, or Share-sheet instructions on iOS}The false branch is the correct degraded behaviour: a browser that cannot answer the question should behave as if no related app is installed, which at worst shows an install button to a user who already has the native app.
See also
Section titled “See also”- Get Installed Related Apps API specification (wicg.github.io)
- Is your app installed? getInstalledRelatedApps() will tell you! (developer.chrome.com)
- getInstalledRelatedApps() browser support
related_applicationsmanifest member- beforeinstallprompt event
- The N+1 install problem
Specifications
| Specification | Status |
|---|---|
| getInstalledRelatedApps() | WICG draft |
- Legend
- Yes
- Partial
- Flag
- No
- Unknown
| Browser / Platform | Support | Versions | Confidence | Source | Notes |
|---|---|---|---|---|---|
| Chrome (Desktop, Windows) | Yes | 85 | low | source | 1 |
| Chrome (Android) | Yes | 84 | low | source | — |
| Edge (Desktop, Windows) | Yes | 85 | low | source | 2 |
| Samsung Internet | Yes | 14.0 | low | source | — |
| Opera (Desktop, Windows) | Yes | 71 | low | source | 3 |
| Firefox (Desktop) | No | — | low | source | 4 |
| Safari (macOS) | No | — | low | source | 5 |
| Safari (iOS) | No | — | low | source | 6 |