Why upload forms reject HEIC

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.

Empty MIME type for .heic Three checks, measured JPG passes all three

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.

The three checks, side by side

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:

CheckHEIC (sample.heic, 41,465 bytes)JPG out (sample.jpg, 38,078 bytes)
Name ends in .jpg / .jpegFailsPasses
Browser reports image/jpegFails — reports an empty stringPasses — image/jpeg
First bytes are FF D8 FFFails — starts 00 00 00 18Passes — ff d8 ff e0
Looser version: type starts with image/FailsPasses

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.

What your browser tells a form about a HEIC

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:

FileSizeMIME type the browser reports
photo.HEIC41,465 bytesempty string
photo.heif41,465 bytesempty string
sample.heic41,465 bytesempty string
batch_001.heic1,267,632 bytesempty string
photo.jpg100,826 bytesimage/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.

Does renaming it to .jpg get you in?

Partly, and the part it fails is the part that matters. I made two files whose names lie and ran the same three checks:

FileWhat the bytes areBrowser reportsNameMIMEFirst bytes
heic-bytes-named.jpgHEICimage/jpegPassesPassesFails — 00 00 00 18
jpeg-bytes-named.heicJPEGempty stringFailsFailsPasses — 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.

What the JPG looks like on the inside

I read the output file’s structure marker by marker, because a couple of these details decide whether a fussy pipeline accepts it:

MarkerMeaningSize
FFE0JFIF header16 bytes
FFE2ICC colour profile472 bytes
FFDB × 2Quantisation tables67 bytes each
FFC0Baseline frame (not progressive)—
FFC4 × 4Huffman tables—
FFDAScan 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.

Where the wall actually is

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:

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.

How to check a form in ten seconds

  1. Read the form’s own filter. Right-click the upload field, choose Inspect, and look for an accept attribute. If it lists only image/jpeg or .jpg,.png, a HEIC is out before you start.
  2. Watch where it fails. Rejected the moment you pick the file: a name or type check. Rejected after uploading: a check on the bytes, or on size.
  3. Convert and retry. If it still fails, the limit is size or dimensions, not format.

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.

Questions

Will renaming .heic to .jpg fool an upload form?

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.

Does the JPG keep the original resolution?

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.

Is the output a progressive JPEG?

No — the frame marker is FFC0, which is baseline. I saw no FFC2 in the output I dissected.

Does the converted JPG still carry my location?

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.

My upload form has a file-size cap. Will converting help?

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.

What I could not measure

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