Read and Edit Image EXIF Metadata with Python
EXIF metadata stores information about how a photo was taken: camera model, date, GPS, exposure, and more. Python lets you read, modify, and remove it with Pillow and piexif.
Installation
pip install pillow piexif
Read EXIF Metadata
from PIL import Image
from PIL.ExifTags import TAGS
def read_exif(image_path):
img = Image.open(image_path)
exif = img._getexif()
if not exif:
print("No EXIF metadata found")
return {}
data = {}
for tag_id, value in exif.items():
tag = TAGS.get(tag_id, tag_id)
data[tag] = value
print(f" {tag:30}: {str(value)[:80]}")
return data
read_exif("camera_photo.jpg")
Read GPS Coordinates
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
def get_gps(image_path):
img = Image.open(image_path)
exif = img._getexif()
if not exif: return None
gps_info = {}
for tag_id, value in exif.items():
if TAGS.get(tag_id) == "GPSInfo":
for gps_id, gps_val in value.items():
gps_info[GPSTAGS.get(gps_id, gps_id)] = gps_val
def to_decimal(coords, ref):
deg, mins, secs = coords
dec = deg + mins/60 + secs/3600
return -round(dec, 6) if ref in ['S','W'] else round(dec, 6)
if 'GPSLatitude' in gps_info:
lat = to_decimal(gps_info['GPSLatitude'], gps_info.get('GPSLatitudeRef', 'N'))
lon = to_decimal(gps_info['GPSLongitude'], gps_info.get('GPSLongitudeRef', 'E'))
print(f"Location: {lat}, {lon}")
print(f"Google Maps: https://maps.google.com/?q={lat},{lon}")
return lat, lon
print("No GPS data found")
return None
get_gps("travel_photo.jpg")
Modify EXIF Metadata
import piexif
from PIL import Image
def edit_exif(input_file, output_file, author=None, description=None, date=None):
img = Image.open(input_file)
exif_raw = img.info.get("exif", b"")
try:
exif_dict = piexif.load(exif_raw) if exif_raw else {"0th":{}, "Exif":{}, "GPS":{}, "1st":{}}
except:
exif_dict = {"0th":{}, "Exif":{}, "GPS":{}, "1st":{}}
if author:
exif_dict["0th"][piexif.ImageIFD.Artist] = author.encode('utf-8')
if description:
exif_dict["0th"][piexif.ImageIFD.ImageDescription] = description.encode('utf-8')
if date:
# Format: "YYYY:MM:DD HH:MM:SS"
exif_dict["0th"][piexif.ImageIFD.DateTime] = date.encode('utf-8')
exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal] = date.encode('utf-8')
img.save(output_file, exif=piexif.dump(exif_dict))
print(f"EXIF updated: {output_file}")
edit_exif(
"photo.jpg", "photo_signed.jpg",
author="My Photography Studio",
description="Mountain landscape at sunset",
date="2024:06:15 18:30:00"
)
Strip EXIF (Privacy)
from PIL import Image
def strip_exif(input_file, output_file):
img = Image.open(input_file)
clean = Image.new(img.mode, img.size)
clean.putdata(list(img.getdata()))
clean.save(output_file)
print(f"EXIF removed: {output_file}")
def batch_strip_exif(folder, output_folder):
import os
from pathlib import Path
Path(output_folder).mkdir(exist_ok=True)
for name in os.listdir(folder):
if name.lower().endswith(('.jpg','.jpeg')):
strip_exif(
os.path.join(folder, name),
os.path.join(output_folder, name)
)
print(f" Cleaned: {name}")
strip_exif("original_photo.jpg", "private_photo.jpg")
batch_strip_exif("original_photos/", "clean_photos/")
Add GPS Coordinates to a Photo
import piexif
from PIL import Image
def add_gps(input_file, output_file, latitude, longitude):
img = Image.open(input_file)
exif_raw = img.info.get("exif", b"")
try:
exif_dict = piexif.load(exif_raw)
except:
exif_dict = {"0th":{}, "Exif":{}, "GPS":{}, "1st":{}}
def to_rational(value):
value = abs(value)
degrees = int(value)
minutes = int((value - degrees) * 60)
seconds = round(((value - degrees) * 60 - minutes) * 60 * 1000)
return [(degrees,1), (minutes,1), (seconds,1000)]
exif_dict["GPS"][piexif.GPSIFD.GPSLatitudeRef] = b'N' if latitude >= 0 else b'S'
exif_dict["GPS"][piexif.GPSIFD.GPSLatitude] = to_rational(latitude)
exif_dict["GPS"][piexif.GPSIFD.GPSLongitudeRef] = b'E' if longitude >= 0 else b'W'
exif_dict["GPS"][piexif.GPSIFD.GPSLongitude] = to_rational(longitude)
img.save(output_file, exif=piexif.dump(exif_dict))
print(f"GPS added: {latitude}, {longitude} -> {output_file}")
# New York City
add_gps("photo.jpg", "photo_geotagged.jpg", 40.7128, -74.0060)
Additional Resource
For converting images between JPG, PNG, WebP and other formats without any coding, use KaijuConverter — free and no registration required.
Related conversions
Most teams that read this guide convert images in one of these directions: