PNG to TIFF API
Upload a PNG to POST /v2/convert/png/to/tiff for an uncompressed TIFF with the same pixels. Alpha is kept as a fourth channel and 16-bit PNGs stay 16-bit. The sample adds ImageResolution=300 so layout software sizes the 300 px sticker at one inch.
- Endpoint
- POST /v2/
convert/ png/ to/ tiff - Accepts
- png
- Sample timing
- 1 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/png/to/tiff \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@garden-plot-badge.png \
--form-string ImageResolution=300 \
-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/png/to/tiff",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("garden-plot-badge.png", "rb"))],
data={
"ImageResolution": "300",
},
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 = "garden-plot-badge.png";
form.append("File", new Blob([await readFile(file)]), file);
form.append("ImageResolution", "300");
const url = "https://api.pdfconversionapi.com/v2/convert/png/to/tiff";
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.001,
"Files": [
{
"FileName": "garden-plot-badge.tiff",
"FileExt": "tiff",
"FileSize": 360214,
"FileData": "SUkqAGh+BQAsAQAAAQAAACwB…"
}
]
}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
- garden-plot-badge.png (39 KB)
- Output
- garden-plot-badge.tiff (352 KB)
- Source
- A round garden-plot sticker with a QR code, a transparent background and a soft drop shadow, drawn by us for these pages. (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 |
|---|---|
ImageResolutioninteger | DPI written to the TIFF tags with inches as the unit. The PNG's own 144 dpi is not copied, so without this the TIFF says 1 × 1 and no unit.Values: 10–800 |
ImageWidthinteger | Width in pixels; 150 makes a 150 × 150 file of 90,214 bytes.Values: 1–20000 |
ImageHeightinteger | Height in pixels, or with a width a box to fit into.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches to both given sizes. |
ScaleIfLargerboolean, default false | true keeps a smaller PNG at its own size. |
ScaleImageboolean, default true | false crops at the requested size from the top-left corner. |
ImageInterpolationboolean, default false | Accepted, no effect: resizing is Lanczos3 either way. |
MultiPageboolean, default true | Accepted either way; a PNG becomes a single-page TIFF. |
TransparentColorstring | Clears one more exact color on top of the PNG's own transparency; #FFFFFF on the sticker removes the white panel too.Values: Color name, #RRGGBB or R,G,B |
ColorSpaceenum, default default | gray gives a one-channel 8-bit TIFF for opaque PNGs (90,198 bytes for an opaque copy of the sticker). On a PNG with transparency, gray and monochrome keep the alpha and store RGBA with equal gray values, 360,214 bytes for the sample. rgb drops an alpha channel no pixel uses: the opaque copy came back as 270,210-byte RGB.Values: default, rgb, gray, monochrome; cmyk returns 400 |
FileNamestring | Output name; default garden-plot-badge.tiff. |
StoreFileboolean, default false | true returns a 3-hour link in Files[].Url. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageQuality | Only the documented default, 75, is accepted; ImageQuality=90 returns 400 "ImageQuality is not supported yet for PNG → TIFF". The TIFF is uncompressed. |
What carries over, and what doesn't
Kept
- All 90,000 RGBA values of the sample, alpha included
- 16 bits per sample for 16-bit PNGs, grayscale and RGB
- Partly transparent pixels such as the sticker's shadow
- The DPI you set, stored with inches as the unit
- The upright view of a PNG tagged with an EXIF orientation: a 300 × 200 test PNG tagged Orientation 6 came back as a 200 × 300 TIFF
Lost or not yet supported
- File size: 360,214 bytes, nine times the PNG, since nothing is compressed.
- The PNG's own 144 dpi, text chunk and color profile.
- Every frame but the first of an animated PNG.
- A tag naming the fourth channel as alpha (ExtraSamples is not written); the readers we tried still treated it as transparency.
- Palette storage: a palette PNG with a transparent index becomes a 32-bit RGBA TIFF, one without becomes 24-bit RGB.
Limits
- A single PNG per request.
- Bodies up to 10 MB on the Free plan or 100 MB on paid plans.
- 100,000,000 pixels per image.
- 120 seconds per conversion.
Where teams use it
Artwork for print layouts
Logos and stickers made as PNG go into print layouts as TIFF with a known DPI and their transparent background intact.
16-bit masters
Scans and measurements saved as 16-bit PNG, gray or RGB, keep all 16 bits per channel in the TIFF. The JPEG, GIF, BMP and WebP routes reduce them to 8.
Questions
Is transparency kept?
Yes. The TIFF has four 8-bit samples per pixel and the alpha values match the PNG exactly. The file does not include the ExtraSamples tag that labels the fourth sample; the two readers we tried still showed the transparency.
Does a 16-bit PNG stay 16-bit?
Yes. A 16-bit gray PNG and a 16-bit RGB PNG both came back with 16 bits per sample. Among the other PNG routes, png-to-png and compress-png keep 16 bits as well.
What does ColorSpace=gray do to a transparent PNG?
It keeps the transparency. TIFFs from this route have no gray-plus-alpha layout, so the pixels are stored as RGBA with three equal gray values: the sample came back as 360,214 bytes with every alpha value unchanged. An opaque PNG becomes a one-channel 8-bit TIFF. To get a one-channel gray TIFF from a transparent PNG, flatten it first with png-to-pnm and convert the result with ColorSpace=gray; we got a 90,198-byte gray TIFF that way.
Can the TIFF be compressed?
No. The output is always uncompressed, and ImageQuality other than 75 is refused.
Convert your first PNG file in a minute.