Contacts

The Contacts API gives privileged Web applications a programmatic access to the user's address book maintained in the system.

The initial version of the API was created for Firefox OS back in 2013 and implemented in Firefox. It allowed reading & modifying the contacts through the vCard-like format. It was soon disabled due to implementation flaws, though.

The second proposal to provide Web applications with the ability to interact with the address book was initiated by Google Chrome in late 2018. The new proposal targets specifically the read-only scenario of picking the contacts to be used within the client application only – no modification is to be supported by the API. The proposal is not yet implemented, though.

Regardless from the programmatic access to the contacts API availability, the Web applications might ask for pre-filling the form data from the device address book with the help of form elements' autocomplete attribute values.

API glimpse

Google Chrome proposal (2018)

navigator.contacts.select(filterOptions)
Returns a Promise resolved with the array of contacts from the address book according to the criteria specified.

Firefox OS API (2013)

navigator.contacts.find(filterAndSortOptions)
Returns a Promise resolved with the array of contacts from the address book according to the criteria specified.
navigator.contacts.save(new Contact())
Returns a Promise resolved when the newly created contact is inserted into the address book.
navigator.contacts.remove(contact)
Returns a Promise resolved when the contact is removed from the address book.
navigator.contacts.addEventListener('contactschange', listener)
An event fired when the address book data has changed, containing all the added, removed and changed contact entries.

Live Demo

 
  • function readContacts() {
      var api = (navigator.contacts || navigator.mozContacts);
        
      if (api && !!api.select) { // new Chrome API
        api.select({
          properties: ['name', 'email'],
          multiple: true
        })
          .then(function (contacts) {
            consoleLog('Found ' + contacts.length + ' contacts.');
            if (contacts.length) {
              consoleLog('First contact: ' + contacts[0].name + ' (' + contacts[0].email + ')');
            }
          })
          .catch(function (err) {
            consoleLog('Fetching contacts failed: ' + err.name);
          });
          
      } else if (api && !!api.find) { // old Firefox OS API
        var criteria = {
          sortBy: 'familyName',
          sortOrder: 'ascending'
        };
    
        api.find(criteria)
          .then(function (contacts) {
            consoleLog('Found ' + contacts.length + ' contacts.');
            if (contacts.length) {
              consoleLog('First contact: ' + contacts[0].givenName[0] + ' ' + contacts[0].familyName[0]);
            }
          })
          .catch(function (err) {
            consoleLog('Fetching contacts failed: ' + err.name);
          });
          
      } else {
        consoleLog('Contacts API not supported.');
      }
    }
    
    function consoleLog(data) {
      var logElement = document.getElementById('log');
      logElement.innerHTML += data + '\n';
    }
  • <p>
      <button class="btn btn-lg btn-default" onclick="readContacts()">Read Contacts</button>
    </p>
    
    <pre id="log"></pre>
    

Resources