Export iPhone call history from an encrypted local backup to CSV. Includes contact name resolution, FaceTime, and third-party app calls (WhatsApp, Teams, etc.).
- macOS (or Windows/Linux with an iTunes backup)
- Python 3.14+
- uv
- An encrypted local iPhone backup (call history is only included in encrypted backups)
- Connect your iPhone to your Mac
- Open Finder, select your iPhone in the sidebar
- Check Encrypt local backup and set a passphrase (remember it!)
- Click Back Up Now and wait for it to complete
Backups are stored in ~/Library/Application Support/MobileSync/Backup/.
git clone <this-repo>
cd ios-call-export
uv syncuv run python export_calls.pyThe script auto-detects the most recent backup and outputs calls.csv.
--backup-dir PATH Path to a specific backup directory
--output, -o PATH Output CSV path (default: calls.csv)
--passphrase TEXT Backup encryption passphrase
Copy the example env file and configure your passphrase:
cp .env.example .envEdit .env and uncomment one of the options:
BACKUP_PASSPHRASE-- set the passphrase directlyOP_BACKUP_REF-- use a 1Password secret reference (requiresopCLI, triggers biometric prompt)- macOS Keychain -- store the passphrase encrypted in Keychain (works unattended, recommended for cron):
security add-generic-password -a "$USER" -s "ios-backup-passphrase" -w
The passphrase is resolved in this order:
--passphrasecommand-line argumentBACKUP_PASSPHRASEenvironment variable (via.envor shell)OP_BACKUP_REFenvironment variable (via.envor shell)- macOS Keychain (
ios-backup-passphrase) - Interactive prompt
| Column | Description |
|---|---|
id |
Database primary key |
unique_id |
Stable UUID for the call record |
start |
Call start time (ISO 8601 with timezone) |
end |
Call end time (ISO 8601 with timezone) |
contact_name |
Resolved contact name from AddressBook |
phone_number |
Phone number or email (for FaceTime) |
duration |
Human-readable duration (e.g. 5:08) |
duration_seconds |
Duration as integer seconds |
direction |
Incoming, Outgoing, or Missed |
call_type |
Phone, FaceTime Video, FaceTime Audio, or app name (e.g. Whatsapp) |
answered |
True or False |
country_code |
ISO country code (e.g. DE) |
service_provider |
Bundle ID of the calling service |
location |
Location string if available |
- Decrypts the encrypted iOS backup using iphone-backup-decrypt
- Extracts the
AddressBook.sqlitedbto build a phone number/email to contact name lookup - Extracts
CallHistory.storedataandCallHistoryTemp.storedata, queries theZCALLRECORDtable - Deduplicates records across databases by
ZUNIQUE_ID - Resolves contact names and call types, writes CSV
Calls can be synced to Google Calendar via a webhook. A separate workflow receives the call data, deduplicates by unique_id, and creates calendar events.
- Set up a webhook-based workflow that creates Google Calendar events from the call data
- Add the webhook URL to
.env:WEBHOOK_URL=https://your-instance.com/webhook/your-webhook-path
uv run python send_to_webhook.py # send all answered calls
uv run python send_to_webhook.py --weeks 4 # only last 4 weeks
uv run python send_to_webhook.py --dry-run # preview without sendingCalendar events use the format Contact Name — Call Type as title, with direction, type, phone number, and duration in the description. Duplicate calls are skipped automatically using the call's unique_id as the Google Calendar event ID.
- Call history only goes back as far as iOS retains it (typically ~1 year, varies)
- Contact names are resolved from the AddressBook at backup time; deleted contacts won't have names unless the database's
ZNAMEfield was populated - Group FaceTime calls have no phone number or contact name — iOS stores participants in a separate relationship table, not in the main call record
- The backup must be encrypted (Apple excludes call history from unencrypted backups)