Photos (JPEG images) taken with smartphones or digital cameras contain Exif (Exchangeable Image File Format) information, which is metadata such as the shooting date, camera model, aperture value, and ISO sensitivity.
Using Python’s Pillow library, you can easily retrieve and analyze this information. Since the raw data consists of numerical tag IDs, it is common to use the PIL.ExifTags.TAGS dictionary to convert them into human-readable item names.
Executable Sample Code
The following code is a script that retrieves Exif information from an image and displays a list of item names and values.
I have corrected typos in the provided user code and added error handling for cases where Exif information does not exist.
Note: Please be aware that Exif information is often deleted from images uploaded to social media or re-saved with image editing software.
from PIL import Image
from PIL.ExifTags import TAGS
import os
def read_exif_data():
filename = "photo_with_exif.jpg"
# There is no dummy image creation function for this example
# (Writing correct Exif programmatically is complex).
# Please specify a photo taken with your smartphone or camera.
if not os.path.exists(filename):
print(f"Warning: File '{filename}' not found.")
print("Please replace with the file path of your JPEG photo and run again.")
return
try:
with Image.open(filename) as img:
print(f"Loading: {filename}")
# Retrieve Exif data using the getexif() method
# * Old code often used _getexif(), but getexif() is now recommended
exif_data = img.getexif()
if not exif_data:
print("This image does not contain Exif information.")
return
print("\n--- Exif Information ---")
# Exif data is in dictionary format {tag_ID: value}
for tag_id, value in exif_data.items():
# Convert tag ID to a human-readable tag name (string)
# Manufacturer-specific tags not in TAGS are displayed as ID
tag_name = TAGS.get(tag_id, tag_id)
# Format for display
# (Omit values that are too long, such as binary data, for readability)
if isinstance(value, bytes) and len(value) > 20:
value = f"<Bytes Data: {len(value)} bytes>"
print(f"{tag_name:25}: {value}")
# Example of retrieving specific information (e.g., DateTime)
# 306 is the tag ID for 'DateTime'
print("\n[Specific Data]")
date_taken = exif_data.get(306)
print(f"Date Taken: {date_taken}")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
read_exif_data()
Explanation: Points of Exif Retrieval
1. image.getexif()
This method reads the Exif header information from the image file and returns an Image.Exif object (which behaves like a dictionary).
In the past, there were many examples using the internal method _getexif(), but currently, getexif() is the standard accessor in Pillow.
2. Conversion using TAGS Dictionary
The actual Exif data is a pair of “Numerical ID” and “Value” (e.g., 306: ‘2025:01:03 12:00:00’).
Since 306 does not convey meaning on its own, we use PIL.ExifTags.TAGS to map it.
from PIL.ExifTags import TAGS
tag_name = TAGS.get(306) # -> 'DateTime'
3. Major Exif Tag IDs
Here are examples of frequently used tag IDs and their names.
| Tag ID | Tag Name (TAGS.get) | Content |
| 271 | Make | Camera Manufacturer (e.g., Apple, Canon) |
| 272 | Model | Camera Model (e.g., iPhone 13) |
| 306 | DateTime | Shooting Date and Time (e.g., 2023:10:01 10:20:30) |
| 33434 | ExposureTime | Exposure Time / Shutter Speed (e.g., 1/60) |
| 34853 | GPSInfo | GPS Information (*Requires further decoding due to complex structure) |
