It is almost never about your photo. Three checks decide whether a form takes your file — and a HEIC fails all three. I ran each check today.
Short answer: an upload form can judge your file in three places — the file extension, the MIME type your browser reports, and the first bytes of the file itself. A HEIC fails all three, and the JPG that comes out of this converter passes all three. I evaluated every one of those checks in a real browser against real files today: Chrome reported no MIME type at all for .heic, .HEIC and .heif — an empty string, not even image/ something — while the converted JPG reported image/jpeg, began with the bytes ff d8 ff e0, and carried a baseline FFC0 frame.
What I measured on this site: I fed a real iPhone HEIC (41,465 bytes, 700×476) into the live converter and opened up the JPG that came back — 38,078 bytes in 679 ms. Renaming is the tempting shortcut, so I measured that too: HEIC bytes renamed to .jpg do fool two of the three checks, because the browser then reports image/jpeg for them. They still fail the third, and the third one is the one a server reads. Table below.
These are the checks themselves, evaluated in the page on the real files — the HEIC I started with and the JPG the converter produced from it:
| Check | HEIC (sample.heic, 41,465 bytes) | JPG out (sample.jpg, 38,078 bytes) |
|---|---|---|
Name ends in .jpg / .jpeg | Fails | Passes |
Browser reports image/jpeg | Fails — reports an empty string | Passes — image/jpeg |
First bytes are FF D8 FF | Fails — starts 00 00 00 18 | Passes — ff d8 ff e0 |
Looser version: type starts with image/ | Fails | Passes |
That is the whole problem in one table. A form does not need to be hostile to HEIC for your upload to bounce; it only needs to ask one of those questions.
The first surprise is that the browser says nothing at all. I put five files through the file input one after another and read back what the browser claimed each one was:
| File | Size | MIME type the browser reports |
|---|---|---|
photo.HEIC | 41,465 bytes | empty string |
photo.heif | 41,465 bytes | empty string |
sample.heic | 41,465 bytes | empty string |
batch_001.heic | 1,267,632 bytes | empty string |
photo.jpg | 100,826 bytes | image/jpeg |
Case makes no difference and neither does the size — all four HEIC variants came back with nothing. That is why this converter’s own file input has to spell its filter out literally as .heic,.heif,image/heic,image/heif: there is no browser-supplied type to match against. It is also why a form written as accept="image/*" leaves you staring at a HEIC the picker will not highlight.
Partly, and the part it fails is the part that matters. I made two files whose names lie and ran the same three checks:
| File | What the bytes are | Browser reports | Name | MIME | First bytes |
|---|---|---|---|---|---|
heic-bytes-named.jpg | HEIC | image/jpeg | Passes | Passes | Fails — 00 00 00 18 |
jpeg-bytes-named.heic | JPEG | empty string | Fails | Fails | Passes — ff d8 ff e0 |
Renaming a HEIC to .jpg buys you the two checks that happen in the browser and loses the one that happens on the server, because the server can read the file’s first bytes and they still say HEIC. The reverse row is the same lesson from the other side: an honest JPEG wearing a .heic name gets turned away by name-based checks even though its bytes are fine. If you want the file to pass everywhere, the bytes have to change, not the name — that is what converting it does.
I read the output file’s structure marker by marker, because a couple of these details decide whether a fussy pipeline accepts it:
| Marker | Meaning | Size |
|---|---|---|
FFE0 | JFIF header | 16 bytes |
FFE2 | ICC colour profile | 472 bytes |
FFDB × 2 | Quantisation tables | 67 bytes each |
FFC0 | Baseline frame (not progressive) | — |
FFC4 × 4 | Huffman tables | — |
FFDA | Scan data | — |
Three things to take from it. The frame marker is FFC0, meaning a baseline JPEG rather than a progressive one (FFC2) — baseline is the flavour that older software and print pipelines handle most reliably. There is no FFE1 EXIF segment at all, so nothing about the camera or the location travels with the file, which I opened up in the EXIF test. And the 472-byte ICC block is the sRGB profile I measured in the colour test, so the output is not arriving in a wide-gamut space that some viewers render oddly.
I did not audit any third-party upload form today, so I am not going to publish a list of services I never tested. What I did verify is the mechanism, and it is the same in every direction people report trouble from:
ftypheic where it expected FF D8. Renaming does not survive this one.Two limits that converting does not fix, both measured today: the output keeps the full resolution (a 4,032×3,024 HEIC came back 4,032×3,024), and it can get larger — 1,267,632 bytes in, 1,708,595 bytes out at the default 85% quality. So if a form caps file size or pixel dimensions rather than format, conversion alone will not get you through, and this page offers quality only, with no resize control. The trade-off between quality and size is measured in the file-size runs.
accept attribute. If it lists only image/jpeg or .jpg,.png, a HEIC is out before you start.None of that requires an account or an upload anywhere: the converter decodes on your own device, and it keeps working after the network goes away, which I measured in the offline test.
Two of the three checks, yes — the browser then reports image/jpeg for it, which I measured. The third check reads the file’s first bytes, and those still start 00 00 00 18. Whether that is enough depends entirely on whether the form bothers to look.
Yes. The 4,032×3,024 file I converted came out 4,032×3,024, and the 700×476 one came out 700×476. Nothing is resized and nothing is cropped.
No — the frame marker is FFC0, which is baseline. I saw no FFC2 in the output I dissected.
No. There is no EXIF segment in the output at all — no camera model, no GPS, no timestamps — which I confirmed by opening the file in the EXIF test.
Possibly not. Conversion changed the format, not the size floor: the 12 MP file I ran today went from 1,267,632 bytes to 1,708,595 bytes at 85%. A lower quality setting produces a smaller file — the measured trade-off is in the file-size runs — but this page has no resize control.
.heic is what this Chrome reports; another browser may fill it in.Hit a form that refuses your photo? Convert it here and try again — the bytes are what change, and nothing leaves your device.
First published: 27 September 2026