I keep running into the same request: someone shoots photos on an iPhone, sends them to a Windows laptop, and the files won't open. The fix everyone reaches for is a "free online HEIC to JPG converter" — and almost every one of them means handing a stranger's photo library to a server you know nothing about.
That trade always bothered me. Converting a photo format is arithmetic. There is no reason it needs to leave the device.
The constraint I started with
HEIC is a HEIF container with images compressed by HEVC. Browsers can display it on Apple platforms but generally can't decode it elsewhere, which is why the conversion step exists at all.
The obvious implementation is a server: receive file, run the converter, return JPG. It's ten lines of code and it scales. It also means every photo passes through a disk you now have to secure, retain policy for, and eventually delete. For a tool people use once or twice a decade, that is a lot of custody for very little compute.
So the rule for the project was: the file never leaves the tab.
Making it work offline
The whole converter runs in the browser as WebAssembly. The page loads the decoder once, then decoding and re-encoding happen in the same tab. Nothing is posted anywhere.
This turned out to be easy for me to verify, which is the part I actually care about:
- Load the page, convert one photo, then pull the network cable and convert another. It still works.
- Open the Network panel while converting and watch: no request carries your image.
I'd rather ship something whose privacy claim you can falsify in ten seconds than something that asks you to trust a paragraph in a policy page.
What I measured
Claims about "smaller files" are cheap, so I ran real phone photos through it at quality 90 and at quality 75 and compared against the original HEIC:
| Phone | HEIC | JPG q90 | JPG q75 |
|---|---|---|---|
| iPhone 7 | 0.88 MB | 1.49 MB (1.70x) | 0.81 MB (0.92x) |
| iPhone 12 Pro | 1.72 MB | 2.55 MB (1.48x) | 1.52 MB (0.88x) |
| Samsung SM-A326B | 1.22 MB | 1.70 MB (1.40x) | 0.91 MB (0.74x) |
Two things worth noting. At quality 90 — the default — the JPG is roughly 1.4 to 1.7 times the size of the HEIC. You are paying for compatibility in bytes. At quality 75 it flips and the JPG can actually come out smaller than the original HEIC, at a visible quality cost.
I left the default at 90 because most people converting a photo want it to look the way it looked on the phone, not to win a file size contest.
The boring parts that matter
A few decisions that don't demo well but matter in practice:
- No sign-up. There's no account system, so there's nothing to sign into and no reason to collect an email.
- No quota. There's no server counting your conversions, so there's nothing to meter. The real limit is your device's memory.
- Batch mode downloads finished files as a ZIP. Converting 200 photos one at a time is a punishment.
- Quality is adjustable per conversion, and in batch you can set it for the whole batch.
Where it's honestly still rough
JPG is lossy. If you need an archival copy, keep the original HEIC — no converter will give you back what the encoder threw away. Large images get downscaled to fit what the browser can process in one go. And on low-memory Android devices, big batches get flaky, because browsers there are less generous with memory than desktop Chrome.
None of that is going to change. It's the shape of the problem, not a bug list.
Try it and check the claim
It's free, it's at heicly.io, and it works the same in Chrome, Edge, Firefox and Safari. If you want to test the no-upload claim, unplug your network after the page loads and convert something.
If you find a photo it chokes on, I'd genuinely like to know — that's the kind of bug that only shows up in other people's camera roll.
Top comments (0)