Dev.to Security 🔐 Cybersecurity 👁 0 📖 4 min read

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
Instagram Stripped on upload
Twitter/X Stripped on upload
Facebook 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 (Orientation tag) 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.app/tools/exif-viewer

ToolZip — 48 free browser-based tools. Everything runs client-side.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.