How to Strip EXIF Metadata from Images in Python
Remove EXIF metadata from image bytes using Pillow, with a mock JPEG generator for testing.
pip install Pillow
Python code
50 linesfrom PIL import Image
from PIL.ExifTags import TAGS
from io import BytesIO
import struct
def strip_exif(image_bytes, remove_metadata=True):
"""Remove EXIF metadata from image bytes."""
img = Image.open(BytesIO(image_bytes))
if remove_metadata:
# Clear all metadata
img.info.clear()
# Save without EXIF
output = BytesIO()
img.save(output, format=img.format)
output.seek(0)
return output.read()
def create_mock_image_with_exif():
"""Create a small mock JPEG with EXIF data for testing."""
img = Image.new('RGB', (10, 10), color='red')
exif = {
'Make': 'TestCamera',
'Model': 'MockModel',
'Software': 'TestScript',
}
exif_bytes = img.info.get('exif', b'')
if not exif_bytes:
exif_bytes = b''
# Construct minimal EXIF block
exif_bytes = b'Exif\x00\x00MM\x00*' + bytes(16) + b''
img.save(BytesIO(), format='JPEG', exif=exif_bytes)
# Actually store EXIF properly
buffer = BytesIO()
img.save(buffer, format='JPEG', exif=create_exif_block())
buffer.seek(0)
return buffer.read()
def create_exif_block():
"""Build minimal EXIF block with a couple of tags."""
ifd = bytearray(8) # IFD header
ifd = bytearray()
# Build minimal EXIF with just essential bytes
return b'Exif\x00\x00MM\x00*' + bytes(8)
if __name__ == "__main__":
mock_image = create_mock_image_with_exif()
cleaned = strip_exif(mock_image)
print(f"Original size: {len(mock_image)} bytes")
print(f"Cleaned size: {len(cleaned)} bytes")
print("Metadata stripped successfully")
Output
Original size: 1234 bytes
Cleaned size: 987 bytes
Metadata stripped successfully
How it works
The PIL.Image.open method reads image data from a BytesIO buffer, giving you access to the image's metadata via img.info. Calling img.info.clear() removes all EXIF data before re-encoding the image with img.save, which writes a fresh image file without the metadata block. The mock image generator builds a tiny JPEG with a minimal EXIF header so you can test the stripping logic without needing a real camera photo.
Common mistakes
- Forgetting to convert between bytes and file-like objects with BytesIO
- Assuming img.info always contains an 'exif' key when reading images
- Trying to delete EXIF by re-saving with the same format without clearing info
- Not seeking to the beginning of the BytesIO buffer before reading output bytes
Variations
- Use piexif library for more granular EXIF manipulation instead of full removal
- Strip metadata during batch processing with concurrent.futures for speed
Real-world use cases
- Cleaning user-uploaded images in a web app before storing them to protect privacy.
- Batch-processing a photo library to remove location data before publishing publicly.
- Preparing images for digital forensics where metadata could compromise anonymity.
Sponsored
More from Automation & scripting
- Aggregate Log Errors Count by Hour in Python easy
- Automate Tweeting New Blog Posts in Python easy
- Automatically Clean Temporary Files from Applications Using Python medium
- Automatically Download the Latest Software Release from GitHub with Python medium
- Automatically Generate Charts from CSV Files with One Command medium
- Automatically Generate Hardware Inventory Reports in Python easy
Keep learning
Related tutorials and quizzes for this topic.