Skip to main content

Python PhotoKit

Python PhotoKit is a Python interface to the Apple PhotoKit framework for working with the Photos app on macOS.

This is currently a work in progress, and is not yet ready for use. I'm working on extracting the code from osxphotos and adding additional functionality.

It is based on work done for osxphotos which provides a command line interface to the Photos app on macOS as well as a python API for working with Photos.

Synopsis

>>> from photokit import PhotoLibrary
>>> PhotoLibrary.authorization_status()
(True, True)
>>> pl = PhotoLibrary()
>>> new_photo = pl.add_photo("/Users/user/Desktop/IMG_0632.JPG")
>>> new_photo.uuid
'8D35D987-9ECC-490C-811A-1AA33C8A7983'
>>> photo = pl.asset("CA2E3ADB-53A4-4E85-8D7D-4A664F970810")
>>> photo.original_filename
'IMG_4703.HEIC'
>>> photo.export("/private/tmp")
['/private/tmp/IMG_4703.heic']
>>> photo.revert()  # discard any edits
>>>

Libraries other than the system library can be opened by path; this switches PhotoKit to multi-library mode (see Implementation Notes):

>>> from photokit import PhotoLibrary
>>> library2 = PhotoLibrary("/Users/user/Pictures/Test2.photoslibrary")
>>> library2.add_photo("/private/tmp/IMG_4703.HEIC")
<photokit.asset.PhotoAsset object at 0x...>

Installation

Still a work in progress and not yet ready for normal use. If you'd like to experiment with it, you can install it from GitHub:

git clone git@github.com:RhetTbull/photokit.git
cd photokit
python3 -m pip install flit
flit install

or via pip:

    pip3 install photokit

Documentation

Documentation is available at https://rhettbull.github.io/photokit/.

Supported Platforms

Python PhotoKit was originally developed on macOS Ventura (13.5.x) with initial testing on macOS Monterey (12.x) and macOS Sonoma (14.x). The test suite currently passes on macOS 27. No guarantees are made for other versions. It will not work on macOS Catalina (10.15.x) or earlier as those versions of macOS do not support some of the API calls used by this library.

Implementation Notes

PhotoKit is a macOS framework for working with the Photos app. It is written in Objective-C and is not directly accessible from Python. This project uses pyobjc to provide a Python interface to the PhotoKit framework. It abstracts away the Objective-C implementation details and provides a Pythonic interface to the PhotoKit framework with Python classes to provide access to the user's Photo's library and assets in the library.

In addition the public PhotoKit API, this project uses private, undocumented APIs to allow access to arbitrary Photos libraries, accessing keywords, etc. The public PhotoKit API only allows access to the user's default Photos library (the so called "System Library") and limits the metadata available.

Opening a library other than the system library (PhotoLibrary(library_path) or PhotoLibrary.enable_multi_library_mode()) switches PhotoKit into multi-library mode for the rest of the process; after that, PhotoLibrary() (single-library mode) can no longer be used. Some methods (smart_album(), smart_albums(), observe_changes()) are only available in single-library mode.

A number of methods allow retrieval of assets of via a local identifier or universally unique identifier. Photos uses a local identifier to identify assets, albums, etc. within a single Photos library. The local identifier is specific to a given instance of the Photos library. The same asset in a different instance of the Photos library will have a different local identifier. This library uses the term "UUID" interchangeably with local identifier. A UUID is a string of hexadecimal digits that takes the form: 61A4B877-5EAC-4710-AA77-6D387629D9A5. A local identifier returned by the native PhotoKit interface includes additional digits in the form 61A4B877-5EAC-4710-AA77-6D387629D9A5/L0/001. For any method in this library that accepts a UUID, you may pass either the full local identifier or just the UUID portion. The library will automatically strip off the additional digits.

Whenever a public, documented method is available, the library uses that method. However, when no public method is available, this library uses private, undocumented methods to provide the functionality. If a private method cannot be found or does not work, the library uses direct access to the Photos database. If this doesn't work, the library will use AppleScript via the ScriptingBridge framework to access the Photos app. This is the least desirable method as it is slow and can be unreliable and only works on the current (default) Photos library.

Editing Assets and AAE Files

Assets can be edited with PhotoAsset.edit(), including assets just added to the library, and edits can be undone with PhotoAsset.revert(). See examples for scripts that edit photos and videos with Core Image filters. For Live Photos, the edit callback may also return an edited paired video (this uses a private PhotoKit API); if it does not, Photos saves the edited version as a still photo. The PhotoLibrary.add_*_with_adjustments() methods add an original asset then apply an edited version along with adjustment data read from an AAE file (for example, one exported from Photos). Photos will not accept an edit from another process that uses its own adjustment format identifier, com.apple.photo; attempting to do so fails with PHPhotosErrorDomain error 3302. Adjustment data read from an AAE file with this identifier is therefore stored under a photokit-specific identifier. The adjustment data is preserved and the edited version displays normally (and "Revert to Original" works) but Photos treats the edit as coming from another app so it cannot re-open Apple's adjustments in its own editor.

It would be wonderful if Apple provided a full public API to Photos but this is unlikely to happen. The use of private APIs is not recommended by Apple and could break at any time. This library is provided as-is with no guarantees of functionality. Use at your own risk.

See Also

  • osxphotos: Python app to export pictures and associated metadata from Apple Photos on macOS. Also includes a package to provide programmatic access to the Photos library, pictures, and metadata.
  • PhotoScript: Automate macOS Apple Photos app with python. Wraps AppleScript calls in Python to allow automation of Photos from Python code.

License

This project is licensed under the terms of the MIT license.

To Do

PhotoLibrary

Static Methods

  • enable_multi_library_mode()
  • multi_library_mode()
  • system_library_path()
  • default_library_path()
  • authorization_status()
  • request_authorization() (partially implemented, not well tested)
  • create_library() (removed: the private API it used no longer works)

Methods

  • library_path
  • is_system_library()
  • is_default_library()
  • assets() (all assets or assets(uuids=[...]))
  • asset()
  • albums()
  • album() (by UUID or title)
  • create_album()
  • delete_album()
  • smart_album(), smart_albums() (single-library mode only)
  • moments()
  • folders() (stub: prints folders but does not return them)
  • create_folder()
  • fetch_burst_uuid() (implemented, not yet tested)
  • selection() (assets currently selected in Photos)
  • delete_assets()
  • add_photo()
  • add_video()
  • add_raw_pair_photo()
  • add_live_photo()
  • add_photo_with_adjustments()
  • add_video_with_adjustments()
  • add_live_photo_with_adjustments()
  • add_raw_pair_photo_with_adjustments()
  • create_keyword()
  • observe_changes(), stop_observing_changes() (single-library mode only)
  • __len__

PhotoAsset

  • keywords getter/setter
  • isphoto
  • ismovie
  • isaudio
  • original_filename
  • uuid
  • local_identifier
  • raw_filename
  • hasadjustments
  • media_type
  • media_subtypes
  • favorite (getter/setter)
  • hidden (getter/setter)
  • panorama
  • hdr
  • screenshot
  • live
  • streamed
  • slow_mo
  • time_lapse
  • portrait
  • burst
  • burstid
  • source_type
  • pixel_width
  • pixel_height
  • date (created; setter/getter)
  • date_modified (setter/getter)
  • date_added (setter/getter)
  • timezone_offset (setter/getter)
  • timezone (setter/getter)
  • location (setter/getter)
  • duration
  • orientation() (current or original version)
  • title (getter/setter)
  • description (getter/setter)
  • edit
  • revert
  • burst_photos
  • export (implemented, not yet tested)

VideoAsset

  • export, including slow-mo videos (implemented, not yet tested)

LivePhotoAsset

  • export (implemented, not yet tested)

Album

  • album properties
  • add_assets()
  • remove_assets()

Folder

PhotoDB

  • get_asset_uuids()
  • get_album_uuids

Tests

  • initial test suite

Documentation

  • initial documentation
  • publish to GitHub pages

Type Hints/Linting

  • mypy
  • ruff

Chores

  • add doit for build automation

Metadata

Release files for photokit 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for photokit 0.3.0
File Size Uploaded
photokit-0.3.0.tar.gz 70.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for photokit 0.3.0
File Interpreter ABI Platform
photokit-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 70.6 MB

Release files / photokit-0.3.0.tar.gz

Download URL photokit-0.3.0.tar.gz
Size 70.5 MB
Tags Source
SHA-256 checksum
How to use checksums
b70840c64f4e46853d6d9379d6978e3ef5b03570004498e19ff327a9483bfb8a
BLAKE2b-256 checksum
How to use checksums
1eb46f5b69e50b74d508578ced5854cb2c933362efb62afcd5aa8c67492063b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.5

Release files / photokit-0.3.0-py3-none-any.whl

Download URL photokit-0.3.0-py3-none-any.whl
Size 55.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
792553aaf33b3fab5c1caa42de5b38b053a6be131fcd6ee5d7a949d72f4db0ab
BLAKE2b-256 checksum
How to use checksums
b869a8af0f6a99d73dcf9842514569165deff1132b2a86c8585e2ec115a98005
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.5

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page