PNG to TGA API
Upload a PNG to POST /v2/convert/png/to/tga and an uncompressed Targa comes back, 8 bits per channel plus 8 of alpha. Nothing is compressed, so the 40,051-byte sticker became 360,018 bytes: an 18-byte header and 4 bytes for each of its 90,000 pixels.
- Endpoint
- POST /v2/
convert/ png/ to/ tga - 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/tga \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@garden-plot-badge.png \
-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/tga",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("garden-plot-badge.png", "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 = "garden-plot-badge.png";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/png/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": "garden-plot-badge.tga",
"FileExt": "tga",
"FileSize": 360018,
"FileData": "AAACAAAAAAAAAAAALAEsASAo…"
}
]
}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.tga (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 |
|---|---|
ImageWidthinteger | Sprite width. ImageWidth=64 gives a 64 × 64 Targa of 16,402 bytes from the square sticker.Values: 1–20000 |
ImageHeightinteger | Sprite height. With a width as well it sets a bounding box; the round sticker fills the shorter side.Values: 1–20000 |
ScaleProportionsboolean, default true | With both sides given, false squeezes the art to fit them exactly (200 × 100 makes the circle an ellipse). |
ScaleIfLargerboolean, default false | true refuses to upscale: a 600 px target leaves the 300 px sticker as it is. |
ScaleImageboolean, default true | false crops the top-left corner at the requested size, which for this sticker is mostly transparent pixels and the start of the green rim. |
TransparentColorstring | Adds transparency for one exact color on top of the PNG's own. #FFFFFF cleared another 13,373 pixels of the sticker, the QR code's white modules among them.Values: Color name, #RRGGBB or R,G,B |
ColorSpaceenum, default default | gray keeps alpha and writes gray color values in the same 32-bit pixels, so the file stays 360,018 bytes.Values: default, rgb, gray, monochrome; cmyk refused |
FileNamestring | Rename the result; by default it is garden-plot-badge.tga. |
StoreFileboolean, default false | Return a link that lasts 3 hours (Files[].Url) instead of embedding the file. |
What carries over, and what doesn't
Kept
- Every RGBA value: the decoded Targa matched the 90,000 pixels of the PNG exactly
- Semi-transparent pixels such as the sticker's drop shadow, as straight (unpremultiplied) alpha
- 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 Targa
- Row order, marked top-left in the header
Lost or not yet supported
- 16-bit precision; a 16-bit gray PNG came back as 8-bit RGBA.
- Text chunks, the 144 dpi pHYs value and any color profile.
- Every frame after the first of an animated PNG.
- Compression: the Targa is 360,018 bytes, about nine times the PNG, because no run-length or other compression is applied.
Limits
- One PNG in, one TGA out.
- Request size: 10 MB on the Free plan or 100 MB on paid plans.
- Images over 100,000,000 pixels are rejected with 413.
- Sizes from 1 to 20,000 px per side.
- TGA output stops at 65,535 px per side, and a 70,000 × 2 PNG returned 413 "TGA images can be at most 65,535 pixels on a side, and this one is 70,000×2". Sent with
ImageWidth=100, the same strip came back as a 100 × 1 Targa. - Up to 120 seconds of work per request.
Where teams use it
Sprites and UI art for game engines
Artists hand over PNGs; some engines and older modding tools load Targa. The alpha channel, soft edges included, goes across unchanged, so a sticker or HUD icon keeps its shadow.
Overlays for video titling software
Lower thirds and logos with transparency are often imported as TGA. Convert the PNG and scale it to the frame size you need in the same request.
Questions
Is the alpha premultiplied?
No. The color values are copied from the PNG as they are, with alpha stored next to them. A shadow pixel with color (5, 8, 5) and alpha 24 in the PNG has the same four numbers in the Targa.
Is the Targa compressed?
No. Every file from this route is image type 2, uncompressed true color: the 18-byte header, then 4 bytes per pixel and no footer, 360,018 bytes for the 300 × 300 sample. There is no option for run-length encoding.
Will other programs open the file?
Uncompressed type 2 is the plainest Targa layout, with no run-length packets for a reader to misread. All four readers we tried opened the sample with its alpha, our own API included.
What does TransparentColor add for a PNG that is already transparent?
It clears one extra color. On the sample, #FFFFFF turned the white panel and the QR code's light modules transparent (13,373 pixels), which you only want if the code will sit on a light background.
Convert your first PNG file in a minute.