ShippedmacOS utility · 2026

Local macOS utility

iPhotoSizer

Apple Photos exposes aggregate storage but makes it difficult to answer a simpler question: which originals are actually large? iPhotoSizer reads the local Photos library, preserves local-versus-cloud status, and turns the result into a sortable report without uploading the library anywhere.

My role

Independent project · application and package engineering

iPhotoSizer local web interface showing storage totals and media sorted by file size
macOS utility
Library
Local and iCloud-only originals
Surfaces
CLI + local web UI
Exports
CSV and JSON
01

Answer the storage question directly

The tool reads Apple Photos metadata through osxphotos, normalizes it into typed media records, and sorts originals by bytes rather than by the smaller local proxy that may happen to be present.

Cloud-only items stay in the report with an explicit iCloud status, so the result describes the whole library rather than only files currently downloaded to the Mac.

02

Local data, two useful surfaces

The default CLI writes a CSV or JSON report and prints a compact summary. An optional Flask extra opens the same scan in a local browser with search, media filters, storage totals, export controls, and an experimental path back into Photos.app.

Both surfaces share the same typed model and scan logic. The web interface is not a separate cloud service and the photo library never leaves the machine.

03

Treat macOS permissions as product behavior

Photos access depends on Full Disk Access granted to the enclosing terminal application, not just the Python process. The error path walks the process tree to identify that host and gives a concrete System Settings instruction instead of surfacing a generic database failure.

Individual records that cannot be parsed are reported and skipped, while disk-space checks happen before export so one bad item or a nearly full volume does not destroy the entire scan.

Engineering choices

The decisions that shaped it.

The implementation details matter because each one closes a specific failure mode or keeps an important boundary visible.

01

Keep the library on-device

The application reads the Photos database locally and serves the optional UI only on the user's machine.

02

Use one domain model

CLI summaries, browser views, and exports consume the same validated media records instead of implementing separate scan paths.

03

Degrade per record

An unreadable photo becomes a visible warning, not a reason to discard the rest of a long library scan.

Where it landed

A tested macOS utility distributed through PyPI, with a scriptable export path for quick cleanup work and a local visual interface for exploring the same data.

Next case study

Academic Metrics

Keep reading