Skip to content
pdfconversionapi

PNM to SVG API

POST a netpbm image to /v2/convert/pnm/to/svg and get an SVG of filled paths. The sample render, traced with ColorPrecision=8 and GradientStep=6, came back as 243 paths in 190 colors and 112,616 bytes.

Endpoint
POST /v2/convert/pnm/to/svg
Accepts
pnm
Sample timing
29 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/svg \
  -H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
  -F File=@three-spheres-render.ppm \
  --form-string ColorPrecision=8 \
  --form-string GradientStep=6 \
  -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 OK29 ms median1 file, 110 KB
{
  "ConversionCost": 1,
  "ConversionTime": 0.029,
  "Files": [
    {
      "FileName": "three-spheres-render.svg",
      "FileExt": "svg",
      "FileSize": 112616,
      "FileData": "PD94bWwgdmVyc2lvbj0iMS4w…"
    }
  ]
}

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.svg, rendered by the API
Input
three-spheres-render.ppm (225 KB)
Output
three-spheres-render.svg (110 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
Presetenum, default noneBase settings for the trace. On the render: bw 5 paths (2,757 bytes), poster 188 paths, photo 55 paths (75,318 bytes). Other options you send override it.Values: none, bw, poster, photo
ColorModeenum, default colorbw traces in black and white, the natural choice for PBM bitmaps.Values: color, bw
Layeringenum, default stackedcutout makes shapes that don't overlap; for the render that meant 98 paths and 53,548 bytes instead of 175 and 91,789.Values: stacked, cutout
FilterSpeckleinteger, default 4Drops patches smaller than this many pixels across. 0 keeps the aliasing in the distant checkerboard: 3,034 paths, 310,154 bytes. 20 leaves 34 paths.Values: 0–128
ColorPrecisioninteger, default 6How many bits per channel decide whether two colors are the same. The sample uses 8; 1 collapses the render into a single path of 286 bytes.Values: 1–8
GradientStepinteger, default 16Color step between gradient layers. The sample sends 6 to keep more of the shading on the spheres and in the sky; 0 gave 198 paths.Values: 0–128
CurveModeenum, default splineCurves (91,789 bytes), straight segments (26,932 bytes) or pixel-edge steps (73,730 bytes) for the render with other options left out.Values: spline, polygon, pixel
CornerThresholdinteger, default 60Bends sharper than this angle stay corners; 55 gave 89,950 bytes on the render.Values: 0–180
SegmentLengthnumber, default 4Segment length used when fitting curves; values outside the range return 400.Values: 3.5–10
SpliceThresholdinteger, default 45Angle at which a curve is split; 35 produced 93,985 bytes.Values: 0–180
ImageWidthintegerRescales the image before tracing, which sets the detail level: 128 px wide gives 80 paths. The limit is 12,000,000 pixels; 4000 × 3000 sits exactly at it and returned 3,357 paths in 1.4 MB.Values: 1–20000
ImageHeightintegerHeight before tracing, or with a width the box the image is fitted into.Values: 1–20000
ScaleImageboolean, default truefalse with a size traces only that top-left part of the image.
FileNamestringBase name of the .svg; the upload's name otherwise.
StoreFileboolean, default falseLink to the SVG, kept 3 hours, instead of base64.

What carries over, and what doesn't

Kept

  • Large shapes and their edges: floor tiles, spheres and horizon are separate paths
  • Flat colors closely: on the sample, the traced image differs from the PPM by 4.4 levels on average
  • The canvas size, 320 × 240, as the SVG's width and height

Lost or not yet supported

  • Smooth shading, which becomes bands of flat color.
  • The mirror sphere's outline: with the default settings its upper half, which reflects the sky, merges into the sky, and the spheres reflected in it become soft blobs.
  • 16-bit depth, reduced to 8 bits before tracing.

Limits

  • One file per request.
  • Tracing is limited to 12,000,000 pixels after resizing; above that the API returns 413.
  • Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
  • 120 seconds per conversion, then 504.

Where teams use it

Tracing bitmaps of line art

Black-and-white bitmaps such as a scanned signature, stamp or logo can be traced straight from PBM. A 320 × 240 test bitmap traced to 5 paths in 2,746 bytes.

Stylized vector versions of renders

Color frames become flat-color poster art. Lower ColorPrecision or raise FilterSpeckle for fewer, bolder shapes; do the opposite for more shading.

Questions

Which settings work for a black-and-white PBM?

The defaults already handle it, since a bitmap has two colors. Our test bitmap, the render thresholded so that the spheres' dark sides and their shadows are black on white, traced to a white base with 4 black shapes on it: 5 paths in 2,746 bytes. ColorMode=bw draws only the black areas, here 5 black paths (2,769 bytes), and leaves the rest of the canvas empty.

Why do gradients turn into bands?

The tracer groups pixels into regions of similar color and fills each region with one color. GradientStep sets how far apart those layers are, so lower values give more, narrower bands.

How large an image can be traced?

Up to 12,000,000 pixels after any resize; larger requests return 413. A 4,000 × 3,001 bitmap sent without size options got "vectorizing is limited to 12,000,000 pixels, and this image is 4,000×3,001; set ImageWidth or ImageHeight to scale it down". When ImageWidth or ImageHeight made the image too large, the message ends in "; lower ImageWidth or ImageHeight" instead.

Convert your first PNM file in a minute.