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>
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.
-
heic2anycan return an array. A multi-image HEIC (like a Live Photo burst) gives several blobs, so always checkArray.isArray(result). -
File type can be empty. On some systems the browser reports an empty
file.typefor.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
awaitis safer thanPromise.allon 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)