Skip to content

SOPs

Pulling Originals Out Of Apple Photos By Filename

I shoot most things on the iPhone. They land in iCloud Photos. By the time I want to use one in a blog post, a Facebook post, or a website embed, the moves are usually:

  1. Open Photos.app.
  2. Find the photo by scrolling and squinting.
  3. Drag it to the desktop.
  4. Wait while iCloud downloads the original.
  5. Move it to the right folder.
  6. Continue.

That is six manual steps for what should be one command. And if Claude is the one doing the work, none of those steps are reachable — Claude cannot drag and drop, cannot scroll, cannot squint.

The annoying part is that the file is right there on disk, just hidden. Photos stores everything under ~/Pictures/Photos Library.photoslibrary/originals/<hex>/<UUID>.<ext>. The catch is twofold:

  • The filename you remember (IMG_4213.MOV) is not the filename on disk (700E1A58-242B-495B-968B-E43ACBEBE799.mov).
  • With “Optimize Mac Storage” on, the original may not even be on disk. Only a smaller proxy is.

Photos keeps a SQLite database at ~/Pictures/Photos Library.photoslibrary/database/Photos.sqlite. The ZASSET table has the on-disk filename in ZFILENAME. The original filename you actually remember lives in a separate table, ZADDITIONALASSETATTRIBUTES, in a column called ZORIGINALFILENAME. They join on ZASSET.Z_PK = ZADDITIONALASSETATTRIBUTES.ZASSET.

So to find IMG_4213.MOV on disk:

SELECT a.ZDIRECTORY, a.ZFILENAME, aa.ZORIGINALFILENAME
FROM ZASSET a
LEFT JOIN ZADDITIONALASSETATTRIBUTES aa ON aa.ZASSET = a.Z_PK
WHERE aa.ZORIGINALFILENAME = 'IMG_4213.MOV';

That gives back the UUID-named copy under originals/<ZDIRECTORY>/<ZFILENAME>.

If “Optimize Mac Storage” is on and the original is offloaded, the row still exists in the database but the file at that path will not. The next piece handles that.

2. AppleScript can tell Photos to export — including the iCloud pull

Section titled “2. AppleScript can tell Photos to export — including the iCloud pull”

Photos exposes a real scripting dictionary. The clause that does the magic is export ... with using originals. When the original is offloaded to iCloud, this triggers an on-demand download. No human-in-the-loop required:

tell application "Photos"
set theItems to (every media item whose filename is "IMG_4213.MOV")
if (count of theItems) is 0 then
error "Not found"
end if
set destFolder to POSIX file "/tmp/photos-export" as alias
export theItems to destFolder with using originals
end tell

The script blocks until the download finishes, then writes the original to the destination with the human filename intact.

~/apps/cc/bin/photos-export.sh wraps both pieces. Usage:

Terminal window
# Run on the same machine that has the Photos library
photos-export.sh IMG_4213.MOV ~/apps/allthingshandy/videos/
# Run from elsewhere — SSH back to the machine that has the library
PHOTOS_HOST=mbp photos-export.sh IMG_4213.MOV ~/apps/allthingshandy/videos/

What it does:

  1. Queries the SQLite database to confirm the asset exists (and tell me if more than one asset shares that filename).
  2. Runs the AppleScript export with using originals, which pulls from iCloud if needed.
  3. Moves the result into the destination directory.
  4. Cleans up the temp dir.

When PHOTOS_HOST is set, the same logic runs over SSH on the named host, then the result is scp’d back to the local destination. This is the case I hit most: Claude is on the Mac Studio, my iPhone syncs Photos to the MacBook Pro, so I run PHOTOS_HOST=mbp photos-export.sh ... to grab from there.

  • “Pull IMG_XXXX from my Photos.”
  • “Grab that video I just took on my phone.”
  • Any time the next action is “drag it to the desktop and then move it to the repo.”
  • Especially when the file is offloaded to iCloud and would otherwise need a manual click to download.
  • The file is already in ~/Downloads or ~/Desktop — just use it.
  • The asset is on a different cloud (Google Drive, iCloud Drive, Dropbox) — different APIs.
  • I need a still frame from a video — that is ffmpeg, not Photos.
  • ERROR: 'IMG_XXXX.MOV' not found in Photos library (matched 0 assets). The filename is wrong, the file is on a different device, or it has been deleted. Use the hint at the bottom of the error to do a LIKE search against the database.
  • AppleScript export hangs. iCloud is downloading the original. With a slow connection and a 4K video, this can take real time. The script blocks until done — that is the right behavior.
  • tell application "Photos" prompts for Automation permission. First-run only; macOS asks once per controlling app. Approve in System Settings → Privacy & Security → Automation.

Before this script:

  • Open Photos on the iPhone.
  • Wait for sync.
  • Find the photo on the Mac.
  • Drag to desktop.
  • Watch iCloud spinner.
  • Move file.

After this script:

  • One command.

That is the gap closed. Follows the same pattern as clipboard-image.sh and pbcopy-james.sh — wrap the annoying part once, never think about it again.