TL;DR: I built a Python script that exports your entire Apple Photos library—with albums, faces, favourites, and edits—into a folder structure that Lightroom Classic can import cleanly. It’s incremental, so you can run it again without creating duplicates.
The Problem
If you’ve ever tried to move from Apple Photos to Adobe Lightroom Classic, you know the pain. Apple Photos stores everything in a proprietary .photoslibrary package with its own database, while Lightroom wants plain files it can catalog. Manually exporting is tedious, and you lose all your organizational work—albums become meaningless, favorites disappear, and those carefully tagged faces? Gone.
I needed a solution that would:
- Export all my photos to a clean folder structure
- Preserve albums, people tags, and favorites
- Include both original and edited versions
- Be re-runnable without creating duplicates
So I built one.
What This Script Does
The photos_to_lightroom.py script reads your Apple Photos library and exports everything to a date-organized folder structure with XMP sidecar files that Lightroom reads automatically.
Features at a Glance
| What You Have in Photos | How It’s Preserved |
|---|---|
| Albums | Keywords like Album:Vacation2024 |
| People/Faces | Keywords like Person:John |
| Favorites | 5-star rating + Favorite keyword |
| Original photos | Exported as filename_original.jpg |
| Edited versions | Exported as filename_edited.jpg |
| Date organization | Folders: 2024/01/, 2024/02/, etc. |
The Secret Sauce: XMP Sidecars
Each exported photo gets a companion .xmp file containing all the metadata. Lightroom reads these automatically on import, so your albums and people tags appear as keywords you can filter and organize.
<dc:subject> <rdf:Bag> <rdf:li>Album:Family Trip 2024</rdf:li> <rdf:li>Person:Mom</rdf:li> <rdf:li>Person:Dad</rdf:li> <rdf:li>Favorite</rdf:li> </rdf:Bag></dc:subject>
Requirements
System Requirements
- macOS (the script reads the native Photos library)
- Python 3.8 or later
- Your Photos library stored locally (not iCloud-optimized)
Installation
The script uses osxphotos, an excellent open-source library for reading Apple Photos databases:
pip install osxphotos
That’s it. No other dependencies required.
How to Use It
Basic Usage
Download the script and run it:
python photos_to_lightroom.py
By default, it will:
- Connect to your system Photos library
- Export to
~/Pictures/LightroomImport/
Custom Options
# Specify a different librarypython photos_to_lightroom.py --library ~/Pictures/MyPhotos.photoslibrary# Export to a custom locationpython photos_to_lightroom.py --output ~/Desktop/PhotoExport# Preview what will happen (no actual export)python photos_to_lightroom.py --dry-run# Force re-export everything (ignore previous exports)python photos_to_lightroom.py --force
Example Output
Here’s what a typical run looks like:
============================================================Apple Photos to Lightroom Classic Exporter============================================================Connecting to system Photos library...Library opened successfully! Photos DB version: 6000 Total photos: 1,623 Total albums: 47Preparing export to: /Users/you/Pictures/LightroomImportNo previous export manifest found - starting freshFound 1,623 photos to process (excluding trash)------------------------------------------------------------ [1/1623] Original: IMG_0001_original.HEIC [1/1623] Edited: IMG_0001_edited.HEIC [2/1623] Original: IMG_0002_original.jpg [3/1623] Original: IMG_0003_original.jpg [4/1623] Original: IMG_0004_original.PNG ... [1623/1623] Original: IMG_1623_original.jpg------------------------------------------------------------============================================================EXPORT COMPLETE============================================================ Total photos in library: 1,623 Newly exported: 1,623 Edited versions: 89 Skipped (already done): 0 Skipped (not local): 0 Errors: 0 Total in manifest: 1,623Exported to: /Users/you/Pictures/LightroomImportDetailed log: /Users/you/Pictures/LightroomImport/export_log.jsonImport instructions: /Users/you/Pictures/LightroomImport/LIGHTROOM_IMPORT_INSTRUCTIONS.txt============================================================NEXT STEPS:============================================================1. Open Lightroom Classic2. File > Import Photos and Video3. Navigate to: /Users/you/Pictures/LightroomImport4. Import with 'Add' option to keep files in place5. See LIGHTROOM_IMPORT_INSTRUCTIONS.txt for details============================================================
Folder Structure Created
~/Pictures/LightroomImport/├── 2023/│ ├── 06/│ │ ├── IMG_4521_original.HEIC│ │ ├── IMG_4521_original.HEIC.xmp│ │ ├── IMG_4522_original.jpg│ │ └── IMG_4522_original.jpg.xmp│ └── 12/│ └── ...├── 2024/│ ├── 01/│ ├── 02/│ └── ...├── .export_manifest.json ← Tracks what's been exported├── export_log.json ← Detailed export log└── LIGHTROOM_IMPORT_INSTRUCTIONS.txt
Running It Again (Incremental Exports)
The killer feature: you can run the script again after adding new photos, and it won’t duplicate anything.
The script maintains a hidden manifest file (.export_manifest.json) that tracks:
- Which photos have been exported (by UUID)
- When each photo was last modified
- Whether edits have been added since export
Second Run Example
============================================================Apple Photos to Lightroom Classic Exporter============================================================Connecting to system Photos library...Library opened successfully!Preparing export to: /Users/you/Pictures/LightroomImportLoaded manifest: 1,623 previously exported photosFound 1,631 photos to process (excluding trash)------------------------------------------------------------ [1/1631] Skipping (already exported): IMG_0001.HEIC [2/1631] Skipping (already exported): IMG_0002.jpg ... [1624/1631] Original: IMG_1624_original.jpg ← new photo! [1625/1631] Original: IMG_1625_original.HEIC ← new photo! ...------------------------------------------------------------============================================================EXPORT COMPLETE============================================================ Total photos in library: 1,631 Newly exported: 8 Edited versions: 2 Skipped (already done): 1,623 Skipped (not local): 0 Errors: 0 Total in manifest: 1,631============================================================
When Photos Get Re-exported
The script is smart about detecting changes:
| Scenario | Action |
|---|---|
| Photo unchanged since last export | Skipped |
| Photo edited since last export | Re-exported |
| Previously exported file was deleted | Re-exported |
| New photo added to library | Exported |
Importing into Lightroom Classic
Once the export completes:
- Open Lightroom Classic
- Go to File → Import Photos and Video
- Navigate to your export folder (e.g.,
~/Pictures/LightroomImport) - Choose Add to keep files in their current location
- Click Import
Lightroom automatically reads the XMP sidecar files, so all your metadata appears immediately.
Organizing by Albums After Import
Your albums are now keywords prefixed with Album:. To recreate them as Lightroom Collections:
- Go to the Library module
- Open the Keyword List panel
- Find a keyword like
Album:Vacation2024 - Right-click → Create Collection from Keyword
Finding Favorites
Your favorites are marked two ways:
- 5-star rating (visible in the grid)
- “Favorite” keyword (filterable)
Filter by Rating >= 5 or by the Favorite keyword to see them all.
How It Works Under the Hood
For the curious, here’s what the script does:
- Connects to Photos.app’s SQLite database using
osxphotos, which handles all the complexity of Apple’s proprietary schema. - Iterates through every photo (skipping trash) and extracts metadata: albums, faces, keywords, favorites, dates, edit status.
- Copies the original file to a date-based folder structure (
YYYY/MM/). - Exports edited versions using Apple’s Photos export API (via
osxphotos) to get the rendered edit, not just the RAW + adjustments. - Generates XMP sidecar files with all metadata encoded as Dublin Core and XMP fields that Lightroom understands.
- Updates the manifest so subsequent runs can skip already-exported photos.
The XMP generation is the clever part—it translates Apple’s album structure into keywords that Lightroom can work with, since there’s no direct equivalent to Photos albums in Lightroom’s import process.
Limitations
A few things to be aware of:
- iCloud Photos: If you use “Optimize Mac Storage,” some originals may not be available locally. The script will skip these and tell you.
- Live Photos: The still image is exported; the video component requires additional handling.
- Smart Albums: Only regular albums are captured. Smart album criteria don’t transfer.
- One-way sync: This is an export tool, not a sync tool. Changes in Lightroom won’t flow back to Photos.
Wrapping Up
Migrating from Apple Photos to Lightroom Classic doesn’t have to mean losing all your organization. With this script, you get a clean, re-runnable export that preserves what matters—your albums, your tagged faces, and your favorites—in a format Lightroom understands.
Grab the script, run it, and you’ll have your entire library ready for Lightroom in minutes.
Happy organising!


Leave a comment