DEV Community

BellSal
BellSal

Posted on

The HTML canvas quietly deletes your photo's metadata — and one day that bites you

I build browser-based image tools, and the single most confusing class of bug reports I get all trace back to the same fact: the moment a photo passes through a <canvas>, its metadata is gone. No EXIF, no GPS, no color profile, no orientation flag. The canvas carries pixels and nothing else.

Most of the time that's a feature. Sometimes it's a silent disaster. Here's both sides.

What actually happens

When you draw an image to a canvas and read it back out:

const canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
canvas.getContext("2d").drawImage(img, 0, 0);
const out = canvas.toDataURL("image/jpeg", 0.85); // or toBlob
Enter fullscreen mode Exit fullscreen mode

out is a brand-new JPEG encoded from raw pixels. Every ancillary chunk the original file carried — the EXIF block, the IPTC/XMP metadata, the ICC color profile — never existed in the canvas, so none of it makes it into the output. There's no flag to preserve it. The pixels are all the canvas ever had.

The good side: free metadata stripping

This is genuinely useful. If you run a photo through any canvas-based compressor, resizer or format converter, the output is automatically clean:

  • The GPS coordinates that say where you took the photo? Gone.
  • The camera serial number, the timestamp, the "edited by X"? Gone.
  • The little privacy leak that is a raw phone photo? Gone.

So a browser tool that re-encodes an image is also, for free, a metadata stripper — whether or not that's advertised as the point. I lean on this on purpose: "compress this image" and "scrub this image before I post it" become the same operation, done locally, with nothing uploaded.

One caveat worth stating loudly: this only protects you if the tool processes locally. If the page uploads your file to a server to do the work, you've handed the metadata to that server on the way to deleting it. "Runs in the browser" is the part that matters, not "strips EXIF."

The bad side: the orientation bug that eats an afternoon

Here's the one that generates the confused bug reports. iPhones (and many other cameras) don't rotate the pixels when you turn the phone. They store the image in the sensor's native orientation and set an EXIF Orientation flag — "display this rotated 90°." Your photo viewer reads that flag and rotates on display. The pixels themselves are sideways.

Now send that image through a canvas. The canvas draws the raw pixels — sideways — and the orientation flag, like all metadata, is dropped. Your output is a photo that is now permanently rotated the wrong way, with no flag left to correct it.

The infuriating part is that it looks fine in your <img> preview, because the browser applied the orientation flag when it displayed the original. It only breaks after the canvas round-trip. So the user sees a correct preview, downloads the result, and it's rotated. Classic "works on my screen."

The fix, since 2020-ish, is one line. Tell the browser to bake the orientation into the pixels when it decodes:

const bitmap = await createImageBitmap(file, { imageOrientation: "from-image" });
// now draw `bitmap` to the canvas — pixels are already upright
Enter fullscreen mode Exit fullscreen mode

Or, if you draw an <img> element instead, CSS image-orientation: from-image (the default in modern browsers) fixes the display — but not what drawImage reads. drawImage still takes the raw pixels. So for canvas work, createImageBitmap with imageOrientation: "from-image" is the reliable route. Test it with a portrait photo taken on a phone held sideways; a landscape screenshot will never reveal the bug.

The rule I settled on

Two sentences I now keep in my head whenever a canvas touches user images:

  1. Assume all metadata is lost the instant you drawImage. If you need to keep any of it (orientation, color profile, a copyright tag), handle it explicitly before the round-trip — don't hope it survives, it won't.
  2. Treat the loss as a privacy win only if the processing is local. Uploading to strip is theatre.

If you want to see both sides in practice, both tools are mine and free: an EXIF viewer to see exactly what your photos are carrying, and the compressor that drops all of it while it shrinks the file — both running entirely in the browser, nothing uploaded.

Top comments (0)