Manifest · Manifest member
handle_links manifest member
Published Updated
handle_links is a proposed manifest member, written up in the WICG pwa-url-handler
explainer, through which an installed PWA would tell the browser whether links into its scope
should open inside the installed app window instead of a browser tab. The member takes one of
three string values and is a hint, not a guarantee: the user agent stays free to honour a user
preference over the manifest.
No engine ships it. The Chromium entry on chromestatus.com lists the implementation as “On hold” with no origin trial and no milestone, and Firefox and Safari have published no position (chromestatus.com, feature 5740751225880576). Chrome 155 parses the manifest without it: the member is dropped silently like any unknown key. Link capturing exists in Chromium anyway, but as a per-app user setting rather than a manifest declaration.
Member
Section titled “Member”- Type: string, one of
"auto","preferred", or"not-preferred". - Default:
"auto"when the member is absent or holds another value; the user agent picks the platform’s own behaviour. - Example value:
"preferred".
preferred asks the user agent to open in-scope links in the installed app; not-preferred
asks it to keep them in the browser; auto defers to the platform. The explainer’s non-goals
bound what the member covers: it does not widen scope (that is scope_extensions), and it
does not decide what happens inside the app once a link lands (that is launch_handler). The
only question it answers is whether an in-scope link reaches the app at all.
What shipped instead decides the behaviour in practice. Desktop Chrome 155 and Edge 154 offer a
per-app toggle in the app’s settings page (chrome://apps, right-click, App settings) named
Opening supported links with the choice Open in [app name]; the default is off and the
manifest cannot flip it. Chrome for Android captures links into a WebAPK when the site’s
assetlinks.json verifies the app through Digital Asset Links, again with no manifest input.
Examples
Section titled “Examples”The first example shows the proposed syntax; the second shows the member that does work in Chromium for routing a captured link once it reaches the app.
Declaring the preference the explainer describes
Section titled “Declaring the preference the explainer describes”The member sits at the top level next to scope. start_url must remain inside scope for the
declared boundary to apply; otherwise the user agent falls back to a scope derived from
start_url (w3.org, Web Application Manifest “scope member”) and the links handle_links would
cover are not the ones the author intended.
{ "name": "Tracker", "start_url": "/app/", "scope": "/app/", "handle_links": "preferred"}This manifest is valid everywhere because unknown members are ignored. On Chrome 155 the line changes nothing; it documents intent for a browser that may implement the explainer later.
Routing a captured link with launch_handler and launchQueue
Section titled “Routing a captured link with launch_handler and launchQueue”When the user has enabled link capturing for the app, Chrome 110+ launches the installed app
and reports the clicked URL through LaunchParams.targetURL. Pairing launch_handler with a
launchQueue consumer keeps a single window and navigates it in place; without a consumer the
browser opens the URL in a new app window.
{ "launch_handler": { "client_mode": "navigate-existing" }}if ('launchQueue' in window) { window.launchQueue.setConsumer((launchParams) => { if (!launchParams.targetURL) return; // Icon launch, nothing to route. const url = new URL(launchParams.targetURL); router.navigate(url.pathname + url.search); });} else { // Firefox 157 and Safari 27: links open in a tab; the page loads the URL normally.}client_mode: "navigate-existing" is what makes the captured link reuse the open window; the
launchQueue consumer is only needed for client-side routing. A page that renders from the
URL on load needs neither.
See also
Section titled “See also”- scope manifest member
- scope_extensions manifest member
- launch_handler manifest member
- WebAPK: how Chrome installs PWAs on Android
- PWA URL Handler: handle_links explainer (github.com)
- Chrome Platform Status: Web App Link Handling (handle_links) (chromestatus.com)
- Launch Handler API (developer.chrome.com)
Specifications
| Specification | Status |
|---|---|
| Web App Manifest: handle_links | Explainer |
| Web Application Manifest: scope member | W3C |