Skip to content
pdfconversionapi

PNM to GIF API

POST a netpbm image to /v2/convert/pnm/to/gif and get a single-frame GIF89a. The 1,934-color sample render was reduced to a 256-entry palette (183 entries in use) and came back as 9,879 bytes.

Endpoint
POST /v2/convert/pnm/to/gif
Accepts
pnm
Sample timing
46 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/pnm/to/gif \
  -H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
  -F File=@three-spheres-render.ppm \
  -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
fi
200 OK46 ms median1 file, 9.6 KB
{
  "ConversionCost": 1,
  "ConversionTime": 0.046,
  "Files": [
    {
      "FileName": "three-spheres-render.gif",
      "FileExt": "gif",
      "FileSize": 9879,
      "FileData": "R0lGODlhQAHwAIAAAAAAAAAA…"
    }
  ]
}

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.

First page of three-spheres-render.gif, rendered by the API
Input
three-spheres-render.ppm (225 KB)
Output
three-spheres-render.gif (9.6 KB)
Source
A 320 x 240 frame from a small ray tracer we wrote for this page (three spheres on a checkered floor), saved as a binary PPM (P6) with 8 bits per channel. (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.

ParameterWhat it does
ImageWidthintegerWidth of the GIF. At ImageWidth=128 the render is 128 × 96 and 6,077 bytes.Values: 1–20000
ImageHeightintegerHeight of the GIF; with a width as well, the frame is fitted inside both.Values: 1–20000
ScaleProportionsboolean, default truefalse forces the exact width and height, changing the frame's shape.
ScaleIfLargerboolean, default falseWith true, only downscaling happens.
ScaleImageboolean, default truefalse crops the requested size from the top-left corner.
ColorSpaceenum, default defaultmonochrome makes a two-color GIF of the render at 795 bytes; gray gives 10,186 bytes.Values: default, rgb, gray, monochrome
TransparentColorstringMarks one exact color as the GIF's transparent color. #92969D makes the 19,013 pixels of exactly that gray see-through, the unshaded parts of the dark floor tiles; shadowed, distant and edge pixels of those tiles have other grays and stay opaque.Values: Color name, #RRGGBB or R,G,B
ImageResolutionintegerAccepted and range-checked; GIF has nowhere to store it.Values: 10–800
ImageInterpolationboolean, default falseAccepted; resampling always uses Lanczos.
FileNamestringName of the .gif; the upload's name otherwise.
StoreFileboolean, default falseStore the GIF for 3 hours and reply with a link.

What carries over, and what doesn't

Kept

  • Shapes and shading closely: the largest error against the PPM was 38 levels, the average 0.11
  • Exact colors when the image has 256 or fewer: a PBM keeps its 2 colors and a gray test PGM its 158 gray levels
  • Full transparency from PAM files, where alpha is 0

Lost or not yet supported

  • Colors beyond 256. The render's 1,934 colors were mapped to 183 palette entries.
  • Partial transparency from PAM: rows with alpha 128 in a test file became fully opaque.
  • 16-bit depth and the original maxval.

Limits

  • One file per request; the GIF has one frame.
  • Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
  • Images over 100,000,000 pixels return 413.
  • Each side can be at most 65,535 px: a 65,536 × 2 PPM returned 413 "GIF images can be at most 65,535 pixels on a side, and this one is 65,536×2", while the 65,535 × 2 one converted.
  • 120 seconds per conversion, then 504.

Where teams use it

Line art and masks saved as PBM

Black-and-white PBM bitmaps convert to very small GIFs: a 320 × 240 test bitmap came back as 795 bytes with its two colors exact.

Quick previews where only GIF is accepted

Where a forum, wiki or mail template accepts GIF but not PNG or WebP, a render converts to a 10 KB preview, at the cost of some color precision.

Questions

How are the colors reduced?

If the image has 256 colors or fewer, the palette is made of exactly those colors. Otherwise a quantizer chooses 256 entries, which is what happened to the render.

Can I make an animated GIF from several PPM frames?

Not on this route. It takes one file and writes one frame.

Does a PAM with alpha keep its transparency?

Only where alpha is 0. GIF has a single transparent color, so every partly transparent pixel (alpha 1 to 254) is stored as opaque.

Convert your first PNM file in a minute.