home | contact | blog | notes | recommendations | colophon | resume
started 2026-03-16 at 00:04 EDT | updated 2026-03-16 at 00:04 EDT | written in Maryland
This is a brief note on taking and extracting (into a human-readable form closely resembling, as best I can tell, the on-device directory structure of the originating device) backups from iOS devices. I used this process for an Apple iPhone 13 Pro Max, but it should apply equally to ~any device supported by libimobiledevice. This allows one to access a great deal of on-device data not otherwise exposed to users, at the cost of having very limited support for granularity/incremental backups. If everything goes well, it includes data from most (all?) core applications and user-installed applications on an iPhone, including e.g., browsing data, photos (and associated metadata), notes, etc., generally in normal files and/or legible SQL databases. Maybe somebody will find the below useful.
For backing up/transferring photos from my iPhone to my server, I have a separate workflow involving iOS shortcuts and a REST API, which I will document at some point in the future – but this is quite janky and I find it reassuring to have a proper & reasonably recent full-device backup in place before running any destructive actions.
libimobiledevice exposes most of the necessary tools:
nix-shell -p libimobiledevice usbmuxd
Then, after plugging in the device and clicking “Trust” in the dialog box that appears:
idevicepair pair
If this succeeds, then:
idevicepair validate
Enabling encryption (even though we’ll decrypt and extract the contents immediately after making the backup) permits us to extract a much wider set of on-device domains, including normally protected health/browsing data (these would otherwise be silently excluded!):
idevicebackup2 encryption on -i
(this will prompt for a password)
Then:
mkdir ./iphone-backup
idevicebackup2 backup --full ./iphone-backup
We can then extract the raw encrypted backup using:
idevicebackup2 unback ./iphone-backup --password <password>
…but this requires the device to remain connected and paired throughout extraction. My phone’s charging port is fairly unreliable and the connection usually fails at some point in the process. There are some other options, like this script:
python ./dump-iphone-backup.py -b ./iphone-backup/<UUID> -o ./iphone-backup-unpacked
However, I found the performance lacking, and preferred to use MVT’s backup decryption tool, which is better-optimized (I did not finish a full run using the other script and so cannot compare directly, but eyeballing it, this seems to be at least 30-50x faster).
NIXPKGS_ALLOW_UNFREE=1 nix-shell -p mvt
mvt-ios decrypt-backup --password '<password>' --destination ./iphone-backup-unpacked ./iphone-backup
It decrypts the individual files comprising the backup, but does not seem to have a built-in way to remap these to their original on-device names/paths. For this, I had Claude (Opus 4.5) compose a short script:
python remap_backup.py ./iphone-backup-unpacked ./iphone-backup-unpacked-remapped
For me, this (seemingly successfully; I have yet to verify it more thoroughly) handled ~157k files in ~45 seconds. A cursory inspection indicated that the results had the expected size and shape, but I wasn’t urgently concerned about whether every single file was handled, since I retained the original encrypted backup, and since the unpacked version was in this case more for my own casual interest/archival than immediate use.
The script creates hard links to the source files, so I merely deleted the original flattened archive generated by MVT (i.e., unlinked its contents) to save myself some storage space in the event that a hard-link-unaware backup process is run over this directory at some point in the future.
That’s all; feel free to contact me with any questions or concerns.