Export ALL your data from Apple Photos
See the code
PhotosExport is a small macOS command-line tool that exports Apple Photos library assets to the filesystem, and that I developed out of frustration with Shortcuts’ limited (i.e., non-existent) Photos export capabilities and the brokenness of AppleScript-based solutions.
It is intentionally opinionated:
PHAssetResources (including originals, FullSizeRender resources, Live Photo paired video resources, adjustment data, brush stroke retouches, etc.), when present.YYYY/MM folder hierarchy.This tool uses the Photos framework and needs permission to read your Photos library.
If you run it from Terminal, macOS typically associates the Photos permission with Terminal (or your terminal app). Enable it in:
System Settings → Privacy & Security → Photos
If permission is denied, the tool will exit before exporting.
Exports go under:
~/Pictures/Exports/YYYY/MM/Unless you pass:
PhotosExport --export-directory /path/to/exportAn error log is written to:
<export directory>/export_errors.logEach exported resource file is named:
YYYYMMDDHHMMSSx.extWhere:
YYYYMMDDHHMMSS comes from the asset creationDate.x is only added when needed to avoid collisions; it is a lowercase letter (a–z) derived from a deterministic hash of the resource’s name plus stable metadata (type/UTI/dimensions/etc.).…a, …b, …) until unique.If you pass:
PhotosExport --metadata…the exporter will write a JSON sidecar next to the exported files for each asset.
What it contains (high level):
Notes:
stderr as it:
To write the progress log to a file instead:
PhotosExport --log-file /path/to/export.logIf you want to avoid re-downloading/re-writing files, use:
PhotosExport --incrementalBy default, the exporter will overwrite existing files at the destination path.
With --incremental, the exporter will instead skip any resource whose destination filename already exists.
By default, the exporter processes assets from the current calendar year.
To override:
PhotosExport --year 2024You can export multiple years in a single run by specifying both --year (start year) and --end-year (end year):
PhotosExport --year 2018 --end-year 2025Notes:
--end-year must be used together with --year.--year is greater than --end-year, the tool exits with an error.The year can be any valid integer. By popular request, we now allow any year—to accommodate researchers, time travelers, and inter-dimensional drift.
There’s a Makefile with self-documenting targets:
make (shows help)make buildmake run ARGS='--log-file /tmp/photosexport.log'make lintmake testYou can also run via SwiftPM directly:
swift build -c release./.build/release/PhotosExportIf you’re building this with Swift 6 strict concurrency enabled: yes, it can be nearly as unpalatable as AppleScript.
PHAssetResourceRequestOptions.isNetworkAccessAllowed is enabled, so items stored in iCloud may be downloaded during export.PHAssetResources; some assets may only have rendered derivatives available.Swift
99.0%
Makefile
1.0%
Export ALL your data from Apple Photos
See the code
PhotosExport is a small macOS command-line tool that exports Apple Photos library assets to the filesystem, and that I developed out of frustration with Shortcuts’ limited (i.e., non-existent) Photos export capabilities and the brokenness of AppleScript-based solutions.
It is intentionally opinionated:
PHAssetResources (including originals, FullSizeRender resources, Live Photo paired video resources, adjustment data, brush stroke retouches, etc.), when present.YYYY/MM folder hierarchy.This tool uses the Photos framework and needs permission to read your Photos library.
If you run it from Terminal, macOS typically associates the Photos permission with Terminal (or your terminal app). Enable it in:
System Settings → Privacy & Security → Photos
If permission is denied, the tool will exit before exporting.
Exports go under:
~/Pictures/Exports/YYYY/MM/Unless you pass:
PhotosExport --export-directory /path/to/exportAn error log is written to:
<export directory>/export_errors.logEach exported resource file is named:
YYYYMMDDHHMMSSx.extWhere:
YYYYMMDDHHMMSS comes from the asset creationDate.x is only added when needed to avoid collisions; it is a lowercase letter (a–z) derived from a deterministic hash of the resource’s name plus stable metadata (type/UTI/dimensions/etc.).…a, …b, …) until unique.If you pass:
PhotosExport --metadata…the exporter will write a JSON sidecar next to the exported files for each asset.
What it contains (high level):
Notes:
stderr as it:
To write the progress log to a file instead:
PhotosExport --log-file /path/to/export.logIf you want to avoid re-downloading/re-writing files, use:
PhotosExport --incrementalBy default, the exporter will overwrite existing files at the destination path.
With --incremental, the exporter will instead skip any resource whose destination filename already exists.
By default, the exporter processes assets from the current calendar year.
To override:
PhotosExport --year 2024You can export multiple years in a single run by specifying both --year (start year) and --end-year (end year):
PhotosExport --year 2018 --end-year 2025Notes:
--end-year must be used together with --year.--year is greater than --end-year, the tool exits with an error.The year can be any valid integer. By popular request, we now allow any year—to accommodate researchers, time travelers, and inter-dimensional drift.
There’s a Makefile with self-documenting targets:
make (shows help)make buildmake run ARGS='--log-file /tmp/photosexport.log'make lintmake testYou can also run via SwiftPM directly:
swift build -c release./.build/release/PhotosExportIf you’re building this with Swift 6 strict concurrency enabled: yes, it can be nearly as unpalatable as AppleScript.
PHAssetResourceRequestOptions.isNetworkAccessAllowed is enabled, so items stored in iCloud may be downloaded during export.PHAssetResources; some assets may only have rendered derivatives available.Swift
99.0%
Makefile
1.0%