HEIF to PNG API
POST a .heif to /v2/convert/heif/to/png and get an 8-bit RGBA PNG of the decoded image. The HEIF's separate alpha plane becomes the PNG's alpha channel: the sticker's 11,811 partly transparent shadow and edge pixels (alpha 1 to 254) came through within 5 levels of the drawing.
- Endpoint
- POST /v2/
convert/ heif/ to/ png - Accepts
- heif
- Sample timing
- 24 ms median of 5 runsHow we measure
- Request size
- Up to 10 MB on the Free plan or 100 MB on paid plans, all files together
Request and response
Every sample below ran against the API before this page was published. Set PDFCONVERSIONAPI_KEY to your key and run it as is.
curl -sS -X POST \
https://api.pdfconversionapi.com/v2/convert/heif/to/png \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@succulent-sticker.heif \
-o response.json
# FileData is base64. Save the first file in converted/,
# or print the JSON error.
if jq -e '.Files' response.json > /dev/null; then
mkdir -p converted
name=$(jq -r '.Files[0].FileName' response.json)
jq -r '.Files[0].FileData' response.json \
| base64 --decode > "converted/$name"
else
cat response.json
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/heif/to/png",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("succulent-sticker.heif", "rb"))],
timeout=180,
)
result = response.json()
if not response.ok:
raise SystemExit(f"{result['Code']}: {result['Message']}")
os.makedirs("converted", exist_ok=True)
for file in result["Files"]:
path = os.path.join("converted", file["FileName"])
with open(path, "wb") as out:
out.write(base64.b64decode(file["FileData"]))
print(path, file["FileSize"], "bytes")
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
const form = new FormData();
const file = "succulent-sticker.heif";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/heif/to/png";
const key = process.env.PDFCONVERSIONAPI_KEY;
const response = await fetch(url, {
method: "POST",
headers: { Authorization: `Bearer ${key}` },
body: form,
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${result.Code}: ${result.Message}`);
}
await mkdir("converted", { recursive: true });
for (const file of result.Files) {
const path = join("converted", file.FileName);
await writeFile(path, Buffer.from(file.FileData, "base64"));
console.log(path, file.FileSize, "bytes");
}
{
"ConversionCost": 1,
"ConversionTime": 0.024,
"Files": [
{
"FileName": "succulent-sticker.png",
"FileExt": "png",
"FileSize": 46906,
"FileData": "iVBORw0KGgoAAAANSUhEUgAA…"
}
]
}Response from our test run on 2026-11-03. ConversionTime shows the median of 5 runs. FileData is shortened here; the real response carries the whole file as base64.
The sample, converted
The same file the code sends. Download the input and the output and compare them yourself.

- Input
- succulent-sticker.heif (11 KB)
- Output
- succulent-sticker.png (46 KB)
- Source
- A potted succulent sticker that we drew ourselves, with a transparent background and a soft shadow, saved as a 320 x 320 HEIF with an alpha plane. (CC0-1.0). How it was made
- Made by
- 2026-11-04, API build
9eeeb0640aba
Parameters
Send these as form fields next to the file. Names are case-insensitive. If you set one of the documented options below that we don't support yet, the request fails with a 400 that names it instead of returning a file made without it.
| Parameter | What it does |
|---|---|
ImageWidthinteger | Scales color and alpha together; 200 gave 23,052 bytes, 800 gave 227,128.Values: 1–20000 |
ImageHeightinteger | Target height, or a box together with ImageWidth.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches to both sizes. |
ScaleIfLargerboolean, default false | true doesn't enlarge small images. |
ScaleImageboolean, default true | false cuts the top-left area instead of scaling. |
ImageResolutioninteger | Adds a pHYs chunk with this many dots per inch.Values: 10–800 |
ColorSpaceenum, default default | gray writes gray plus alpha (22,378 bytes); monochrome black and white plus alpha (11,890 bytes).Values: default, rgb, gray, monochrome |
TransparentColorstring | Clears pixels of exactly this color on top of the existing alpha. #C4623B removed 5,931 pot pixels.Values: #RRGGBB, R,G,B or a basic color name |
FileNamestring | Base name for the PNG. |
StoreFileboolean, default false | true keeps the PNG for 3 hours and returns a link. |
What carries over, and what doesn't
Kept
- The alpha plane: 72,482 clear, 11,811 partly clear and 18,107 opaque pixels, against 72,969, 11,032 and 18,399 in the drawing
- Opaque colors within 2 levels on average of the drawing; the largest single gap is 53 levels
- The 320 × 320 size and every decoded value, stored losslessly
Lost or not yet supported
- HEIF files with AV1-coded pictures: an AVIF saved under a .heif name returned 422.
- Color tags and metadata. The PNG holds only IHDR, IDAT and IEND chunks.
- Tones of HEIF files that embed a Display P3 profile, which the decoder stretches (gray 32 came out at 19).
- Size: 46,906 bytes for an 11,269-byte HEIF.
Limits
- One HEIF per request; for files with several pictures, only the primary one.
- Up to 100,000,000 pixels, requests up to 10 MB on the Free plan or 100 MB on paid plans, 120 seconds per conversion.
- A HEIF saved at one desktop encoder's top quality setting returned 422 'malformed data'.
Where teams use it
Cut-out images saved as HEIF
Subject cut-outs, stickers and design exports saved as HEIF carry their transparency in a separate alpha plane. PNG is the usual way to keep that transparency in web pages, editors and slide software.
A lossless intermediate for image pipelines
Decode once to PNG and run resizing, compositing or recognition on a format every image library reads, without adding a second lossy step.
Questions
Which HEIF files can it read?
HEIF files whose pictures are HEVC-coded, with or without an alpha plane, including image sequences (the still picture is returned). HEIF files coded with AV1, which is what AVIF is, return 422 'Avif: decoding is not available for this format'.
Is the transparency exact?
HEIF stores alpha as its own lossy-coded plane. Against the drawing we saved, the decoded alpha differs by at most 5 levels, and the decode has 487 fewer fully clear pixels. The PNG keeps the decoded values exactly.
Why does `ImageQuality` not return an error here?
On HEIF to PNG, options the route doesn't read are accepted and ignored; ImageQuality=50 gave the same bytes. Values of options it does read are still checked, so ImageResolution=5 returns 400.
What is the difference from HEIC to PNG?
Only the route name. The decoder reads the file's content, so a .heif and a .heic of the same picture give the same PNG. Send each file to the route matching its extension.
Convert your first HEIF file in a minute.