KRA to GIF API
POST a Krita file to /v2/convert/kra/to/gif to get a still GIF89a of the merged layers. The GIF gets one palette of up to 256 colors and a single transparent index, so only fully clear pixels stay see-through.
- Endpoint
- POST /v2/
convert/ kra/ to/ gif - Accepts
- kra
- Sample timing
- 67 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/kra/to/gif \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@rocket-sticker.kra \
-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/kra/to/gif",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("rocket-sticker.kra", "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 = "rocket-sticker.kra";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/kra/to/gif";
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.067,
"Files": [
{
"FileName": "rocket-sticker.gif",
"FileExt": "gif",
"FileSize": 10154,
"FileData": "R0lGODlhQAFAAYAAAAAAAAAA…"
}
]
}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
- rocket-sticker.kra (108 KB)
- Output
- rocket-sticker.gif (9.9 KB)
- Source
- A cartoon rocket sticker on a transparent canvas that we drew and saved as a six-layer KRA file (one layer hidden, one faded by a transparency mask). (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 | GIF width in pixels. A 128 px emoji-size version of the rocket is 3,792 bytes; 160 px is 4,830.Values: 1–20000 |
ImageHeightinteger | GIF height. Used with ImageWidth, the canvas is fitted inside both, so 200 × 100 yields a 100 × 100 GIF.Values: 1–20000 |
ScaleProportionsboolean, default true | Set to false and a 200 × 100 request distorts the art to exactly that size (4,307 bytes). |
ScaleIfLargerboolean, default false | true keeps the GIF at 320 px when you ask for more. |
ScaleImageboolean, default true | false crops the top-left ImageWidth × ImageHeight region and scales nothing. |
ColorSpaceenum, default default | monochrome thresholds at level 128 before the palette step and shrank the file to 2,074 bytes; gray gave 10,472.Values: default, rgb, gray, monochrome (also srgb, truecolors, grayscale); cmyk returns 400 |
TransparentColorstring | Adds one more color to the transparent index. With #FFFFFF, 104 pure white pixels along the soft edge of the rocket body dropped out (9,978 bytes); the highlights are tinted by the body and stay.Values: #RRGGBB, R,G,B or a color name |
FileNamestring | Sets the GIF's name; the default here is rocket-sticker.gif. |
StoreFileboolean, default false | Asks for a 3-hour link in Files[].Url in place of the GIF data. |
What carries over, and what doesn't
Kept
- The merged drawing at 320 × 320, quantized to 206 distinct colors held in 220 palette entries (some entries repeat, one is the transparent index)
- Fully transparent canvas: all 83,159 empty pixels map to the GIF's transparent index
- Opaque detail closely: on fully opaque pixels the average error after quantizing was 0.4 levels
Lost or not yet supported
- Partial transparency. The GIF has one transparent index, so all 4,962 semi-transparent pixels became solid: the soft gray shadow turned into a dark navy outline and the flame's faded tail into hard orange.
- Colors beyond one 256-entry palette; smooth gradients may band.
- Animation. Krita's animation frames, if any, are not exported; the GIF has a single frame.
- Vector, filter and fill layers, which our converter does not draw yet.
- Resolution data. GIF has no DPI field, so
ImageResolutionchanges nothing.
Limits
- A single KRA per request, canvas up to 100,000,000 pixels and 300,000 px a side.
- A GIF side can't exceed 65,535 px. A 65,536 × 10 canvas returned 413
GIF images can be at most 65,535 pixels on a side, and this one is 65,536×10; 65,535 × 10 converted. - Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- 120 seconds per conversion; longer jobs get 504.
- Output is always one frame with one global palette.
Where teams use it
Chat stickers and forum avatars
Where an upload form or a sticker pack takes GIF only, a small flat-color Krita drawing converts well: 220 palette entries covered the sample at 10,154 bytes.
Legacy email templates
Templates that are built around GIF badges can take Krita artwork directly. Pick the badge size with ImageWidth in the same call, for example 128 px for 3,792 bytes.
Questions
Why does my soft shadow look black in the GIF?
GIF transparency is on or off per pixel. Pixels that are only partly transparent are written with their own color at full strength, so a 35% shadow painted in dark navy shows as solid dark navy. Flatten the art onto a background first, for example with our KRA to PNG or JPG route and AlphaColor, if you need the soft look.
Can I export a Krita animation as an animated GIF?
No. The route merges the layers of the document as saved and writes one frame. We have not tested animated .kra files.
How many colors does the GIF use?
Up to 256 in one palette. The rocket's GIF uses 220 entries, but they hold only 206 distinct colors, because some entries repeat and one is the transparent index. On the opaque parts the difference from the full-color merge averaged 0.4 levels per channel.
Convert your first KRA file in a minute.