TGA to ICO API
POST a TGA to /v2/convert/tga/to/ico and get an .ico with a single 32-bit entry. Textures larger than 256 px are scaled to fit; smaller ones keep their size and every pixel.
- Endpoint
- POST /v2/
convert/ tga/ to/ ico - Accepts
- tga
- 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/tga/to/ico \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@shield-icon.tga \
-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/tga/to/ico",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("shield-icon.tga", "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 = "shield-icon.tga";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/tga/to/ico";
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": "shield-icon.ico",
"FileExt": "ico",
"FileSize": 4052,
"FileData": "AAABAAEAAAAAAAAAIAC+DwAA…"
}
]
}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
- shield-icon.tga (16 KB)
- Output
- shield-icon.ico (4.0 KB)
- Source
- A 256 x 256 pixel-art shield icon with a transparent background and a half-transparent shadow, drawn by us and saved as a 32-bit run-length-encoded TGA. (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 | Pick the icon size, for example 128 or 48. Anything over 256 is first resized and then fitted into 256 × 256 again, so ImageWidth=1000 still gave a 256 px icon.Values: 1–20000 (the icon is capped at 256) |
ImageHeightinteger | Icon height in pixels; with ImageWidth, both set the box.Values: 1–20000 (capped at 256) |
ScaleProportionsboolean, default true | false forces exactly the width and height given, for a square icon from a non-square texture. |
ScaleIfLargerboolean, default false | true keeps a small texture at its own size instead of enlarging it. |
ScaleImageboolean, default true | false takes a top-left crop of the requested size instead of scaling. |
ColorSpaceenum, default default | gray or monochrome change the pixel values; the entry stays 32-bit RGBA either way.Values: default, rgb, gray, monochrome; cmyk returns 400 |
FileNamestring | File name for the icon, without .ico. |
StoreFileboolean, default false | true stores the icon for 3 hours and returns a URL. |
What carries over, and what doesn't
Kept
- The full 256 × 256 sample, pixel for pixel: it fits the ICO maximum exactly, so nothing is resized
- 8-bit alpha, half-transparent shadow included, because the entry is stored as a PNG inside the ICO
- The aspect ratio of larger textures: a 512 × 128 sprite strip became a 256 × 64 icon
Lost or not yet supported
- Extra sizes. The ICO has one entry, not the 16, 32 and 48 px set many icon files carry; request each size separately if you need several.
- Detail in textures over 256 px, which are scaled down with a Lanczos3 filter.
- The TGA ID string and footer, and any key-color handling:
TransparentColoris ignored for ICO output.
Limits
- One TGA per request; one image in the icon, at most 256 × 256.
- 100,000,000 pixels per source image.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- 120 seconds per conversion.
Where teams use it
Desktop icons for a game launcher or tool
If your game art is already in TGA, an icon made from the same texture keeps its alpha, so the launcher or shortcut shows a clean edge on any desktop background.
Favicons from existing sprite art
Send ImageWidth=48 or 32 to get a small favicon from a larger sprite in one call. Keep in mind that the smoothing filter softens pixel art at small sizes.
Questions
What is inside the ICO file?
A 6-byte header, one 16-byte directory entry and a PNG of the image. For the shield the embedded PNG is byte for byte the file that TGA to PNG returns, so the icon is 22 bytes larger: 4,052 bytes.
Can one ICO hold several sizes?
Not from this API today. Each request writes one entry. Request the sizes you need separately with ImageWidth, then combine them with an icon tool if you need a multi-size file.
My texture is 1024 px. What size is the icon?
It is fitted into 256 × 256 with its proportions kept, so 1024 × 1024 becomes 256 × 256 and a wide strip becomes 256 px wide. You don't need to resize it yourself first.
Convert your first TGA file in a minute.