Your Photos Are Leaking Your Home Address — EXIF Data Explained
Every photo taken with a smartphone or modern digital camera contains hidden data you might not know about. This metadata — called EXIF — records where you were, what time it was, what device you used, and dozens of othe
Every photo taken with a smartphone or modern digital camera contains hidden data you might not know about. This metadata — called EXIF — records where you were, what time it was, what device you used, and dozens of other details, all embedded invisibly inside the image file.
When you share that photo, you share all of that data too.
What Is EXIF Data?
EXIF (Exchangeable Image File Format) is a standard for storing metadata in image files. It was developed by the Japan Electronics and Information Technology Industries Association (JEITA) in 1995 and is now supported by virtually every digital camera and smartphone.
The metadata recorded includes:
Camera information:
- Make and model (e.g., "Apple iPhone 15 Pro")
- Firmware version
- Lens focal length
- Aperture, shutter speed, ISO
- Flash used or not
Image information:
- Original resolution
- Color space
- Orientation (how the camera was held)
- Compression settings
GPS data (the sensitive part):
- Latitude and longitude to several decimal places
- Altitude
- GPS accuracy
- Direction the camera was pointing
Temporal data:
- Date and time of capture
- Time zone offset
Reading EXIF Data
Any image can be inspected for EXIF data. In JavaScript:
import ExifReader from 'exifreader';
async function readExif(file) {
const buffer = await file.arrayBuffer();
const tags = ExifReader.load(buffer);
// GPS coordinates
const lat = tags['GPSLatitude']?.description;
const lon = tags['GPSLongitude']?.description;
const latRef = tags['GPSLatitudeRef']?.description; // N or S
const lonRef = tags['GPSLongitudeRef']?.description; // E or W
// Camera info
const make = tags['Make']?.description;
const model = tags['Model']?.description;
// Timestamp
const dateTime = tags['DateTime']?.description;
console.log({ lat, lon, latRef, lonRef, make, model, dateTime });
}
The GPS coordinates in EXIF are stored in degrees, minutes, seconds format. Converting to decimal degrees:
function exifCoordToDecimal(coord, ref) {
if (!coord) return null;
// coord is typically [degrees, minutes, seconds] as fractions
const [deg, min, sec] = coord;
let decimal = deg + min / 60 + sec / 3600;
// Southern latitudes and Western longitudes are negative
if (ref === 'S' || ref === 'W') {
decimal = -decimal;
}
return decimal;
}
// Usage
const lat = exifCoordToDecimal(
tags['GPSLatitude']?.value,
tags['GPSLatitudeRef']?.value
);
The Privacy Risk Is Real
In 2012, a high-profile incident demonstrated the danger clearly: a public figure posted a photo to social media. The image's EXIF data contained precise GPS coordinates. Someone extracted those coordinates and identified the exact home address.
This isn't hypothetical. The pattern has been documented repeatedly:
- Photos shared "privately" on platforms that don't strip EXIF
- Images emailed as file attachments (not shared through social media upload flows)
- Photos posted to smaller sites or forums that don't process EXIF
- RAW files shared with photographers or designers
The major platforms (Instagram, Twitter, Facebook) now strip EXIF data server-side before showing images publicly. But direct file sharing doesn't go through this processing.
Which Platforms Strip EXIF?
| Platform | EXIF Handling |
|---|---|
| Stripped on upload | |
| Twitter/X | Stripped on upload |
| Stripped on upload | |
| WhatsApp (compressed) | Stripped |
| WhatsApp (original quality) | Preserved |
| KakaoTalk (compressed) | Stripped |
| KakaoTalk (original) | Preserved |
| Email attachments | Preserved |
| Direct file sharing | Preserved |
| Most blog platforms | Varies |
The "original quality" sharing option in messaging apps is the primary vector. Users often choose it without realizing they're also sharing their location.
Stripping EXIF Data in the Browser
Removing EXIF data client-side is straightforward — you re-encode the image through the Canvas API, which doesn't carry EXIF through the process:
async function stripExif(file, quality = 0.92) {
return new Promise((resolve) => {
const img = new Image();
const url = URL.createObjectURL(file);
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// Canvas export strips EXIF — it only outputs pixel data
canvas.toBlob((blob) => {
URL.revokeObjectURL(url);
resolve(blob);
}, file.type === 'image/png' ? 'image/png' : 'image/jpeg', quality);
};
img.src = url;
});
}
Why does this work? canvas.toBlob() exports only the raw pixel data of the canvas. EXIF metadata lives outside the pixel data in the file format's header structure. When you draw to canvas and re-export, only the pixels make the round trip.
Caveats:
- This approach always re-encodes the image, which means slight quality loss for JPEGs (controlled by the quality parameter)
- For PNGs, there's no quality loss but the file size may change
- The image orientation stored in EXIF (
Orientationtag) is also lost — you should apply the rotation to the canvas before exporting if you need to preserve it
Handling EXIF Orientation
One complication: EXIF stores image orientation data separately from the pixels. An image might be stored "sideways" in pixels but have an EXIF tag saying "rotate 90° clockwise to display." Stripping EXIF without applying the rotation first makes the image appear rotated.
async function stripExifWithOrientation(file) {
const buffer = await file.arrayBuffer();
const tags = ExifReader.load(buffer);
const orientation = tags['Orientation']?.value ?? 1;
return new Promise((resolve) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Apply rotation based on EXIF orientation
const { width, height } = getRotatedDimensions(img, orientation);
canvas.width = width;
canvas.height = height;
applyOrientation(ctx, orientation, img.naturalWidth, img.naturalHeight);
ctx.drawImage(img, 0, 0);
canvas.toBlob((blob) => resolve(blob), 'image/jpeg', 0.92);
};
img.src = URL.createObjectURL(file);
});
}
Preventing EXIF at the Source
If you'd rather not strip EXIF after the fact, you can disable GPS recording at the camera level:
iOS: Settings → Privacy & Security → Location Services → Camera → Never
Android: Open Camera app → Settings → Location tags (disable)
This prevents GPS from being recorded but doesn't remove other EXIF data like make, model, and timestamp.
Try It
ToolZip's EXIF viewer and remover reads all EXIF tags from an image (including displaying GPS coordinates on a map) and can strip the EXIF data entirely — all in the browser, no upload required.
ToolZip — 48 free browser-based tools. Everything runs client-side.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.