ICO to TIFF API
POST an icon to /v2/convert/ico/to/tiff and get a single-page TIFF with four 8-bit samples per pixel. The pixels and transparency of the icon's best entry come through unchanged, and ImageResolution sets the DPI tags, as in the sample.
- Endpoint
- POST /v2/
convert/ ico/ to/ tiff - Accepts
- ico
- 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/ico/to/tiff \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@paper-plane-app-icon.ico \
--form-string ImageResolution=96 \
-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/ico/to/tiff",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("paper-plane-app-icon.ico", "rb"))],
data={
"ImageResolution": "96",
},
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 = "paper-plane-app-icon.ico";
form.append("File", new Blob([await readFile(file)]), file);
form.append("ImageResolution", "96");
const url = "https://api.pdfconversionapi.com/v2/convert/ico/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": "paper-plane-app-icon.tiff",
"FileExt": "tiff",
"FileSize": 262358,
"FileData": "SUkqACgABABgAAAAAQAAAGAA…"
}
]
}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
- paper-plane-app-icon.ico (34 KB)
- Output
- paper-plane-app-icon.tiff (256 KB)
- Source
- A four-size app icon we drew and assembled ourselves: 16, 32 and 48 px entries stored as 32-bit bitmaps with a 1-bit mask, and a 256 px entry stored as PNG. The paper plane design is fictional. (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 resolution tags. The sample sends 96, so the TIFF says 96 pixels per inch. Without it the tags hold 1/1 with no unit.Values: 10–800 |
ImageWidthinteger | Width in pixels; ImageWidth=128 made a 65,750-byte TIFF.Values: 1–20000 |
ImageHeightinteger | Height in pixels, or with a width the box to fit into.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches to the exact box size. |
ScaleIfLargerboolean, default false | true prevents upscaling past the icon's own 256 px. |
ScaleImageboolean, default true | false crops the top-left area instead of scaling. |
ColorSpaceenum, default default | rgb changes nothing for an icon with transparency, like the sample; on a fully opaque icon it drops the unused alpha (a 196,818-byte RGB TIFF for a 256 px test icon). gray and monochrome keep the sample's alpha: the TIFF stays RGBA at 262,358 bytes, with equal red, green and blue. A fully opaque icon gives a one-channel 8-bit TIFF of 65,734 bytes.Values: default, rgb, gray, monochrome |
TransparentColorstring | Pixels of exactly this color get alpha 0. With #FFFFFF only the plane's white wing goes (3,398 pixels); its light-blue side and the blue-green tile keep their alpha.Values: Color name, #RRGGBB or R,G,B |
ImageInterpolationboolean, default false | Accepted; scaling always uses Lanczos. |
FileNamestring | Base name of the TIFF; the icon's name by default. |
StoreFileboolean, default false | Link instead of base64, kept for 3 hours. |
What carries over, and what doesn't
Kept
- Pixels and alpha of the 256 px entry, unchanged in the sample
- 8 bits per sample, four samples per pixel, one page
- The DPI you send: the sample's resolution tags read 96 × 96 pixels per inch
Lost or not yet supported
- Compression. The sample TIFF is 262,358 bytes, almost all of it raw pixels.
- An explicit alpha label: the file has no ExtraSamples tag, which the TIFF 6.0 specification uses to mark the fourth sample as alpha. The readers we tried still treated it as alpha.
- A one-channel gray TIFF for icons with transparency:
ColorSpace=graykeeps four samples per pixel, with the gray value in red, green and blue. - The 16, 32 and 48 px entries of the icon.
Limits
- One icon per request.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
ImageWidthandImageHeightup to 20,000 px, and 100,000,000 pixels in all; uncompressed, that is up to 400 MB of samples.- 120 seconds per conversion, then 504.
Where teams use it
Print and page layout
Layout and prepress workflows that ask for TIFF can place an icon at a known size: with ImageResolution=96, the 256 px sample is 2.67 inches wide; at 300 it is 0.85 inches.
Archives of master files
Collections that keep originals as uncompressed TIFF can store icons in the same form, alpha channel included, without a decoder for compressed data.
Questions
Is the TIFF compressed?
No. There is no compression option on this route, and the sample's 256 × 256 pixels take 262,144 of the file's 262,358 bytes.
What does ColorSpace=gray do to an icon with transparency?
It turns every pixel gray and keeps the alpha channel. Our TIFF writer has no gray-plus-alpha layout, so the result is RGBA with equal red, green and blue: 262,358 bytes for the sample, the same size as the color file, with its 10,690 clear pixels still clear. monochrome does the same with only black and white. A fully opaque icon converts to a one-channel gray TIFF instead.
What DPI does the TIFF have?
Whatever you send in ImageResolution, from 10 to 800. Without it the resolution tags are 1/1 with no unit, which says nothing about print size.
Does the TIFF keep transparency?
The alpha values are stored as the fourth sample of each pixel. The file doesn't label that sample with an ExtraSamples tag, but the readers we opened it with treated it as alpha.
Convert your first ICO file in a minute.