[Proposal] Contact Picker API


Contact Picker API

This is a proposal for adding a Contact Picker API to the Web. Contact pickers are frequently seen in native mobile applications for a variety of use cases, and in various desktop applications such as e-mail clients and calendars.

Contact information is among the most sensitive information on a device, which is why we’re proposing a picker rather than a lower level API. This enables user agents to offer an experience that’s consistent with platform expectations, and to highlight the exact information that is to be shared with the website.

This proposal does not address the source of the contacts. Many operating systems offer functionality to access the user’s contacts, and various browsers allow the user to log in which might provide access to contact information as well.

Use cases

  • Social networks could use contact information to bootstrap a user’s social graph. This is particularly important for emerging markets, where users might prefer a PWA over a native app due to storage constraints.
  • An e-mail application could allow the user to select the recipients for a message without needing their own address book.

Why do we need a new built-in API?

  • Excluding the operating system, there is no canonical place where users maintain a list of their contacts. Developers would have to integrate with a variety of services to provide a comprehensive experience.
  • User agents can offer an experience to users that’s consistent with other applications on the user’s device. The information that will is going to be shared with the website can be clearly highlighted.
  • Contact information is sensitive. Individual contacts can have any number of properties associated with them. Websites seeking the e-mail address of a single user should not have access to the same information of all other contacts.


selectRecipientsButton.addEventListener('click', async () => {
  const contacts = await navigator.contacts.select({
      properties: ['name', 'email'],
      multiple: true
  if (!contacts.length) {
    // Either no contacts were selected in the picker, or the picker could
    // not be launched. Exposure of the API implies expected availability.
  // Use the names and e-mail addresses in |contacts| to populate the
  // recipients field in the website's UI.

Proposed WebIDL

dictionary ContactInfo {
    sequence<USVString> name;
    sequence<USVString> email;
    sequence<USVString> tel;

enum ContactProperty { "email", "name", "tel" };

dictionary ContactsSelectOptions {
    sequence<ContactProperty> properties;
    boolean multiple = false;

[Exposed=Window, SecureContext]
interface ContactsManager {
    Promise<sequence<ContactInfo>> select(ContactsSelectOptions options);

[Exposed=Window, SecureContext]
partial interface Navigator {
    readonly attribute ContactsManager contacts;
  • Sequences are returned for the properties as multiple may be available in the user’s address book. User agents are encouraged to enable users to limit their selection.
  • Support for additional properties can be added iteratively. Whether the returned data can (and should) be sanitized is a question that’s unique to each property. At least one property must be provided.
  • Some future might include the ability to add contacts, or even contact management, so having an intermediary object on navigator helps extensibility.

Security and Privacy

Exposing contact information has a clear privacy impact. We propose a picker model so that the user agent can offer a user experience that makes it clear what information in going to be shared with the website: the spec will have a MUST requirement to ensure that the user understands and selects which contacts or information to share.

The API will only be available on secure contexts. Additionally, we propose that a user gesture is required in order to trigger the contact picker, to help avoid users from inadvertently seeing the picker.

Alternatives Considered

<input type="file" accept="text/contacts+json;items=name,tel" />

The Web Platform already supports a picker for external data through <input type="file" />, which some user agents specialize based on the mime types that are being selected.

Supporting contacts this way has a number of downsides:

  • There is much contention in file types for expressing contact information. For most use cases, a FileReader would be used to read and parse the file in order to access the individual properties. We can optimize for this. Libraries can be used for converting this data in another format of the developer’s choosing.
  • Feature detection is harder, and would likely need a new API such as HTMLInputElement.isTypeSupported() mimicking the MediaRecorder. Unlike existing specializations of file pickers, contacts would be unlikely to gracefully degrade to a general picker.
  • Extensibility is harder, as it would rely on additional parameters being passed to the mime type.

Potential follow-up work

  • As mentioned, more properties can be added iteratively as use cases are identified. It is a non-goal of this API to share all information stored for a particular contact without filtering.
  • A Contact Provider API can be considered to complement data available from the operating system or the user’s account.

I’d been thinking about a potential Contacts API, especially with respect to privacy, a bunch over the last 6 months and this hits every point for me. I love it! I also like the idea of a user gesture being an additional gate. I do wonder if we could consider install as a valid (and persistent) user gesture for PWAs, however.

I think the picker pattern is exactly right for this kind of granular and sensitive data, from a privacy and usability perspective.

I wonder if another way to align it with the existing file picker metaphor would be to have it as a button or drag-and-drop rather than initiated by JavaScript (which also adds the requirement of making sure it’s triggered based on a user gesture). I see the suggestion that overloading input type="file" could have problems, but I could imagine a new input type (e.g. input type="contacts") for this kind of picking. Personally, I think we should have the same for Geolocation.

This API seems to have gathered enough interest so I’m requesting to move the spec to the WICG repo.

Relevant Links:

The GitHub issues contain contributions from Google, Microsoft, and Firefox. There’s also interest from Facebook on some of the issues. This thread includes support from Microsoft.

Support from Microsoft noted, so moving the repo to WICG LGTM.

At the same time, I failed to find interest from Facebook on the issues, so for next time, would be good to provide direct links to such support statements.

The repo now lives under https://github.com/WICG/contact-api

Happy incubationing!! :slight_smile:


I hope that I can use my own stylesheet with the API to make some harmony in the app; because the page looks bad :sob:

I’ve deployed the #contactpicker in coms.global’s Messenger product to make it easier for users to invite friends to the platform. Works like a charm - sends an editable default message by SMS. I hope this is adopted as a standard and other browser vendors catch up fast (Y). I like npdoty’s input type=“contacts” suggestion - that’s a very good idea.

This API is really useful for the new era of web apps and PWAs. Social network or IM apps often want to get all contact entries to build the user’s social graph, but I noticed for this to happen, user must manually select all entries. Am I missing something or it’s intended to be like this?

Being able to pick a contact is a great first step. Being able to to request to add a contact would be another. Like a portfolio page where the “Add To Contacts” button appears, when clicked a dialog appears for the user to accept or reject the contact.

This feature would open so many amazing doors for Web Apps and PWAs. We have long been waiting for something like this and anxiously await its arrival and acceptance on a grand scale! A big thank you to all behind it! <3

How can we get all contacts(with all contact properties) from the device phone book?

We have one requirement where need to import the contacts and show on the page load. So, per my understanding only there is an option to open a picker and select the contacts.

It would be great if navigator.contacts gives the all contacts on page load without showing the picker… Please help me.

For privacy and security getting all contacts will NEVER be an option. The user MUST opt-in to what information is shared through this API.