ICO to TGA API
POST an icon to /v2/convert/ico/to/tga and get an uncompressed Targa file. It stores 32 bits per pixel with an 8-bit alpha channel, rows from the top down, so the icon's clear corners and soft shadow keep their values.
- Endpoint
- POST /v2/
convert/ ico/ to/ tga - 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/tga \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@paper-plane-app-icon.ico \
-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/tga",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("paper-plane-app-icon.ico", "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 = "paper-plane-app-icon.ico";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/ico/to/tga";
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.tga",
"FileExt": "tga",
"FileSize": 262162,
"FileData": "AAACAAAAAAAAAAAAAAEAASAo…"
}
]
}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.tga (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 |
|---|---|
ImageWidthinteger | Target width; ImageWidth=128 gave a 65,554-byte 128 × 128 TGA: an 18-byte header and 4 bytes per pixel.Values: 1–20000 |
ImageHeightinteger | Target height, or the height of a fitting box when you also send a width.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches the icon into a box of another shape, for example a 256 × 128 texture slot. |
ScaleIfLargerboolean, default false | With true, an icon already smaller than the requested size is left alone. |
ScaleImageboolean, default true | false takes a top-left crop of the requested size. |
ColorSpaceenum, default default | gray gives gray values and monochrome pure black and white, still as 32-bit pixels with alpha. Both files are 262,162 bytes, the same as the color one.Values: default, rgb, gray, monochrome |
TransparentColorstring | Sets alpha to 0 for every pixel of exactly this color, in addition to the icon's own transparency.Values: Color name, #RRGGBB or R,G,B |
ImageResolutioninteger | Accepted for compatibility and not written to the file.Values: 10–800 |
ImageInterpolationboolean, default false | Accepted; resampling is Lanczos either way. |
FileNamestring | File name of the .tga; defaults to the icon's. |
StoreFileboolean, default false | Return a download URL kept for 3 hours. |
What carries over, and what doesn't
Kept
- Every pixel and alpha value: decoding the sample TGA gave back the icon's 256 px entry exactly
- 8 bits of alpha per pixel, as the header's image descriptor declares, stored straight rather than premultiplied
- Top-down row order, flagged in the header so readers don't flip the image
- A plain true-color layout (image type 2, no color map) that all three image readers we tried opened
Lost or not yet supported
- Compactness. With no run-length encoding the file is 262,162 bytes, an 18-byte header plus 4 bytes per pixel, 7.6 times the whole four-size .ico.
- A TGA 2.0 footer: the file ends right after the pixel data.
- The 16, 32 and 48 px entries in the .ico.
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; at most 100,000,000 pixels after resizing.- 120 seconds per conversion, then 504.
Where teams use it
UI textures for games and mods
Game engines and modding tools that import TGA with alpha can take an application or item icon this way. Set ImageWidth to the slot size the engine expects, such as 64 or 128.
Texture tools without ICO support
If a texture utility in your toolchain reads Targa but not .ico, converting gives it the icon with its full alpha channel, which a JPEG would lose.
Questions
Is the TGA compressed?
No. Each pixel is stored as 4 raw bytes in blue, green, red and alpha order after an 18-byte header, so the sample is 262,162 bytes. There is no option to turn on run-length encoding; convert to PNG if you want a smaller lossless file with alpha.
Is the alpha straight or premultiplied?
Straight. The color values in the file are the icon's own, not multiplied by alpha; the sample's decoded pixels equal the icon's RGBA values exactly.
Which way up are the rows stored?
Top row first. The header's image descriptor sets the top-left origin bit, so readers that honor it show the icon upright.
Convert your first ICO file in a minute.