Convert HEIC to JPG

iPhone photos are HEIC; WhatsApp, Shopee and most web forms are not. This page converts them in your own tab — nothing is uploaded, and the decoder loads only when you ask.

🔒 100% client-side · zero server upload

The first conversion downloads a 700 KB HEIC decoder (libheif, LGPL-3.0). It is fetched only when you press the button, and your browser caches it afterwards.

Results

    No demo file here on purpose: a sample HEIC would mean putting a stranger’s photo in the page. Use one of your own — it is decoded in this tab and never sent anywhere.

    Decoding runs in this browser tab. Your photos are never uploaded.

    Decoding uses libheif 1.23.5, unmodified, under LGPL-3.0. Source: github.com/catdad-experiments/libheif-js.

    Malaysian rules & edge cases

    Why HEIC needs its own page

    Every other tool here is a few kilobytes of JavaScript. A HEIC decoder is not: the file format wraps HEVC video frames, and browsers refuse to open it unless Safari made the file. So this page ships the one thing the rest of the site avoids — a 700 KB WebAssembly decoder — and pays for it honestly:

    WhatThis page
    Decoder download700 KB gzip, on the first conversion, cached by the browser afterwards. It is not part of the page load.
    Where decoding runsIn this tab, on your own CPU. No photo, filename or byte ever leaves the device.
    Librarylibheif 1.23.5, unmodified, LGPL-3.0 — source at github.com/catdad-experiments/libheif-js. Relinking is not required: the library is used as published, and the source offer is this notice.
    HEVC patentsDecoding is licensed by the codec inside the library; this site ships no encoder, so it never creates HEVC content.
    Accepted inputheic, heix, hevc and the generic mif1/msf1 brands. AVIF shares the container but needs an AV1 decoder this build does not carry — it is refused by name, not by a crash.
    Size limit20 megapixels. A 48 MP "HEIF Max" photo needs about 390 MB of pixel buffers in one tab and would be killed mid-decode; the row says so instead.
    One file, many imagesA HEIC burst or a Live Photo still holds several images. Each becomes its own result row and its own file — nothing is silently dropped.

    What it does not do. It does not write HEIC back: encoding HEVC is a patent-licensed product, and no browser can do it. It does not read HEIC from iCloud links or zip archives, and it does not upscale — a 12 MP photo comes out 12 MP.

    Before and after

    Before

    IMG_4821.HEIC · 2.4 MB · 4032×3024 · HEVC from an iPhone 15 · refused by the Shopee upload form, refused by Outlook, invisible in Word

    After

    IMG_4821.jpg · 0.9 MB · 4032×3024 · same photo, opens in every form, chat and print shop

    How it works

    1. Drop the HEIC photos — or tap Choose photos — and the first conversion fetches the 700 KB decoder.
    2. Pick JPEG for forms and chat, PNG for lossless, WebP for a website; the row shows the real bytes either way.
    3. Download one photo, or all of them as a single ZIP, and check the signed percentage before you upload.

    FAQ

    Is my photo uploaded to a server?

    No. The decoder is downloaded, but the photo is not: it is read from your file picker into this tab and decoded by your own CPU. You can watch the network panel — after the 700 KB decoder arrives, no request carries photo data, and turning off the network does not stop the conversion.

    Why does the page download 700 KB when I press convert?

    Because a HEIC decoder cannot be hand-written in a few hundred lines: HEVC is a video codec, and the reference implementation is 1.4 MB of WebAssembly. Shipping it on every page would make the whole site slower for everyone who came for a CSV tool, so it is fetched only here, only when needed, and cached afterwards.

    Will I lose quality or the date and location?

    The image is re-encoded at the quality you choose, so some detail goes — JPEG at 90% is visually identical at normal size. The EXIF block (camera, date, GPS) is not carried into the JPG: the decoder returns pixels, not metadata. That usually helps when you are about to upload the photo to a marketplace.

    What if my file is AVIF, or a burst of ten photos?

    AVIF is refused by name — it is the same container with an AV1 image inside, which this decoder build cannot read. A burst is handled the other way: every image inside the file becomes its own row, so ten photos give you ten rows and ten files in the ZIP, not one.