Convert HEIC to JPG in the Browser (Files Stay on Your Device)
On this page· 6 sections
You can convert iPhone HEIC to JPG in the browser without uploading the files, because decoding and JPEG encoding both run in the tab. The batch that finishes depends on this machine: file size, how many decoded frames stay in memory, and whether this browser can decode HEIC itself.
HEIC to JPG is that converter. People looking for HEIC to JPG online, a browser HEIC to JPEG convert, or an iPhone HEIC convert with no upload get this local path: the file stays on the device. It is free, it has no watermark, and it does not ask for an account. Files are not sent to zhanghe.dev or any other server.
What the shipped tool converts
This note does not time a conversion. There is no recorded session with input bytes, output bytes, or wall-clock numbers for this tool. The figures below are the product page and the constants in the converter. Quote them as limits, not as a speed claim.
The product page describes iPhone HEIC stills turned into JPEG. Decode once, then move the quality slider to re-encode. The drop hint says up to 40 photos at once, 40MB each, still frames only, and Live Photo video is not extracted. The FAQ repeats the same boundary: input is HEIC or HEIF stills, output is JPEG, and a Live Photo video track is not extracted.
The file picker accept value is .heic,.heif,image/heic,image/heif. The checker also accepts the extensions .heic and .heif in any letter case, and the MIME types image/heic, image/heif, image/heic-sequence, and image/heif-sequence. A .jpg or .png name is rejected with "Only .heic or .heif files are accepted." An empty file is rejected. A file larger than the guard is skipped with "Skipped files larger than 40MB."
The guard in code is 40 * 1024 * 1024 bytes, which is 41,943,040. The on-page size formatter prints that value as 40.0 MB. The page copy says 40MB. A file of exactly 41,943,040 bytes is inside the guard. One byte over is not. The FAQ adds that device memory can lower the practical limit. This guide did not generate a file at that boundary.
Each accepted file becomes one JPEG. photo.heic is saved as photo.jpg. photo.HEIF uses the same stem, so a second file in the same batch is named photo-2.jpg. A blank name becomes photo.jpg. The list shows original size, JPEG size, and pixel width and height after decode. Those sizes are the files in the tab. This guide does not publish a sample pair.
Convert a batch without an upload
The privacy boundary is the one the FAQ states: decoding and JPEG encoding run in the browser. The photo bytes are not posted to a server. Downloads are blob: URLs created in the tab.
- Open HEIC to JPG.
- Drop HEIC or HEIF stills, or choose photos. A batch can include 40 photos. Past that, the page says "A batch can include 40 photos."
- Leave JPEG quality at 85, or move the slider. The range is 40 to 95 in steps of 1. The encoder passes that number divided by 100 to
OffscreenCanvasconvertToBlobwith typeimage/jpeg. - Wait until each row says Done, then download one JPEG or choose Download all ZIP.
The ZIP is named heic-to-jpg.zip. It is built in the tab with fflate zipSync at level 0, which stores the JPEGs instead of deflating them. Failed rows are left out. If nothing has finished, the page says "There are no JPEGs to download yet."
Quality, workers, and the decoder
The default quality is 85. Values outside 40 to 95 clamp back into that range. A non-numeric value falls back to 85. Moving the slider waits 120 ms, then re-encodes.
Re-encode uses the decoded bitmap when it is still in memory, which is the hint under the slider: changing quality does not decode HEIC again while that bitmap is cached. The cache keeps at most 8 full frames: the selected photo, then the most recently finished ones. A finished frame past that cap is closed. The next quality change queues it and decodes it again. That cap is a memory limit, not a timing result.
Parallel work uses a worker pool. The size is hardwareConcurrency capped at 4, and at least 1. If the browser reports a missing or zero concurrency, the pool falls back to 2. The page includes a screen-reader status of that count followed by " workers". Queued photos move to an idle worker. A worker is busy while it decodes and encodes that file. This guide did not measure how the count changes wall time.
Decode tries createImageBitmap on the HEIC blob first. If the bitmap has a width and a height above 0, the status reads "Using browser decoder". If that call fails or the bitmap is empty, the worker imports heic-to/csp and calls heicTo({ blob, type: "bitmap" }). The status then reads "Using local WASM decoder". The installed package is heic-to 1.5.2. Its package note says that release uses libheif 1.22.2. The tool does not call heic2any.
The product FAQ says browsers that can decode HEIC natively, such as Safari, use the system decoder, and that other browsers use the local WASM decoder, which can be slower on the first file. That sentence is the page copy. This guide did not time Safari against another browser, and it does not turn that sentence into a speed ranking.
Limits for size, metadata, and format
- Size. The page says 40MB each and 40 photos. The byte guard is 41,943,040. Under the guard is not a promise that a large still will finish. The FAQ already points at device memory.
- Batch. Forty is the slot cap. Extra files are skipped with the batch message. There is no folder picker on this page. Each drop or chooser action adds files until the 40 slots are full.
- Memory. Eight decoded frames stay. The rest are dropped and decoded again if you move the quality slider. The worker pool does not raise that cache.
- Metadata. The FAQ says orientation is applied to the pixels, and that date, GPS, and other EXIF fields are not written into the JPEG. The encoder in this tool draws the bitmap and calls
convertToBlobforimage/jpeg. There is no EXIF copy step in that function. This guide did not open a JPEG in an EXIF reader. - Live Photo. The page says the video track is not extracted. The worker returns one bitmap and one JPEG per file. The checker can accept a sequence MIME type, and the worker still returns one bitmap.
- Decoder. Native decode is whatever
createImageBitmapaccepts in this browser. The WASM path is the fallback. A file both paths reject is marked Failed. The worker fallback text is "Could not convert this HEIC file." - Not a cloud converter. Nothing in this tool posts the photo. A later tool on this site can upload for a different job. That upload is not this conversion.
Thumbnails in the list are a separate 160-pixel-wide JPEG encoded at quality 70. They are previews, not the download.
Two other local photo tools
WebP Converter turns JPEG, PNG, GIF stills, WebP, BMP, and iPhone HEIC into WebP. It has a quality slider or lossless WebP, a folder drop, and a ZIP. Its page allows 80 photos at 40MB each. Use it when the output should be WebP. HEIC to JPG writes JPEG only, and it does not offer a lossless mode.
Unbg cuts out JPEG, PNG, WebP, or GIF stills. It does not accept HEIC. Free mode runs ormbg / IS-Net in the browser. Pro and the API send the photo onward for cloud fal BiRefNet, and the page says files are not stored by default. Convert to JPEG here first only if the cutout tool is the next job, and read that page before you choose Pro.
Convert the stills on this device
To turn iPhone HEIC or HEIF into JPEG without an upload, open HEIC to JPG, set the quality, and download the JPEG or the ZIP. For WebP, including a lossless option and a folder batch, use WebP Converter. For a cutout of a JPEG, PNG, WebP, or GIF still, use Unbg.