Sharing on mobile and desktop simplified with the Web Share Target API
On a mobile or desktop device, sharing should be as straightforward as clicking the Share button, choosing an app, and choosing who to share with. For example, you may want to share an interesting article, either by emailing it to friends or tweeting it to the world.
In the past, only platform-specific apps could register with the operating system to receive shares from other installed apps. But with the Web Share Target API, installed web apps can register with the underlying operating system as a share target to receive shared content.
See Web Share Target in action
- Using either Chrome 76 or later for Android, or Chrome 89 or later on desktop, open the Web Share Target demo.
- When prompted, click Install to add the app to your home screen, or use the Chrome menu to add it to your home screen.
- Open any app that supports sharing, or use the Share button in the demo app.
- From the target picker, choose Web Share Test.
After sharing, you should see all of the shared information in the web share target web app.
Register your app as a share target
To register your app as a share target, it needs to meet Chrome's installability criteria. In addition, before a user can share to your app, they must add it to their home screen. This prevents sites from randomly adding themselves to the user's share intent chooser and ensures that sharing is something that users want to do with your app.
Update your web app manifest
To register your app as a share target, add a share_target
entry to its web
app manifest. This tells the operating system to include your app as
an option in the intent chooser. What you add to the manifest controls the data
that your app will accept. There are three common scenarios for the share_target
entry:
- Accepting basic information
- Accepting application changes
- Accepting files
Accepting basic information
If your target app is merely accepting basic information such as data, links,
and text, add the following to the manifest.json
file:
"share_target": {
"action": "/share-target/",
"method": "GET",
"params": {
"title": "title",
"text": "text",
"url": "url"
}
}
If your application already has a share URL scheme, you can replace the params
values with your existing query parameters. For example, if your share URL
scheme uses body
instead of text
, you could replace "text": "text"
with "text":
"body"
.
The method
value defaults to "GET"
if not provided. The enctype
field, not
shown in this example, indicates the type of encoding for the data.
For the "GET"
method, enctype
defaults to "application/x-www-form-urlencoded"
and
is ignored if it's set to anything else.
Accepting application changes
If the shared data changes the target app in some way—for example, saving a
bookmark in the target application—set the method
value to "POST"
and include
the enctype
field. The example below creates a bookmark in the target app,
so it uses "POST"
for the method
and "multipart/form-data"
for the
enctype
:
{
"name": "Bookmark",
"share_target": {
"action": "/bookmark",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"url": "link"
}
}
}
Accepting files
As with application changes, accepting files requires that method
be "POST"
and that the enctype
be present. Additionally, enctype
must be
"multipart/form-data"
, and a files
entry must be added.
You must also add a files
array defining the types of files your app accepts. The
array elements are entries with two members: a name
field and an accept
field. The accept
field takes a MIME type, a file extension, or an array
containing both. It's best to provide an array that includes both a
MIME type and a file extension since operating systems differ in which
they prefer.
{
"name": "Aggregator",
"share_target": {
"action": "/cgi-bin/aggregate",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "name",
"text": "description",
"url": "link",
"files": [
{
"name": "records",
"accept": ["text/csv", ".csv"]
},
{
"name": "graphs",
"accept": "image/svg+xml"
}
]
}
}
}
Handle the incoming content
How you deal with the incoming shared data is up to you and depends on your app. For example:
- An email client could draft a new email using
title
as the subject of an email, withtext
andurl
concatenated together as the body. - A social networking app could draft a new post ignoring
title
, usingtext
as the body of the message, and addingurl
as a link. Iftext
is missing, the app might useurl
in the body as well. Ifurl
is missing, the app might scantext
looking for a URL and add that as a link. - A photo sharing app could create a new slideshow using
title
as the slideshow title,text
as a description, andfiles
as the slideshow images. - A text messaging app could draft a new message using
text
andurl
concatenated together and droppingtitle
.
Processing GET shares
If the user selects your application, and your method
is "GET"
(the
default), the browser opens a new window at the action
URL. The browser then
generates a query string using the URL-encoded values supplied in the manifest.
For example, if the sharing app provides title
and text
, the query string is
?title=hello&text=world
. To process this, use a DOMContentLoaded
event listener in your foreground page and parse the query string:
window.addEventListener('DOMContentLoaded', () => {
const parsedUrl = new URL(window.location);
// searchParams.get() will properly handle decoding the values.
console.log('Title shared: ' + parsedUrl.searchParams.get('title'));
console.log('Text shared: ' + parsedUrl.searchParams.get('text'));
console.log('URL shared: ' + parsedUrl.searchParams.get('url'));
});
Be sure to use a service worker to precache the action
page so that it loads quickly and works reliably, even if the user is offline.
Workbox is a tool that can help you
implement precaching in your service worker.
Processing POST shares
If your method
is "POST"
, as it would be if your target app accepts a saved
bookmark or shared files, then the body of the incoming POST
request contains
the data passed by the sharing application, encoded using the enctype
value
provided in the manifest.
The foreground page cannot process this data directly. Since the page sees the data as
a request, the page passes it to the service worker, where you can intercept it with a
fetch
event listener. From here, you can pass the data back to the foreground
page using postMessage()
or pass it on to the server:
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// If this is an incoming POST request for the
// registered "action" URL, respond to it.
if (event.request.method === 'POST' &&
url.pathname === '/bookmark') {
event.respondWith((async () => {
const formData = await event.request.formData();
const link = formData.get('link') || '';
const responseUrl = await saveBookmark(link);
return Response.redirect(responseUrl, 303);
})());
}
});
Verifying shared content
Be sure to verify incoming data. Unfortunately there is no guarantee that other apps will share the appropriate content in the right parameter.
For example, on Android, the url
field will be empty because
it's not supported in Android's share system. Instead, URLs will often appear in
the text
field, or occasionally in the title
field.
Browser support
The Web Share Target API is supported as described below:
On all platforms, your web app has to be installed before it will show up as a potential target for receiving shared data.
Sample applications
Show support for the API
Are you planning to use the Web Share Target API? Your public support helps the Chromium team prioritize features and shows other browser vendors how critical it is to support them.
Send a tweet to @ChromiumDev using the hashtag
#WebShareTarget
and let us know where and how you're using it.