Sage and Pepper's Musings

Life through the eyes of two German Shepherds and their staff.


How to Export Your Apple Photos Library to Adobe Lightroom Classic (With a Python Script)

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 PhotosHow It’s Preserved
AlbumsKeywords like Album:Vacation2024
People/FacesKeywords like Person:John
Favorites5-star rating + Favorite keyword
Original photosExported as filename_original.jpg
Edited versionsExported as filename_edited.jpg
Date organizationFolders: 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 library
python photos_to_lightroom.py --library ~/Pictures/MyPhotos.photoslibrary
# Export to a custom location
python 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: 47
Preparing export to: /Users/you/Pictures/LightroomImport
No previous export manifest found - starting fresh
Found 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,623
Exported to: /Users/you/Pictures/LightroomImport
Detailed log: /Users/you/Pictures/LightroomImport/export_log.json
Import instructions: /Users/you/Pictures/LightroomImport/LIGHTROOM_IMPORT_INSTRUCTIONS.txt
============================================================
NEXT STEPS:
============================================================
1. Open Lightroom Classic
2. File > Import Photos and Video
3. Navigate to: /Users/you/Pictures/LightroomImport
4. Import with 'Add' option to keep files in place
5. 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/LightroomImport
Loaded manifest: 1,623 previously exported photos
Found 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:

ScenarioAction
Photo unchanged since last exportSkipped
Photo edited since last exportRe-exported
Previously exported file was deletedRe-exported
New photo added to libraryExported

Importing into Lightroom Classic

Once the export completes:

  1. Open Lightroom Classic
  2. Go to File → Import Photos and Video
  3. Navigate to your export folder (e.g., ~/Pictures/LightroomImport)
  4. Choose Add to keep files in their current location
  5. 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:

  1. Go to the Library module
  2. Open the Keyword List panel
  3. Find a keyword like Album:Vacation2024
  4. 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:

  1. Connects to Photos.app’s SQLite database using osxphotos, which handles all the complexity of Apple’s proprietary schema.
  2. Iterates through every photo (skipping trash) and extracts metadata: albums, faces, keywords, favorites, dates, edit status.
  3. Copies the original file to a date-based folder structure (YYYY/MM/).
  4. Exports edited versions using Apple’s Photos export API (via osxphotos) to get the rendered edit, not just the RAW + adjustments.
  5. Generates XMP sidecar files with all metadata encoded as Dublin Core and XMP fields that Lightroom understands.
  6. 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