
GeoImageTaggerIf your application handles user-uploaded images, those files likely carry data you do not want to...
If your application handles user-uploaded images, those files likely carry data you do not want to serve or store. EXIF metadata can include GPS coordinates accurate to 3–5 meters, device serial numbers that fingerprint individual phones, and timestamps that map user routines. If you serve user images without stripping metadata, you are distributing that information to anyone who downloads the file.
EXIF data lives in the APP1 marker segment of JPEG files and in IFD structures within TIFF-based formats (including HEIC). The GPS sub-IFD contains tags like GPSLatitude, GPSLongitude, GPSLatitudeRef, GPSLongitudeRef, and GPSAltitude. Device identification lives in Make, Model, and BodySerialNumber. The combination of serial number and device model creates a unique fingerprint that can link anonymous uploads across platforms.
This is not theoretical. In 2012, EXIF GPS data in a photo published by Vice led to the arrest of John McAfee. The same year, the FBI used iPhone GPS metadata from a publicly posted photo to identify and arrest a hacker. Researchers analyzing dark web images demonstrated that unstripped GPS data could unmask 229 anonymous sellers by identifying the residential locations where product photos were taken.
ExifTool (CLI — the gold standard):
# Remove everything
exiftool -all= photo.jpg
# Remove everything and suppress backup files
exiftool -all= -overwrite_original photo.jpg
# Selective: remove GPS and serial number only
exiftool -GPS:all= -EXIF:BodySerialNumber= photo.jpg
# Batch: recursively strip all JPEGs in a directory
exiftool -all= -overwrite_original -r -ext jpg /path/to/images/
Sharp (Node.js):
const sharp = require('sharp');
// Strip all metadata
await sharp('input.jpg')
.withMetadata(false)
.toFile('output.jpg');
// Keep orientation but strip everything else
await sharp('input.jpg')
.withMetadata({ orientation: undefined })
.toFile('output.jpg');
Note that sharp with withMetadata(false) also strips ICC color profiles, which can cause color shifts. If that matters, extract and re-embed the profile separately.
Python (Pillow):
from PIL import Image
img = Image.open('photo.jpg')
# Create a new image without metadata
clean = Image.new(img.mode, img.size)
clean.putdata(list(img.getdata()))
clean.save('clean.jpg', quality=95)
This approach creates a pixel-identical copy without any metadata. For more granular control, piexif or exifread let you inspect and selectively delete specific IFDs.
Not every delivery channel strips metadata. Social media platforms (Instagram, Facebook, X) generally strip EXIF from public posts. But email attachments, cloud storage links, WhatsApp document-mode sends, Telegram file sends, and most forum uploads preserve the original file untouched.
If your pipeline serves user-uploaded images through a CDN or API, strip metadata at the processing stage — not at the client. Server-side stripping with ExifTool or Sharp ensures consistency regardless of how the image is later consumed.
Always verify after stripping. Some formats (HEIC, WebP with embedded XMP) can retain metadata in unexpected locations.
exiftool -GPS:all -EXIF:BodySerialNumber -EXIF:DateTimeOriginal output.jpg
For a browser-based verification tool that runs entirely client-side, GeoImageTagger's Metadata Viewer displays EXIF, GPS, IPTC, XMP, and raw fields without uploading to a server.
Full guide: How to Remove EXIF Data from Photos