Home > Article > Web Front-end > Read Phone Contacts with JavaScript
Author's note: The technologies and processes described in this article are experimental and will only work in a few browsers. At the moment of writing, the Contact Picker API was only supported by Android Chrome (from version 80) and iOS Safari (from version 14.5, but only behind a flag). If you want to review the functionality, you can check a running demo on my website.
Reading entries from the contact list on a phone or tablet has traditionally been limited to native apps. But with the Contact Picker API, we can do just that using JavaScript.
This feature can be interesting in apps that need contact information like phone numbers or VoIP, social networks where we want to discover known people, or apps that require filling in form information without swapping applications to view the data.
The API and the device will limit which properties will be available. There are five standard ones that developers can select:
The plurals here are important, as a contact can have more than one phone, email, or multiple addresses. The returned data will always be inside arrays for consistency, even if it is a single value. More on that later.
The contact information stored on a phone can contain sensitive information that we must treat carefully. Because of that, there are privacy and security considerations that we must take into account:
The first time that they use a website that uses the Contact Picker API, they may get a message like this:
The phone will display this pop-up every time until the user taps "Allow." The Contact Picker API won't run until that happens. Which is good; we want to ensure users grant the proper permissions. It's also good that it's a one-time thing; granting authorization each time the page runs the Contact Picker API code would be a pain in the neck.
The Contact Picker API only defines two methods:
Both methods return promises, but taking into account that the actions that they trigger block the regular flow of the app, we should use async / await when handling them.
It may be tempting to ignore getProperties() and request all the properties directly. But beware if you do that: it will likely work, but if any of the specified properties is unavailable, the select() method will throw an exception.
A demo of the Contact Picker API is in action (run it online here or watch this video). If the API is supported, it shows a button that reads the contact's telephone number, name, and email to display it.
First, we need the button. As detailed earlier in the Privacy and Security section, a user action is required before we can call the API, so we cannot trigger anything without user interaction:
<button onclick="getContactData()">Show contact data</button>
The main code will be in the getContactData() function. But before that, what would be the point of showing the button if the Contact Picker API is unavailable? Let's hide the button if it is not available. Or even better, let's hide the button by default (adding the hidden attribute) and only show it if the API is available.
// only show the button if browser supports Contact Picker API if ("contacts" in navigator) { document.querySelector("button").removeAttribute("hidden"); }
Now that the button logic is in place let's focus on getContactData(). Here's a commented version of the function:
// it is asynchronous because we'll wait for the modal selection async function getContactData() { // indicate what contact values will be read const props = ["tel", "name", "email"]; // wrap everything in a try...catch, just in case try { // open the native contact selector (after permission is granted) const contacts = await navigator.contacts.select(props); // this will execute after the native contact selector is closed if (contacts.length) { // if there's data, show it alert("Selected data: " + JSON.stringify(contacts)); } else { // ...if not, indicate nothing was selected alert("No selection done"); } } catch (ex) { // if something fails, show the error message alert(ex.message) } }
Once the button triggers this function, and if the browser has permissions (see screenshot in the previous section), the contact modal will show up, indicating essential information: the URL reading the data, what data it will return, and the list of contacts to pick from.
After closing the modal, the contacts variable will store the data in JSON as an array with an object containing the information requested (it may be empty if it is not available in the contact card).
For example, this is the result after selecting myself as a contact (fake data):
[ { "address": [], "email": [ "alvarosemail@gmail.com" ], "icon": [], "name": [ "Alvaro Montoro" ], "tel": [ "555-555-5555", "555-123-4567" ] } ]
If the data includes an icon, it will be a blob with the image. If the data includes an address, it will be a more complex object with street, city, country, ZIP code, etc. You can check the returned values in the specification.
But why an array if we only selected one contact? Because there's an option to choose more than one contact!
It is possible to select more than one contact. If we want to do that, we need to pass a second parameter to the navigator.contacts.select() method indicating this option.
const props = ["tel", "address", "icon", "name", "email"]; // only one option available: read multiple or only one (default) const options = { multiple: true }; try { const contacts = await navigator.contacts.select(props, options); // ...
The result is an array of contacts, so the rest of the code could remain the same for this example.
The code above can be intimidating, mainly because of all the comments I added. Here's a lightly commented version of the code above. As you may notice, it is pretty simple:
async function getContactData() { if ("contacts" in navigator) { const props = await navigator.contacts.getProperties(); const options = { multiple: true }; try { const contacts = await navigator.contacts.select(props, options); if (contacts.length) { // code managing the selected data } else { // code when nothing was selected } } catch (ex) { // code if there was an error } } }
You can check out a running demo on my website. Don't worry, I don't do any with the contact information beyond writing it on the screen. But review the code before if you don't trust me.
Contact information is PII (Personally Identifiable Information), and we must treat it with all the care and security that sensitive data requires.
Apart from possible legal requirements that I am not going to go through (because I don't know them, and they change from country to country), here are some basic guidelines when dealing with sensitive data:
Suppose a web app tries to read addresses, names, or emails while selecting a phone number. If that happened to me, I would automatically reject the permission and leave the website.
So, explore JavaScript and the Contact Picker API, but always remember that there's a person behind the screen and that the data they share could be risky if it falls into the wrong hands. Don't be reckless.
If you enjoyed this article about JavaScript and like to test Web APIs and different things with JS, check out this other article:
Develop a Rock Band game with HTML and JavaScript
The above is the detailed content of Read Phone Contacts with JavaScript. For more information, please follow other related articles on the PHP Chinese website!