Remove EXIF data: what each method actually leaves behind

No upload Pixels untouched Measured on this machine

Short answer: there are two families of method, and they are not interchangeable. Re-saving the photo through an editor removes the metadata as a side effect of rewriting the file — it also re-encodes the pixels, so the picture you get back is not bit-for-bit the picture you put in. Stripping the segment deletes the metadata block in place and leaves every pixel exactly as it was. Both end up with no EXIF; only one leaves the photo untouched.

The part almost nobody warns you about: the check you run afterwards can lie. Some files carry their EXIF in a form that common readers do not recognise, and those readers will report no EXIF found while the GPS coordinates and the camera serial number are still sitting in the file. We measured that below, with the exact output.

Scope, stated first: this page is about file metadata — the tags a camera writes. It is not about AI watermarks. Claude's text watermark is a statistical pattern in how the model chose its words, not data stored in a file; Anthropic's own documentation says “nothing is added to the text and there are no hidden characters”. No EXIF remover touches it. What Claude does attach to the images it generates is a C2PA content credential, which is metadata and genuinely can be deleted. The two layers, explained →

What “remove EXIF data” actually deletes

EXIF is a block in the file header, ahead of the compressed picture. It carries the make and model of the camera, the lens, the exposure settings, the date and time to the second, the camera's body serial number, the artist or owner name the camera was configured with, and — if location services were on — GPS coordinates in decimal degrees. Many cameras also write a small JPEG copy of the picture into the same block so file browsers can show a preview without decoding the whole thing.

None of that is the photograph. That is why removing it can be done without touching a single pixel, and why the file usually gets smaller rather than blurrier.

Two tags are worth knowing before you delete anything, because they are not identifying data and they do affect how the picture looks:

The check that says there is nothing to remove

Before you pick a method, check the file. Most people do this with whatever image library or file property panel they have to hand, and that is where the trouble starts.

The specification puts a six-byte identifier — Exif\0\0 — in front of the EXIF block. Readers look for it. But some writers put the TIFF structure straight into the block with no identifier at all. The data is identical; the label is missing. A reader that searches for the identifier finds nothing and reports the file as clean.

We built two files that carry the same GPS coordinates, the same serial number and the same owner name. One writes the identifier, one does not. Same data, two answers:

SAME DATA, WRITTEN TWO WAYS Same GPS, same serial number, same owner name in both files written with the Exif\0\0 identifier (30,903 bytes) a spec-reading tool reports: 270 bytes of EXIF, Orientation 6 GPS 37.789556, 122.419333 · serial AX1-4417-2026 · owner Alex Rivera written as a bare TIFF block, no identifier (130,121 bytes) the same tool reports: 0 bytes of EXIF, no orientation GPS 37.789556, 122.419333 · serial AX1-4417-2026 · owner Alex Rivera identical data — one reader sees it, one does not

That second file is not exotic. It is the form this site's cleaner was failing to recognise until a reader reported a batch of photos coming back sideways — the orientation was there, in a block nobody was reading. So: if a check tells you a file has no EXIF, confirm it with something that reads the block itself rather than looking for the label.

Three ways to remove it, measured on one photo

One source file, four results. The source is a 1,600 × 1,200 JPEG carrying GPS coordinates, a body serial number, an owner name, an embedded thumbnail and Orientation = 6. Every number in this table came out of a run on this machine, not out of a spec sheet.

MethodResultPixelsWhat was left in the file
Nothing done (the source) 130,121 B baseline GPS 37.789556, 122.419333 · serial AX1-4417-2026 · owner Alex Rivera · thumbnail 3,178 B
Re-save through a library, no EXIF handed over 126,722 B changed nothing identifying — but see the next section
Strip the segment in place (this site's tool) 126,473 B byte-identical Orientation 6, in a 34-byte block
Delete every APP1 segment by hand 126,437 B byte-identical nothing — Orientation included, so an upright photo turns sideways

The file sizes differ by a few hundred bytes and all four look the same in a file manager. The difference that matters is the third column.

ONE PHOTO, THREE METHODS source: 130,121 bytes, GPS + serial + owner + thumbnail, Orientation 6 re-save the file 126,722 B pixels re-encoded scan sha256 cab64ad8c967ba79 (was 044f4ea22577267b) strip the segment 126,473 B pixels byte-identical scan sha256 044f4ea22577267b · orientation kept delete every APP1 126,437 B pixels byte-identical, orientation lost upright photos come out rotated 90 degrees

Why re-saving is not the same as stripping

Both end with a file that has no EXIF. They get there by different routes, and the route shows up in the picture.

Re-saving decodes the image and compresses it again. The compressed data that comes out is not the compressed data that went in — in our run the scan data changed from 044f4ea22577267b to cab64ad8c967ba79. That is not visible at a glance, but it is a second generation of compression on a photo that was already compressed once, and doing it repeatedly is how people end up with soft, slightly muddy files.

Stripping does not decode anything. The metadata lives in a segment ahead of the scan; deleting that segment and writing the rest back untouched leaves the compressed picture exactly as the camera encoded it. In our run the scan hash is unchanged, byte for byte. This is also why the stripped file is larger than the re-saved one here: keeping the original compression is worth more than the bytes saved by re-encoding.

If you are going to re-save anyway because you are resizing or editing the photo, this does not matter — you are already re-encoding. If the only thing you want is to remove EXIF data, re-saving is an expensive way to do it.

The one tag a careful stripper puts back

Delete the whole EXIF block and you delete Orientation with it. On a photo where Orientation was 1 — meaning the pixels are already stored the right way up — nothing happens. On a phone photo taken upright, where the pixels are stored sideways and Orientation is what tells the viewer to rotate them, the picture comes out rotated.

So a stripper has a choice: leave the photo alone and upright, or delete every last tag. This site rebuilds a 34-byte EXIF block holding that single tag and nothing else. It is the only metadata we write back, and it is not identifying data — it is a number from 1 to 8 that says which way up to hold the picture. (The full list of what gets dropped and what gets kept →)

Check the result yourself

Standard library only, nothing to install. Save as exif_check.py and point it at a file or a whole folder. It reads the EXIF block itself instead of asking a library to look for the identifier — which is the entire point, given the section above.

import os, struct, sys

NAMES = {271: "camera make", 272: "camera model", 274: "orientation",
         305: "software", 315: "artist / owner", 33432: "copyright",
         42033: "body serial number"}

def read_ifd(b, off, endian):
    if off + 2 > len(b):
        return {}, 0
    n = struct.unpack(endian + "H", b[off:off + 2])[0]
    out = {}
    for i in range(min(n, 200)):
        p = off + 2 + i * 12
        if p + 12 > len(b):
            break
        tag, typ, cnt = struct.unpack(endian + "HHI", b[p:p + 8])
        size = {1: 1, 2: 1, 3: 2, 4: 4, 5: 8, 7: 1}.get(typ, 1) * cnt
        raw = b[p + 8:p + 12]
        if size > 4:
            vp = struct.unpack(endian + "I", raw)[0]
            if vp + size > len(b):
                continue
            raw = b[vp:vp + size]
        out[tag] = (typ, cnt, raw[:size])
    nxt = struct.unpack(endian + "I", b[off + 2 + n * 12:off + 6 + n * 12])[0]
    return out, nxt

def text(typ, cnt, raw, endian):
    if typ == 2:
        return raw.rstrip(b"\x00").decode("ascii", "replace")
    if typ == 3 and cnt == 1:
        return str(struct.unpack(endian + "H", raw)[0])
    return ""

def dms(d, endian):
    if len(d) < 24:
        return None
    total = 0.0
    for i in range(3):
        num, den = struct.unpack(endian + "II", d[i * 8:i * 8 + 8])
        if den:
            total += (num / den) / (60 ** i)
    return total

def check(path):
    b = open(path, "rb").read()
    if b[:2] != b"\xff\xd8":
        return "%-34s not a JPEG" % os.path.basename(path)
    i = 2
    while i < len(b) - 1:
        if b[i] != 0xFF:
            break
        m = b[i + 1]
        if m == 0xDA:
            break
        if m in (0xD8, 0xD9) or 0xD0 <= m <= 0xD7 or m == 0x01:
            i += 2
            continue
        ln = struct.unpack(">H", b[i + 2:i + 4])[0]
        p = b[i + 4:i + 2 + ln]
        if m == 0xE1:
            # accept both forms: "Exif\0\0" + TIFF, and a bare TIFF block
            t = p[6:] if p[:6] == b"Exif\x00\x00" else p
            if t[:4] == b"II*\x00":
                endian = "<"
            elif t[:4] == b"MM\x00*":
                endian = ">"
            else:
                i += 2 + ln
                continue
            ifd0, nxt = read_ifd(t, struct.unpack(endian + "I", t[4:8])[0], endian)
            found = []
            for tag in (271, 272, 305, 315, 33432, 42033, 274):
                if tag in ifd0:
                    v = text(ifd0[tag][0], ifd0[tag][1], ifd0[tag][2], endian)
                    if v:
                        found.append("%s %s" % (NAMES[tag], v))
            if 34665 in ifd0:
                sp = struct.unpack(endian + "I", ifd0[34665][2])[0]
                sub, _ = read_ifd(t, sp, endian)
                if 42033 in sub:
                    v = text(sub[42033][0], sub[42033][1], sub[42033][2], endian)
                    if v:
                        found.append("body serial number %s" % v)
            if 34853 in ifd0:
                gp = struct.unpack(endian + "I", ifd0[34853][2])[0]
                g, _ = read_ifd(t, gp, endian)
                lat, lon = dms(g[2][2], endian), dms(g[4][2], endian)
                if lat and lon:
                    found.append("GPS %.6f, %.6f" % (lat, lon))
            if nxt:
                ifd1, _ = read_ifd(t, nxt, endian)
                if 514 in ifd1:
                    found.append("thumbnail %d bytes"
                                 % struct.unpack(endian + "I", ifd1[514][2])[0])
            return "%-34s %s" % (os.path.basename(path),
                                 ", ".join(found) or "nothing identifying")
        i += 2 + ln
    return "%-34s no EXIF block" % os.path.basename(path)

if __name__ == "__main__":
    files = []
    for t in sys.argv[1:]:
        if os.path.isdir(t):
            files += [os.path.join(t, f) for f in sorted(os.listdir(t))
                      if f.lower().endswith((".jpg", ".jpeg"))]
        else:
            files.append(t)
    for f in files:
        print(check(f))

Running it over the four files from the table above prints this:

cropped-rot6.jpg        camera make Aurora, camera model Aurora X100, software Aurora Camera 4.2,
                        artist / owner Alex Rivera, orientation 6, body serial number AX1-4417-2026,
                        GPS 37.789556, 122.419333, thumbnail 3178 bytes
01-pil-resave.jpg       no EXIF block
03-strip-segments.jpg   orientation 6
04-drop-all-app1.jpg    no EXIF block

That third line is the one to look for: one tag left, on purpose, and no longer anything that identifies anyone.

The honest limits

This removes metadata. It does not remove anything that is part of the picture. A logo or a watermark burned into the pixels is image data, not a tag, and no header surgery reaches it.

It also cannot remove a statistical watermark. Those are not stored in the file — they are a property of how the text or image was generated. If you are here because you want Claude's watermark gone, read that first; the short version is that no tool does it, and any site promising otherwise is selling you something else.

The measurements on this page were taken on this machine with the tools available here. Methods we could not run — command-line ExifTool on a machine that does not have it, macOS Preview, phone apps, hosted services — are left out rather than guessed at. The numbers above are real output from real runs; we did not estimate any of them.

Frequently asked questions

What is the easiest way to remove EXIF data?

Drop the file into the cleaner on this site. It runs in your browser, so the photo never leaves your device, and it strips the metadata without re-encoding the picture. If you would rather not upload anything at all — even to yourself — the script further up this page does the same check locally, and the folder cleaner in this guide shows the batch form.

Does saving a photo again remove its EXIF data?

Often yes, but not because you asked it to — because re-encoding writes a new file and most editors do not carry the old metadata across. That is a side effect, not a guarantee: some editors do carry it across, and some only carry part of it. The cost is that you also re-compress the picture. In our test the re-saved file's scan data changed hash while a stripped file's did not.

How do I clear EXIF data from a whole folder?

Point a folder-wide script at it rather than opening files one at a time. The pattern that works is: walk the folder, filter to image extensions, run the strip on each file, then re-run the check over the folder to confirm. This page has a working folder script, including a dry-run mode so you can see what would change before it writes anything, and a pre-commit hook if the folder is a git repository.

Does deleting EXIF data reduce image quality?

Deleting it, no. Re-encoding to delete it, yes — slightly, and cumulatively. Removing a header block cannot degrade the picture, because the picture is not in that block. The quality loss people associate with metadata removal comes from the re-save, not from the removal.

Why did my photo turn sideways after I deleted the EXIF data?

Because the tool deleted the Orientation tag along with everything else. A phone held upright usually stores landscape pixels plus Orientation = 6, and viewers rotate on display. Remove the tag and the raw pixels are shown as stored, so the picture is rotated 90 degrees. Nothing about the image changed; the instruction for displaying it did. This is why the cleaner here rebuilds a 34-byte block containing that one tag.

Can I trust an online EXIF remover with my photos?

Only if it processes the file in your own browser. Many sites upload your photo to their server first, which means the GPS coordinates and serial number you were trying to remove have just been handed to someone else — and you have no way to check whether the copy was deleted afterwards. You can test any site: open your browser's network panel before dropping the file in and look at where the request goes. If the photo is uploaded, the removal is not private.

Any good tools for removing EXIF data from photos and videos?

For photos, three families: a browser tool that never uploads (like the one on this site), a command-line tool, or a scripting library. All three are fine if you verify the result afterwards. Videos are a separate job and this tool does not do them. Video metadata lives in a different container structure (the atoms in an MP4 or MOV), not in a JPEG header segment, so a photo stripper has nothing to work on. If a page promises one tool for both, check whether it actually rewraps the video rather than just claiming to.

Is there a camera app for android that will remove all metadata/EXIF data?

The reliable fix is at the source rather than in an app afterwards: turn off the camera's location permission and it stops writing GPS coordinates into new photos in the first place. For photos you already have, run them through a stripper before sharing. We have not tested Android camera apps on this machine, so we are not going to name one — and any list you find will be out of date within a year. What does not go out of date is the check: strip, then run the script above and confirm it prints nothing identifying.

Any app that randomizes these information?

That is a different operation from removing it, and it is worth being clear about which one you want. Stripping deletes the fields. Randomising writes different values in their place — a fake camera model, a fake serial number, a different date. This site deletes; it does not fabricate. If your goal is to stop one account being tied to another, deletion is the stronger option, because a randomised value is still a value that can be correlated, and a wrong date can break the sorting in whatever you upload the photo to.