HEIF to PNM API
POST a .heif to /v2/convert/heif/to/pnm and get raw 8-bit RGB pixels behind a P6 header. The file has three channels, so a transparent HEIF is blended onto a background: the sample sends AlphaColor=#E8F4EA, a pale green, and the shadow fades into it.
- Endpoint
- POST /v2/
convert/ heif/ to/ pnm - Accepts
- heif
- Sample timing
- 23 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/pnm \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@succulent-sticker.heif \
--form-string 'AlphaColor=#E8F4EA' \
-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/pnm",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("succulent-sticker.heif", "rb"))],
data={
"AlphaColor": "#E8F4EA",
},
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);
form.append("AlphaColor", "#E8F4EA");
const url = "https://api.pdfconversionapi.com/v2/convert/heif/to/pnm";
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.023,
"Files": [
{
"FileName": "succulent-sticker.pnm",
"FileExt": "pnm",
"FileSize": 307215,
"FileData": "UDYKMzIwIDMyMCAyNTUK6PTq…"
}
]
}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.pnm (300 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 |
|---|---|
AlphaColorstring, default white | The color behind clear and partly transparent pixels. With the sample's #E8F4EA, clear corners are (232, 244, 234) and the shadow's center, 112/255 opaque, is (145, 146, 135).Values: #RRGGBB, R,G,B or white, black, red, green, blue, gray |
BackgroundColorstring, default white | Same effect, read when AlphaColor is absent; black puts the sticker on black. |
ImageWidthinteger | Scales before blending; 200 gives a 120,015-byte file.Values: 1–20000 |
ImageHeightinteger | Target height, or a box with ImageWidth.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches to both sizes. |
ScaleIfLargerboolean, default false | true avoids enlarging. |
ScaleImageboolean, default true | false crops the top-left area. |
ColorSpaceenum, default default | gray and monochrome give a one-channel P5 graymap of 102,415 bytes, taken after the blend: with the sample's AlphaColor the clear corners come out as gray 241, or white in monochrome, which holds only 0 and 255.Values: default, rgb, gray, monochrome |
FileNamestring | Base name of the .pnm. |
StoreFileboolean, default false | true returns a 3-hour link. |
What carries over, and what doesn't
Kept
- Soft edges, blended by opacity: every pixel equals the decoded sticker composited onto
#E8F4EA - The 320 × 320 size, with rows stored top first
- 8 bits per channel, with 255 as the header's maximum value
- Acceptance by both readers we tried, with identical pixels
Lost or not yet supported
- Transparency itself: a
P6file has only red, green and blue, no alpha channel. - Size: 307,215 bytes, 27 times the HEIF.
- Tones of HEIF files with an embedded Display P3 profile.
Limits
- One HEIF per request, 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.
- AV1-coded HEIF (AVIF) files are refused with 422.
Where teams use it
Compositing onto a known background
When the next tool can't handle alpha, blending here onto the exact page or video background color gives soft edges that match, instead of a white halo.
Input for vision and test code
Code that reads raw RGB buffers gets a flat file: a short header, then 320 rows of 320 pixels, with transparency already resolved.
Questions
Which background colors can I use?
#RRGGBB, R,G,B (for example 232,244,234), or the names white, black, red, green, blue and gray. Anything else returns 400, such as 'teal' is not a color.
Can the file keep the transparency?
No. The file has no alpha channel: three channels, or one with ColorSpace=gray, so alpha is always resolved against AlphaColor. For transparency, use /v2/convert/heif/to/png or heif/to/tiff.
What does the header look like?
The magic number P6 on its own line, then 320 320 255 (width, height and maximum value) on the next. Binary RGB rows follow from the top. With ColorSpace=gray the magic number is P5 and each pixel is one byte.
Convert your first HEIF file in a minute.