Extract HEIC photos from iCloud zip archives and convert them to PNG files with a single command.
HEIC (High Efficiency Image Container) is the default photo format on iPhones running iOS 11 and later. While it offers better compression than JPEG, it is not universally supported — many apps, websites, and older tools expect JPEG or PNG.
When you export photos from iCloud.com, Apple packages them as one or more zip archives with names like iCloud Photos - Part 1.zip. Inside each zip, your photos are stored under an iCloud Photos/ folder as .heic files.
pyExtractHEIC automates the tedious manual workflow of:
- Unzipping each archive
- Finding all
.heicfiles - Converting them to widely-compatible
.pngfiles
- Python 3.10 or later
pip
pip install -r requirements.txt- Go to icloud.com → Photos
- Select the photos you want, then click the download button
- iCloud will prepare one or more zip files named like
iCloud Photos - Part 1.zip - Save those zip files into a local folder (e.g.
./zip)
python -m heic_converter \
--zip-dir ./zip \
--convert-dir ./convertConverted .png files will appear in ./convert. Use --help to see all options:
python -m heic_converter --helpIf you install the package (pip install -e .), a heic-converter command becomes available:
heic-converter --zip-dir ./zip --convert-dir ./convertpython ConvertIphonePics.pyThis expects ./zip, ./extract, and ./convert directories next to the script. It is kept for backward compatibility; prefer the CLI above for new use.
- Every file in
--zip-dirwhose name matches the glob*icloud*.zipis opened. - Entries stored under the
iCloud Photos/folder inside the zip are extracted to a temporary directory (--extract-dir, deleted automatically when done). - Every
.heicfile in the temporary directory is converted to.pngand saved in--convert-dir. - The temporary extract directory is removed.
| Flag | Default | Description |
|---|---|---|
--zip-dir PATH |
./zip |
Folder containing the iCloud zip archives |
--extract-dir PATH |
./extract |
Temporary folder for extraction (deleted after conversion) |
--convert-dir PATH |
./convert |
Output folder for converted PNG files |
--zip-pattern GLOB |
*icloud*.zip |
Glob pattern used to select zip files |
-v / --verbose |
off | Enable DEBUG-level logging |
pip install -e .
pip install pytest ruffruff check heic_converter/ tests/pytestA GitHub Actions workflow (.github/workflows/ci.yml) runs lint and tests on every push and pull request.
heic_converter/ # Main package
__init__.py
__main__.py # Enables `python -m heic_converter`
converter.py # Core extraction & conversion logic
cli.py # argparse CLI entry point
tests/
test_converter.py # Unit tests for converter module
test_cli.py # Unit tests for CLI
ConvertIphonePics.py # Legacy entry-point (delegates to heic_converter)
requirements.txt # Runtime dependencies (Pillow, pillow-heif)
pyproject.toml # Build & tool configuration
.github/workflows/ci.yml
The following enhancements are not yet implemented but would make the tool more useful:
| Area | Idea |
|---|---|
| Output formats | Add a --format flag to support JPEG output in addition to PNG |
| Parallel conversion | Use concurrent.futures.ThreadPoolExecutor to convert multiple files at once — helpful for large photo libraries |
| Resilient error handling | Wrap per-file conversion in a try/except so one corrupt file does not abort the entire batch; log warnings instead |
| Progress bar | Add a tqdm progress bar for large batches to give visual feedback |
| Preserve metadata | Copy EXIF metadata (date taken, GPS, camera model) from the source HEIC to the output PNG using piexif |
| Duplicate detection | Skip conversion if a PNG with the same stem already exists in the output directory, avoiding redundant work on re-runs |
| Configurable zip folder | Expose --icloud-prefix as a CLI flag so users can handle zips with a different internal folder structure |
| Dry-run mode | Add a --dry-run flag to list what would be converted without writing any files |
| JPEG input | Extend the tool to also convert any .jpg/.jpeg files found in the archive for a one-stop photo normalisation workflow |