How to Strip EXIF Metadata from Images in Python

Remove EXIF metadata from image bytes using Pillow, with a mock JPEG generator for testing.

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 13 views 0 copies

Requires third-party packages — install first
pip install Pillow

Python code

50 lines
Python 3.9+
from 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

stdout
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

  1. Use piexif library for more granular EXIF manipulation instead of full removal
  2. 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

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Automation & scripting

Related tutorials and quizzes for this topic.