contacts — Access the iOS Contacts Database

The contacts module allows you to read and modify the iOS contacts (address book) database.

Note

The first time the contacts module is imported, a system-provided permission dialog will be shown. If you deny access, get_all_people() will always return an empty list. If you change your mind later, you can allow access to your contacts from the Privacy section in the Settings app.

Quick Start

As a simple example for reading information in the address book, let’s start with a script that prints out all people that have text in the ‘Notes’ field:

import contacts
print('Address Book Notes')
print('=' * 40)
people = contacts.get_all_people()
for p in people:
  note = p.note
  if note:
    print(p.full_name)
    print('-' * 40)
    print(note)
    print('=' * 40)

The script uses the get_all_people() function to retrieve a list of all Person objects in the address book, iterates over the list, and prints the name and note for each person that has a (non-empty) Person.note field.

As a slightly more complex example, this script prints out a list of upcoming birthdays (as number of days from now):

import contacts
from datetime import datetime
import operator

days_list = []
people = contacts.get_all_people()
now = datetime.now()
for p in people:
  b = p.birthday
  if b:
    next_birthday = datetime(now.year, b.month, b.day)
    if next_birthday < now:
      next_birthday = datetime(now.year + 1, b.month, b.day)
    days = (next_birthday - now).days
    days_list.append({'name': p.full_name, 'days': days})

if not days_list:
  print('You don\'t have any birthdays in your address book.')
else:
  days_list.sort(key=operator.itemgetter('days'))
  print('Upcoming Birthdays')
  print('=' * 40)
  for item in days_list:
    print('* %s in %i days' % (item['name'], item['days']))

The note and birthday fields are very easy to use because there is only one for each person. Many other fields can have multiple values, e.g. a person can have more than one email address. These fields are represented as lists of tuples, with each tuple containing a label (e.g. ‘home’, ‘work’...), and the actual value. An example for the Person.email attribute would be [('home', 'me@example.com'), ('work', 'work@example.com')].

So far, we’ve only read information from the address book database, but you can also use the contacts module to make changes. Because the previous example used a simple single-value attribute, let’s use the more complex Person.address attribute now, which is represented as a list of multiple dictionaries, each wrapped in a tuple that contains a label (e.g. ‘home’, ‘work’...). Let’s change the country of all people that live in Berlin to be Germany:

import contacts
people = contacts.get_all_people()
for p in people:
  changed = False
  addresses = p.address
  for address_tuple in addresses:
    address = address_tuple[1]
    city = address.get(contacts.CITY, None)
    country = address.get(contacts.COUNTRY, None)
    if city == 'Berlin' and country != 'Germany':
      address[contacts.COUNTRY] = 'Germany'
      address[contacts.COUNTRY_CODE] = 'de'
      changed = True
  if changed:
    p.address = addresses
    print('Updated country of', p.full_name)
contacts.save()
print('Done')

Note that we’ve used constants for the keys in the address dictionary – you can find a list of these keys at the end of this document. After making any changes to the address book, you have to call the save() function to make them persistent.

Note that all multi-value attributes are returned as ‘snapshots’. Modifying these lists directly has no effect unless you re-assign the attribute.

Functions

contacts.get_group(group_id)

Return the Group with the given id (an integer, c.f. Group.id).

contacts.get_all_groups()

Return a list of all Group objects in the address book.

contacts.add_group()

Add a Group to the address book.

contacts.remove_group(group)

Remove a Group from the address book.

contacts.add_person(person)

Add a Person to the address book.

contacts.remove_person(person)

Remove a Person from the address book.

contacts.find(name)

Do a prefix search for the given name and return a list of all matching Person records.

contacts.get_all_people()

Return a list of all people in the address book. Each list entry is a Person object.

contacts.get_person(person_id)

Return the Person with the given id (an integer, c.f. Person.id).

contacts.save()

Save all pending changes in the contacts database. After changing any attributes of a Group or Person object, this function has to be called in order to make the changes persistent.

contacts.revert()

Revert all pending changes in the contacts database.

contacts.localized_label(label)

Return a localized version of a label that is used in a multi-value property.

contacts.is_authorized()

Returns True if access to the address book is currently allowed, False otherwise (e.g. if the permission dialog hasn’t been shown yet or if access is denied due to parental controls).

Group Objects

class contacts.Group

A Group object represents a group in the address book, e.g. friends, family, or co-workers. After initializing a Group object and setting its name attribute, it can be added to the address book database by calling add_group(). When a group’s name is modified, the save() function has to be called in order to make the change persistent.

Group.name

The group’s name, e.g. ‘Friends’ or ‘Family’.

Group.id

The persistent identifier of the group record in the address book (int, readonly), or -1 if the group has not been saved yet. The id can be used with the get_group() function.

Person Objects

class contacts.Person

Person objects represent people in the address book. After initializing a Person and setting its various attributes, it can be added to the address book database by calling add_person(). After any attributes are modified, the save() function has to be called in order to make the changes persistent.

A lot of attributes can have multiple values, e.g. a person can have multiple email addresses (work, private, ...) or phone numbers (home, mobile, ...). Each of these attributes is represented as a list of 2-tuples, with each tuple containing a label and the actual value. For example, this could be the contents of a person’s email attribute: [('home', 'foo@work.com'), ('work', 'foo@work.com')]. Though it’s possible to use any string as a label, it is recommended to use one of the constants at the end of this document. These labels look like '_$!<Work>!$', but will be localized in the UI. You can get a localized representation of a label constant by using the localized_label() function.

Person.address

Street address(es) (multi-dictionary). Use the constants contacts.STREET, contacts.CITY, contacts.STATE etc. as keys.

Person.birthday

Birthday (datetime.datetime).

Person.creation_date

When the person was added to the address book (readonly, datetime.datetime).

Person.department

Department (string).

Person.email

Email address(es) (multi-string)

Person.first_name

First name (string)

Person.first_name_phonetic

First name phonetic (string)

Person.full_name

The person’s full name (readonly, string). To modify the name, use the Person.first_name, Person.last_name and Person.middle_name attributes.

Person.id

The persistent identifier of the person record in the address book (int, readonly), or -1 if the person has not been saved yet. The id can be used with the get_person() function.

Person.instant_message

Instant message accounts (multi-dictionary).

Person.job_title

Job title (string).

Person.kind

The kind of address book record (int, 0 for a person, 1 for an organization).

Person.last_name

Last name (string).

Person.last_name_phonetic

Last name phonetic (string).

Person.middle_name

Middle name (string).

Person.middle_name_phonetic

Middle name phonetic (string).

Person.modification_date

When the person was last modified (readonly, datetime.datetime).

Person.nickname

Nickname (string).

Person.note

Note (string).

Person.organization

Organization (string).

Person.phone

Phone number(s) (multi-string).

Person.prefix

Prefix, e.g. “Sir,” “Duke,” “General” (string).

Person.related_names

Related names (multi-string).

Person.social_profile

Social profile(s), e.g. Twitter accounts (multi-dictionary).

Person.suffix

Suffix, e.g. “Jr.,” “Sr.,” “III” (string).

Person.url

URL(s), e.g. homepage (multi-string).

Person.vcard

VCard reprentation of the person’s data (readonly, string).

Constants

Generic labels for multi-value attributes:

contacts.HOME
contacts.WORK
contacts.OTHER

Labels for the Person.phone multi-string attribute:

contacts.IPHONE
contacts.MAIN_PHONE
contacts.HOME_FAX
contacts.WORK_FAX
contacts.OTHER_FAX
contacts.PAGER

Labels for the Person.related_names multi-string attribute:

contacts.FATHER
contacts.MOTHER
contacts.PARENT
contacts.BROTHER
contacts.SISTER
contacts.CHILD
contacts.FRIEND
contacts.SPOUSE
contacts.PARTNER
contacts.ASSISTANT
contacts.MANAGER

Labels for the Person.url multi-string attribute:

contacts.HOMEPAGE

Keys for Person.address dictionaries:

contacts.STREET
contacts.CITY
contacts.STATE
contacts.ZIP
contacts.COUNTRY
contacts.COUNTRY_CODE