Install & Compatibility
Where this runs
tested against v1.1.3 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.010s · 17.9MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.5s · import 0.010s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
ImageIFD, ExifIFD, GPSIFD, InteropIFD, TAGS
✓ import piexif
# Access constants like:
piexif.ImageIFD.Make
piexif.TAGS['Exif'][piexif.ExifIFD.DateTimeOriginal]
IFD constants and TAGS dictionary are attributes of the top-level piexif module.
This quickstart demonstrates how to load EXIF data from a JPEG image, modify a tag (e.g., the camera make), and then save the image with the updated EXIF information using piexif, often in conjunction with Pillow for image handling.
import piexif
from PIL import Image
import os
# Create a dummy JPEG file for demonstration
dummy_image_path = "dummy_image_with_exif.jpg"
new_image_path = "output_image_with_modified_exif.jpg"
# Create a simple image (requires Pillow)
img = Image.new('RGB', (60, 30), color = 'red')
img.save(dummy_image_path)
# 1. Load EXIF data
try:
# Create a minimal EXIF dictionary
zeroth_ifd = {
piexif.ImageIFD.Make: "PiexifTest",
piexif.ImageIFD.XResolution: (72, 1),
piexif.ImageIFD.YResolution: (72, 1)
}
exif_ifd = {
piexif.ExifIFD.DateTimeOriginal: "2026:04:11 12:34:56"
}
exif_dict_initial = {"0th": zeroth_ifd, "Exif": exif_ifd, "GPS": {}, "Interop": {}, "1st": {}, "thumbnail": None}
exif_bytes_initial = piexif.dump(exif_dict_initial)
img.save(dummy_image_path, exif=exif_bytes_initial)
exif_dict = piexif.load(dummy_image_path)
print("Original Camera Make:", exif_dict["0th"][piexif.ImageIFD.Make])
# 2. Modify an EXIF tag
exif_dict["0th"][piexif.ImageIFD.Make] = "PiexifModified"
# 3. Dump the modified EXIF data to bytes
exif_bytes = piexif.dump(exif_dict)
# 4. Insert the new EXIF data into an image (or save with Pillow)
img_to_modify = Image.open(dummy_image_path)
img_to_modify.save(new_image_path, exif=exif_bytes)
# 5. Verify the change
modified_exif_dict = piexif.load(new_image_path)
print("Modified Camera Make:", modified_exif_dict["0th"][piexif.ImageIFD.Make])
finally:
# Clean up dummy files
if os.path.exists(dummy_image_path):
os.remove(dummy_image_path)
if os.path.exists(new_image_path):
os.remove(new_image_path)
Debug
Known issues
breakingVersion 1.0.0 introduced significant breaking changes. `piexif.ZerothIFD` was renamed to `piexif.ImageIFD`, and the `dump` function's argument signature changed from accepting three separate IFD dictionaries to a single combined dictionary.fixUpdate code to use `piexif.ImageIFD` for 0th IFD tags and pass a single dictionary (e.g., `{'0th': zeroth_ifd, 'Exif': exif_ifd, 'GPS': gps_ifd}`) to `piexif.dump()`. affects: <1.0.0
gotchaPiexif has known issues when handling negative GPS coordinates (longitude/latitude). Directly passing negative values can lead to errors during `piexif.dump()` due to expected unsigned values.fixConvert negative coordinates to positive values and explicitly set the `GPSLatitudeRef` ('N' or 'S') and `GPSLongitudeRef` ('E' or 'W') tags to indicate the correct hemisphere. Custom helper functions for this conversion are often required. affects: All versions
gotchaWhen loading EXIF data from an image, especially when integrating with Pillow (`PIL.Image.open(filename).info["exif"]`), attempting to access `img.info["exif"]` directly might raise a `KeyError` if the image file contains no EXIF data.fixAlways check for the existence of the 'exif' key using `.get()` before attempting to load: `exif_bytes = img.info.get('exif'); if exif_bytes: exif_dict = piexif.load(exif_bytes)`. affects: All versions
gotchaFunctions like `piexif.dump()` or `piexif.transplant()` can raise an `InvalidImageDataError` if the input image data is malformed, corrupted, or contains an empty thumbnail segment, which `piexif` cannot process. This was partially addressed in version 1.0.12 with more explicit error handling.fixEnsure input JPEG data is valid and well-formed. Implement robust error handling (e.g., `try-except InvalidImageDataError`) around `piexif` operations when dealing with user-provided or potentially malformed image files. Inspect the source image or thumbnail data if this error occurs.
affects: <1.0.12 (less explicit errors), All versions (still possible with bad data)
gotchaWhen resizing an image with Pillow and then saving it with modified EXIF data, the `XResolution` and `YResolution` tags in the `0th IFD` might not automatically update to reflect the new dimensions. This can lead to EXIF metadata that doesn't match the actual image size.fixManually update `exif_dict["0th"][piexif.ImageIFD.XResolution]` and `exif_dict["0th"][piexif.ImageIFD.YResolution]` with the new `(width, 1)` and `(height, 1)` tuples respectively, after resizing the image and before dumping the EXIF data.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'piexif'
The 'piexif' library is not installed in the Python environment being used, or the environment's path is not correctly configured.
fixInstall piexif using pip: `pip install piexif`
ValueError: "dump" got wrong type of exif value. 41729 in Exif IFD. Got as <class 'int'>.
An EXIF tag's value in the dictionary passed to `piexif.dump()` is of an incorrect Python type. Piexif expects specific types (e.g., tuples for rational numbers) for EXIF tag values.
fixEnsure all EXIF tag values in the dictionary conform to the expected types, often rational numbers as tuples (numerator, denominator) or byte strings. For example, `(41729, 1)` instead of `41729` for rational tags.
KeyError: 'Exif' (when using piexif.load(img.info["exif"]) with PIL/Pillow)
The image file opened with Pillow (PIL) does not contain any EXIF data, so the `img.info` dictionary lacks the 'exif' key.
fixCheck if the 'exif' key exists in `img.info` before attempting to load it, or use `img.info.get('exif')` to safely retrieve the EXIF data, handling the `None` case if no EXIF is present.
```python
from PIL import Image
import piexif
img = Image.open('image.jpg')
exif_bytes = img.info.get('exif')
if exif_bytes:
exif_dict = piexif.load(exif_bytes)
# Process exif_dict
else:
print("No EXIF data found.")
``` ValueError: Given data isn't JPEG.
The input file provided to `piexif.load()` or `piexif.transplant()` is either not a valid JPEG, WebP, or TIFF file, or the data stream is corrupted or not in the expected format.
fixEnsure the input file is a valid JPEG, WebP, or TIFF image. Verify the file path is correct and the file itself is not corrupted. If processing byte data, ensure the bytes represent a complete and valid image file.
Upgrade
Version history
1.1.3latest on PyPI · released Jul 1, 2019
Audit
Dependencies
PillowoptionalWhile piexif is pure Python and has no hard dependencies, it is very commonly used in conjunction with Pillow (PIL Fork) for image loading, manipulation, and saving, especially when creating new images or handling complex image data flows.