Removing Photo Metadata Without Touching a Single Pixel

There is a hidden cost in most tools that promise to strip metadata from your photos, and it is not the one people worry about.

The worry is usually the upload — that your photo goes to somebody’s server before it comes back clean. That is a legitimate concern and we have written about how to check. But there is a second cost, quieter and more common, and it survives even when the tool runs entirely on your own machine.

Most metadata removers decode your photo and encode it again. And a JPEG that has been decoded and re-encoded is not the photo you started with.

Why re-encoding costs you something

JPEG is a lossy format. When a photo is saved as a JPEG, the encoder throws away detail it judges you will not miss — fine gradients, subtle colour variation, high-frequency texture. What remains is a lossy approximation, and that approximation is what your file contains.

Decode that file and you get pixels. Encode those pixels again and the encoder performs the same judgement a second time, on data that has already been through it once. It discards detail from an image that has already had detail discarded. Edges soften. Flat areas of sky develop faint blocking. Fine texture in hair or fabric smears slightly.

One round is usually invisible on a casual look. It is still a real, measurable, permanent loss, and it compounds every time it happens. If a photo passes through a resizer, then a converter, then a metadata stripper, each of which decodes and re-encodes, you have paid three times.

None of this is necessary to remove metadata. Not one bit of it.

What a JPEG actually looks like inside

A JPEG file is a sequence of segments, each introduced by a two-byte marker. Some segments carry the compressed image data. Others carry everything else.

A typical camera JPEG runs roughly like this:

  • FFD8 — start of image
  • FFE0 — a JFIF segment, basic format information
  • FFE1 — an APP1 segment containing the EXIF block
  • FFE2 — often an ICC colour profile
  • FFDB — quantisation tables
  • FFC0 — frame header: dimensions, components
  • FFC4 — Huffman tables
  • FFDA — start of scan, followed by the compressed image data
  • FFD9 — end of image

The EXIF block — camera model, serial numbers, timestamps, GPS coordinates, the lot — lives in that FFE1 segment. It is a discrete, self-contained region of the file. It sits alongside the image data, not inside it.

Which means removing it is not an image operation at all. It is a file operation. You locate the segment, you omit it, you write out everything else exactly as you found it. The compressed image data — the FFDA scan, the actual photograph — is copied through byte for byte. It is never decoded, so it is never re-encoded, so nothing is lost.

That is what lossless stripping means, and it is what our EXIF viewer and remover does.

How to prove it, rather than claim it

Any tool can assert that it preserves quality. The claim is worth exactly nothing without a test, so here is the one we ran.

We took a test photograph with a hand-constructed GPS block — 25,149 bytes, 23 EXIF tags including coordinates that resolved to 31.52040° N, 74.35870° E. We stripped it.

The cleaned file was 24,618 bytes. Every EXIF tag was gone: the FFE1 segment absent, neither the string “Exif” nor the camera name present anywhere in the bytes, only JFIF, the colour profile and the image tables remaining.

Then the part that matters. We decoded both files to raw pixels and took a SHA-256 hash of each.

The hashes matched.

Not “looked similar.” Not “no visible difference.” Identical — every pixel in the cleaned image bit-for-bit the same as every pixel in the original. The file was 531 bytes smaller and otherwise the same photograph in the most literal sense available.

As a second check, we compared the cleaned file’s byte count against the same image saved from scratch with no metadata at all. They matched, confirming nothing had been left behind in a segment we had failed to look at.

You can run the equivalent test on any tool you are considering. Strip a photo, then compare the decoded pixel data of the original and the result. If the hashes differ, the tool re-encoded your image, whatever its marketing says.

PNG and WebP are not JPEG

Almost every article on this subject assumes JPEG and stops there. Your other files carry metadata too, and they store it differently.

PNG is built from named chunks. EXIF lives in an eXIf chunk, and there are also tEXt, iTXt and zTXt chunks that commonly hold software names, authorship and comments. Stripping means dropping the chunks you do not want and rewriting the sequence — and PNG is losslessly compressed to begin with, so nothing is at risk either way.

WebP is a RIFF container, and it has a trap. Metadata sits in EXIF and XMP chunks, but the file also carries a VP8X extended-format header whose flags byte advertises which optional chunks are present. Delete the EXIF chunk and leave that byte alone, and the file now claims to contain metadata that is not there. Strict decoders will go looking, and some will complain or fail.

Our tool patches the VP8X flags to clear the EXIF, XMP and ICC bits when the corresponding chunks are removed. It is a small detail. It is the difference between a valid file and one that happens to work in most viewers.

The one thing we do not remove by default

Colour profiles stay unless you ask for them to go.

An ICC profile describes how the numbers in your file map to actual colours. Remove it and the image does not become anonymous — it becomes wrong. Colours shift, often subtly enough that you will not notice until you print it or open it on a wide-gamut display.

A colour profile is also not personal data. It says something about your monitor or your camera’s colour space, not about you, where you were or what equipment serial number you own. Stripping it costs you accuracy and buys you no privacy, so the default is to keep it, with the option to remove it if you have a reason.

A bug worth admitting to

While building the parser we wrote a lookup that decided whether a tag pointed to a sub-directory. It tested links[tag] != null against a map whose keys had all been initialised to null.

The branch never fired. Sub-IFD pointers were never followed. And the two most sensitive things in the file — GPS coordinates and lens data — live in sub-directories.

The tool ran without errors. It displayed metadata. It reported “no GPS data found” on a file that contained GPS data, and it would have gone on doing so indefinitely.

We caught it only because the test fixture had known coordinates to check against. A test that asked “does it run” would have passed. A test that asked “does it find 31.52040° N” failed loudly, which is the entire argument for testing against known answers rather than against the absence of a crash.

If you use a metadata tool and it tells you a photo is clean, that is worth exactly as much as the tool’s test suite. Ours now parses that fixture back to the exact degrees, minutes and seconds encoded in it, every build.


Strip metadata from your photos in your browser with the EXIF viewer and remover. Nothing is uploaded, and nothing is re-encoded.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top