While largely overlooked, the AddressBook.sqlitedb database offers unique value joining and requires an advanced SQL Query solution. Contact setup can reveal the relationship or significance of a contact to the device user, beyond just the name, phone number, or username. Additional data entered can provide insight into the user’s relationship, length of interaction, or imported data from third-party applications.
This SQL query goes far beyond the standard, simple select-column query to bring you more:
Prefix,First Name,Middle Name,Last Name, andSuffixinfoPhone / Email / Miscfields with their label prefix centralized to one column- With an added CTE to normalized
labeltext inside_$!<Label>!$_placeholders, so_$!<Mobile>!$_displays asMobile
- With an added CTE to normalized
- Properly ordered multi-line
Address(es) - Profession from
Organization,Department,Title,Organization Phonetic - Social Media
Account(s)and Usernames, ordered alphabetically by the service provider Note, if added for the contactBirthdayand, if present, Chinese lunar (AlternateBirthday) dates → real Gregorian year + full traditional description (with leap month & stem-branch)- Solving the problem of how Apple gets
1985乙丑年十月初六out of1985-11-17when the database value ischinese,0,78,2,10,6
- Solving the problem of how Apple gets
GroupmembershipPhonetic / Pronunciation NameDate Values- Contact Creation / Save / Modification timestamps
| Prefix | First Name | Middle Name | Last Name | Suffix | Phone / Email / Misc |
|---|---|---|---|---|---|
| Miss | Abby | A | Normal | Mobile: (555) 111-3636 | |
| Home: (555) 123-3636 | |||||
| Work: (555) 222-3636 | |||||
| School: (555) 333-3636 | |||||
| iPhone: (555) 444-3636 | |||||
| Apple Watch: (555) 555-3636 | |||||
| Main: (555) 666-3636 | |||||
| HomeFAX: (555) 777-3636 | |||||
| WorkFAX: (555) 888-3636 | |||||
| Pager: (555) 999-3636 | |||||
| Other: (555) 456-3636 | |||||
| Home: abby@fake.com | |||||
| Work: anormal@scienceandtesting.co | |||||
| School: anormal@collegefancy.edu | |||||
| iCloud: anormal@notgmail.com | |||||
| Other: anormal@throwaway.org | |||||
| Anniversary: 2004-07-06 | |||||
| Other: 2016-02-12 | |||||
| HomePage: abnormalthoughts.com | |||||
| Home: blogspace.abby.com | |||||
| Work: scienceandtesting.co | |||||
| School: collegefancy.com | |||||
| Other: absolderthoughts.blog.com | |||||
| Mother: Mother Dearest | |||||
| Father: Father Dearest | |||||
| YoungestSister: Littlest Sue | |||||
| BrotherInLawSistersHusband: Tom | |||||
| Manager: Smart Guy |
| Address(es) | Profession |
|---|---|
| Home: 123 Main Street, Bestburger, AL, 36801, United States, US | Organization: Science and Testing Co. |
| Work: Science and Testing Co 123 Beaker Ave, Bestburger, AL, 36801, United States, US | Department: Measuring (Clean Up) |
| Manager’s Remote Address: 233 12th Street, Columbus, GA, 31901, United States, US | Title: Measuralist |
| Organization Phonetic: Sigh-uhns And Tes-ting Coh |
| Account(s) | Note | Birthday |
|---|---|---|
| AIM: abbynormal36 | Abby Normal is the best at measuring. | Birthday: 1985-11-17 |
| Custom: abbynormal36 | Alternate Birthday: 1985乙丑年十月初六 | |
| Facebook: Abby Normal | ||
| flickr: abbynormal536 | ||
| GoogleTalk: abbynormal36 | ||
| ICQ: abbynormal36 | ||
| Jabber: abbynormal36 | ||
| linkedin: Abby Normal | ||
| MSN: abbynormal36 | ||
| myspace: abbynormalzone | ||
| Signal: abnormal36 | ||
| sinaweibo: Abby Normal | ||
| Skype: abby_normal | ||
| twitter: abbynormal3636 | ||
| Yahoo: abbynormal36 |
| Group | Phonetic / Pronunciation Name | Date Values |
|---|---|---|
| VIPs | Phonetic First Name: Ab-ee | Created: 2025-11-10 14:16:57 |
| Last Name Pronunciation: Nor-muhl | Saved: | |
| 2025-11-10 14:16:57 | ||
| 2025-11-10 14:17:06 | ||
| 2025-11-10 14:17:24 | ||
| 2025-11-10 14:17:38 | ||
| 2025-11-10 14:17:42 | ||
| 2025-11-10 14:23:55 | ||
| 2025-11-10 14:24:02 | ||
| Modified: 2025-11-10 14:24:02 |
1. Prefix, First Name, Middle Name, Last Name, Suffix
These values are pulled straight from the ABPerson table, if present for the contact.
2. Phone / Email / Misc
- The
CleanLabelsCTE strips Apple's_$!<Label>!$_standard values and returns more user-friendly data such as Mobile, Work, etc. - The
CustomFieldsCTE detects phone numbers (many formats), big integers → converts Apple’s Cocoa epoch (978307200 = 2001-01-01) to real dates - All other values are left untouched and the outer query
group_concat(…, CHAR(10))ensures one entry per line in the query result
3. Address(es)
- Reconstructs full multi-line addresses in the correct order (Street → City → State → ZIP → Country)
- Country code is upper-cased (us → US)
- If a label exists (Home/Work), it’s prepended:
Home: 123 Main Street, Bestburger, AL, 36801, United States, US
4. Profession
Concatenation of Organization, Department, JobTitle and organization phonetic field, only if any of them exist.
5. Account(s)
Apple stores instant-message and social-media accounts in several different formats depending on the OS version and application.
This section unifies all variations into a consistent output.
Property Value (ABMultiValue.property) |
Username | Service |
|---|---|---|
| 13 | ABMultiValue.value |
ABMultiValueEntry.value |
| 46 | ABMultiValueEntry.value |
ABMultiValueEntry.value |
The ABMultiValueEntryKey table holds the key names for these entries.
Although the table contains only a single value column, SQLite assigns each row an implicit surrogate key through its internal rowid.
ABMultiValueEntry.key uses this surrogate key as its reference.
Example:
| ABMultiValueEntryKey table | ABMultiValueEntry table | |||
|---|---|---|---|---|
| surrogate key | value | parent_id | key | value |
| 7 | username | 61429 | 7 | abbynormal36 |
| 8 | service | 61429 | 8 | AIM |
The CTEs MVE_Username, MVE_Service, MVE_ProfileEntries, MV_InstantMessage, and MV_Profile normalize the various storage patterns.
CTE UnifiedAccounts unifies the possible variations, our group_concat(formatted_account, CHAR(10)) ensures one entry per line, and ORDER BY service COLLATE NOCASE ASC sorts the Account(s) alphabetically by service name.
6. Birthday
Users can set birthdays for their contacts. This value is stored in ABPerson.Birthday and appears as a timestamp like -477230400.0. A simple datetime conversion turns this into a readable format: 1985-11-17.
If a birthday is entered, the user can also select "add birthday" again, which defaults to the Chinese lunar birthday (e.g., 1985乙丑年十月初六). This value is stored in ABPerson.AlternateBirthday, but its format is not immediately intuitive. Instead of storing the displayed lunar date directly, it appears as:
chinese,0,78,2,10,6
Or, in general terms:
chinese,<is_leap 0/1>,<era_version>,<year_index>,<lunar_month>,<lunar_day>
Here, era_version represents 60-year cycles:
- 76 → 1864–1923
- 77 → 1924–1983
- 78 → 1984–2043 (current)
- 79 → 2044–2103
- ... and so on.
The Gregorian year can be calculated with the formula:
1863 + 60×(era_version − 76) + year_index
Example:
chinese,0,78,2,10,6
is_leap= 0 → normal lunar monthera_version= 78 → current 60-year cycle (1984-2043)year_index= 2 → offset within the era- Lunar month = 10
- Lunar day = 6
Gregorian year = 1863 + 60 x (78-76) + 2 = 1985
→ Chinese lunar date: 1985乙丑年十月初六 (corresponding to 17 Nov 1985 in Gregorian calendar)
Tools like Magnet AXIOM parse this raw string and convert it to a readable date, but historically it was displayed as-is because the encoding was undocumented.
The CTEs (data, split, final_split, etc.) are used to break down the raw AlternateBirthday string into its components and compute a usable Gregorian year.
-
data- Selects
ROWID,First,Birthday(converted to a human-readable date), andAlternateBirthday. - Filters only rows where
AlternateBirthdaybegins with'chinese'. - Converts the Apple epoch (
Birthday + 978307200) to standardYYYY-MM-DDformat.
- Selects
-
split- Begins the process of splitting the comma-separated
AlternateBirthdaystring. part2contains everything after the first comma.
- Begins the process of splitting the comma-separated
-
final_split- Extracts
is_leap_str(whether the lunar month is leap or not) and the rest of the string (rest) for further parsing.
- Extracts
-
version_step- Extracts
version(theera_versioncorresponding to 60-year cycles) fromrest.
- Extracts
-
year_split- Converts
is_leap_strto an integer. - Prepares
rest2for parsingyear_index.
- Converts
-
month_day_split- Extracts
year_index(offset within the era) andrest3(month and day indices).
- Extracts
-
final_calc- Computes
real_yearusing the formula:
real_year = 1863 + 60 * (version - 76) + year_index- Computes
sb_index, which corresponds to the 60-year cycle stem-branch pair (甲子, 乙丑, etc.) used in the Chinese calendar.
- Computes
In short: Each CTE incrementally parses the comma-separated string chinese,<is_leap>,<era_version>,<year_index>,<month>,<day> into separate columns (is_leap, version, year_index, month, day) and calculates a Gregorian year and a Chinese sexagenary cycle index.
The NULLIF(TRIM(COALESCE(...))) AS "Birthday" part is responsible for constructing a readable birthday string, combining both the Gregorian and Chinese lunar birthdays.
- Gregorian birthday:
CASE
WHEN ABPerson.Birthday IS NOT NULL AND ABPerson.Birthday <> ''
THEN 'Birthday: ' || SUBSTR(DATETIME(ABPerson.Birthday + 978307200, 'UNIXEPOCH'),1,10)
END- Converts the Apple timestamp to
YYYY-MM-DDand prefixes withBirthday:.
- Chinese lunar birthday:
CASE
WHEN ABPerson.AlternateBirthday IS NOT NULL AND ABPerson.AlternateBirthday <> ''
THEN CHAR(10) || 'Alternate Birthday: ' || real_year || ...
END- Builds the string starting with
Alternate Birthday: <year> - Appends the stem-branch (sexagenary) year using
sb_index(0–59 → 甲子, 乙丑, …) - Adds
'闰'ifis_leap = 1 - Converts
monthanddayindices to Chinese lunar month and day names (正, 二, …/初一, 初二, …)
NULLIF(TRIM(COALESCE(...)))
- Ensures that if both Gregorian and lunar birthdays are missing or empty, the field becomes NULL rather than a blank string.
In effect: This query outputs a single formatted string like:
Birthday: 1985-11-17
Alternate Birthday: 1985乙丑年十月初六
7. Group
- All groups the contact belongs to, comma-separated.
- Note: When a contact is added to a group, the database creates an additional
ABPersonrow for that contact. TheABPerson.ROWIDis joined toABGroupMembers.member_id, and the corresponding group name is stored inABGroup.Name.
8. Phonetic / Pronunciation Name
Stores all six phonetic/pronunciation fields as entered by the user:
FirstPhonetic,FirstPronunciationMiddlePhonetic,MiddlePronunciationLastPhonetic,LastPronunciation
For Example:
Phonetic First Name: Ab-ee
Last Name Pronunciation: Nor-muhl
9. Date Values
CreationDate– The timestamp when the contact was first created.ModificationDate– The timestamp of the last modification to the contact.save_timestamp– Every save event recorded in the joinedABPersonChanges+ClientSequencetables.
Created: 2025-11-10 14:16:57
Saved:
2025-11-10 14:16:57
2025-11-10 14:17:06
2025-11-10 14:17:24
2025-11-10 14:17:38
2025-11-10 14:17:42
2025-11-10 14:23:55
2025-11-10 14:24:02
Modified: 2025-11-10 14:24:02
Examiners are typically familiar with CreationDate and ModificationDate. However, save_timestamp values provide a more granular view of changes over time and can be invaluable in forensic analysis to track contact edits.
Note: When evaluating timestamps, it is important to distinguish between changes initiated by the user and those generated automatically by the system. Accurate forensic interpretation requires correlating timestamps with other evidence, such as application logs, system events, or network sync records, to reliably determine the source and intent of each change.
- The SQL queries will work in most SQLite database viewers able to execute SQL queries.
- The AddressBook_Contacts.xml file is a Magnet AXIOM Custom Artifact, which can be added to Magnet AXIOM Process through Tools > Manage custom artifacts > ADD NEW CUSTOM ARTIFACT.
This query operates on AddressBook.sqlitedb, the database storing Contacts information on Apple devices. It is found in all iPhone extractions and iTunes backups.
All names, phone numbers, email addresses, URLs, addresses, and any other personal or identifying details appearing in this document are entirely fictitious and used solely for instructional and illustrative purposes. Any resemblance to real persons—living or deceased—or to actual organizations, accounts, or contact information is purely coincidental and unintentional. If you believe any example data in this document corresponds to real personal information and would like it removed, please contact me at james@metadataforensics.com.