DEV Community

ai startup
ai startup

Posted on

Convert iPhone HEIC photos to JPG in the browser with JavaScript

iPhones save photos as HEIC by default. They are about half the size of JPG, but many websites, forms and Windows apps cannot open them. A common request is "let users upload an iPhone photo", and most upload forms reject .heic.

You can convert HEIC to JPG entirely in the browser, with no server. Here is a small, working approach using the heic2any library.

Why not just use a canvas?

Normally you would draw an image onto a canvas and call toBlob(). That fails for HEIC in most browsers, because only Safari can decode HEIC natively. Chrome, Firefox and Edge cannot load a .heic file into an <img>. So you need a decoder, and heic2any ships one compiled to WebAssembly.

Minimal code

<input type="file" id="file" accept=".heic,.heif,image/heic,image/heif" multiple>
<ul id="list"></ul>
<script src="heic2any.min.js"></script>
<script>
document.getElementById('file').addEventListener('change', async (e) => {
  const list = document.getElementById('list');
  list.innerHTML = '';

  for (const file of e.target.files) {
    try {
      const result = await heic2any({
        blob: file,
        toType: 'image/jpeg',
        quality: 0.9
      });
      const blob = Array.isArray(result) ? result[0] : result;

      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = file.name.replace(/\.[^.]+$/, '') + '.jpg';
      a.textContent = 'Download ' + a.download;

      const li = document.createElement('li');
      li.appendChild(a);
      list.appendChild(li);
    } catch (err) {
      console.error(file.name, err);
    }
  }
});
</script>
Enter fullscreen mode Exit fullscreen mode

Details that matter

  • The library is large (about 1.3 MB). Load it lazily, only after the user picks a HEIC file, so normal page loads stay fast.
  • heic2any can return an array. A multi-image HEIC (like a Live Photo burst) gives several blobs, so always check Array.isArray(result).
  • File type can be empty. On some systems the browser reports an empty file.type for .heic, so also check the file name extension, not just the MIME type.
  • Convert files one at a time. Decoding is memory-heavy, so a loop with await is safer than Promise.all on a big batch.
  • Quality 0.9 is a good default. You rarely see a difference from 1.0, and the JPG is much smaller.
  • No upload needed. The file is read locally, which is good for private photos.

Try it without writing code

I turned this into a small free tool: HEIC to JPG converter (there is also HEIC to PNG). It converts several photos at once and runs entirely in your browser. A step-by-step guide for non-developers is here: how to convert HEIC to JPG.

Questions or edge cases you have run into with HEIC? Happy to discuss in the comments.

Top comments (0)