navigator.contacts returns a ContactsManager — the Contact Picker API entry point. Learn feature detection, getProperties(), select(), secure context rules, five examples, and try-it labs.
01
Kind
Read-only property
02
Returns
ContactsManager
03
Status
Experimental
04
Context
Secure (HTTPS)
05
Picker
select()
06
Fields
getProperties()
Fundamentals
Introduction
Forms that ask for a friend’s name, email, or phone number are tedious to fill by hand. The Contact Picker API lets the user choose contacts from their device list and share only the fields you request.
Your entry point is navigator.contacts. It is read-only and returns a ContactsManager object. MDN notes that two successive accesses return the same object instance.
💡
User-controlled sharing
The site never scrapes the whole address book. The user opens a picker, chooses contacts (and which details to share), then your Promise resolves with that limited data.
Concept
Understanding the contacts Property
Think of navigator.contacts as a handle to the Contact Picker for this page. You do not assign to it — you call methods on the ContactsManager it returns.
getProperties() — Promise of supported field names (name, email, tel, address, icon).
select(properties, options) — opens the picker; resolves to an array of selected contacts.
options.multiple — set true to allow selecting more than one contact.
Call select() from a user gesture (button click) on a secure page.
Foundation
📝 Syntax
General form of the property:
JavaScript
navigator.contacts
Value
A ContactsManager object used to open the contact picker and query supported properties.
Common patterns
JavaScript
// MDN-style feature detect:
const supported = "contacts" in navigator && "ContactsManager" in window;
// Supported fields:
const props = await navigator.contacts.getProperties();
// Open picker from a click handler:
const contacts = await navigator.contacts.select(
["name", "email", "tel"],
{ multiple: true }
);
Cheat Sheet
⚡ Quick Reference
Goal
Code
Get ContactsManager
navigator.contacts
Detect API
"contacts" in navigator && "ContactsManager" in window
List fields
await navigator.contacts.getProperties()
Open picker
await navigator.contacts.select(props, opts)
Multi-select
{ multiple: true }
Secure page?
window.isSecureContext
Snapshot
🔍 At a Glance
Four facts to remember about navigator.contacts.
Returns
ContactsManager
Same object twice
Status
experimental
Not Baseline
HTTPS
required
Secure context
Main call
select()
User gesture
Compare
📋 Contact Picker vs Manual Form
navigator.contacts
Manual form fields
UX
Native picker, one tap share
Type name / email / phone
Privacy
User chooses what to share
User types whatever they want
Support
Experimental / limited
Works everywhere
Best for
Enhancement on supporting devices
Always-available fallback
Use together?
Yes — offer “Pick from contacts” when supported; keep the form
Hands-On
Examples Gallery
Examples follow MDN Contact Picker / navigator.contacts patterns. Prefer Try It Yourself on a supporting mobile browser. Use View Output for expected messaging.
📚 Getting Started
Detect the API and confirm a secure context.
Example 1 — Feature Detection
MDN-style check for Contact Picker support.
JavaScript
const supported = "contacts" in navigator && "ContactsManager" in window;
console.log(supported ? "contacts available" : "contacts missing");
navigator.contacts (Contact Picker API) is Experimental and not Baseline. Historical support is strongest on Chrome for Android. Desktop browsers and Safari/Firefox often omit it. Always feature-detect.
✓ Experimental · Not Baseline
Navigator.contacts
Offer Contact Picker as progressive enhancement. Keep a manual name/email/tel form for everyone else.
LimitedNot Baseline
Google ChromeContact Picker mainly on Android builds (check MDN)
Limited
Microsoft EdgeFollow Chromium Contact Picker status on supported platforms
Limited
OperaChromium-based — check current mobile compat
Limited
Mozilla FirefoxNot available for typical web content
Unavailable
Apple SafariNot available for typical web content
Unavailable
contactsLimited
Bottom line: Detect navigator.contacts, require HTTPS, call select() from a click, and always ship a form fallback.
Wrap Up
Conclusion
navigator.contacts is the Contact Picker API entry point. Feature-detect it, require HTTPS, use getProperties() and select() from a button click, and keep a normal form when the API is missing.
Feature-detect with MDN’s contacts + ContactsManager check
Serve over HTTPS
Call select() from a user gesture
Filter fields with getProperties()
Keep a manual contact form as fallback
❌ Don’t
Require Contact Picker for core checkout / invite flows
Assume desktop browsers support it
Request unsupported property names blindly
Auto-open the picker on page load
Store shared contacts longer than the user expects
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about contacts
Contact Picker entry — user-shared fields only.
5
Core concepts
👤01
Returns
ContactsManager
API
🔍02
Fields
getProperties
Query
📞03
Picker
select()
Gesture
🔒04
HTTPS
secure context
Security
🔬05
Status
Experimental
Detect
❓ Frequently Asked Questions
It is a read-only Navigator property that returns a ContactsManager object — the entry point to the Contact Picker API so users can select contacts and share limited details with your site.
Yes. MDN marks it Experimental and not Baseline. Support is limited (historically strongest on Chrome for Android). Always feature-detect and provide a manual form fallback.
Yes. It is available only in secure contexts (HTTPS or localhost) in supporting browsers.
Call await navigator.contacts.select(properties, options) from a user gesture such as a button click. Pass property names like "name", "email", and "tel". Use { multiple: true } to allow several contacts.
await navigator.contacts.getProperties() resolves to an array of property names the system can return. Use it so you only ask select() for supported fields.
No. The property is read-only. Two successive reads return the same ContactsManager object. You call methods on that object.
Did you know?
MDN notes that reading navigator.contacts twice returns the sameContactsManager object — you are not creating a new manager on every access.