Skip to content
pdfconversionapi

BMP to SVG API

POST a bitmap to /v2/convert/bmp/to/svg and get an SVG drawn with filled paths traced from its pixels. Settings such as CurveMode, FilterSpeckle and Preset control how closely the paths follow the bitmap.

Endpoint
POST /v2/convert/bmp/to/svg
Accepts
bmp
Sample timing
14 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/bmp/to/svg \
  -H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
  -F File=@shelf-label.bmp \
  --form-string CurveMode=polygon \
  -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 OK14 ms median1 file, 19 KB
{
  "ConversionCost": 1,
  "ConversionTime": 0.014,
  "Files": [
    {
      "FileName": "shelf-label.svg",
      "FileExt": "svg",
      "FileSize": 19441,
      "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 shelf-label.svg, rendered by the API
Input
shelf-label.bmp (293 KB)
Output
shelf-label.svg (19 KB)
Source
A 24-bit warehouse bin label with a QR code and a colored header, drawn by us for this page. (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
CurveModeenum, default splineHow outlines are drawn. The sample uses polygon: straight segments, 19,441 bytes, against 44,039 with the default curves and 25,498 with pixel, which follows the pixel grid.Values: spline, polygon, pixel
FilterSpeckleinteger, default 4Patches of this value squared pixels or fewer are merged into the color around them. The label's QR modules are 5 × 5 pixels, so 5 already broke the code (112 paths); at 20 only 16 paths and 11,321 bytes were left.Values: 0–128
Presetenum, default noneStarting settings that your other options override. bw (98 paths) and photo (36 paths) both left the label's QR code unreadable; poster was close to the default.Values: none, bw, poster, photo
ColorModeenum, default colorbw traces in black and white only, 32,647 bytes for the label.Values: color, bw
ColorPrecisioninteger, default 6Bits per channel kept when grouping colors; 3 merged a few anti-aliased shades (170 paths instead of 173).Values: 1–8
GradientStepinteger, default 16Color step between layers. We use 16 when it is not sent; ConvertAPI documents 10. GradientStep=10 gave 44,849 bytes, 40 gave 40,194.Values: 0–128
Layeringenum, default stackedcutout produces shapes that do not overlap: 60 paths and 32,568 bytes.Values: stacked, cutout
CornerThresholdinteger, default 60Turns sharper than this many degrees stay corners. Our default is 60; ConvertAPI documents 55, which gave 43,789 bytes.Values: 0–180
SegmentLengthnumber, default 4Segment length for curve fitting; 8 gave 42,547 bytes. Below 3.5 is a 400.Values: 3.5–10
SpliceThresholdinteger, default 45Angle at which splines are split. Omitted, it is 45; ConvertAPI documents 35 (45,304 bytes).Values: 0–180
ImageWidthintegerResamples the bitmap before tracing. With the default curves, 200 px gave a larger SVG, 66,788 bytes against 44,039, though with fewer paths (137 against 173): smoothing adds shades (103 fill colors against 76) and each path is about twice as long. With the sample's CurveMode=polygon it was 23,324 bytes.Values: 1–20000
ImageHeightintegerResamples to this height. ScaleImage=false with both sizes traces only a top-left crop (150 × 100 gave 36 paths).Values: 1–20000
FileNamestringSVG name without extension.
StoreFileboolean, default falseReturn a 3-hour link to the SVG.

What carries over, and what doesn't

Kept

  • The QR code at default settings and in the sample: a render of the SVG decoded to BIN A-14-03 | SKU HX-2207 | QTY 48
  • Large flat areas, within a few levels: the teal header (31, 111, 139) came back as (32, 112, 139) and the amber box (255, 193, 37) as (251, 190, 36)
  • Layout and size: the SVG is 400 × 250 and shapes stay where they were

Lost or not yet supported

  • Small and anti-aliased text. In the sample, "Hex bolts" lost letters and the 14 px line "Zone A / Aisle 14" became fragments.
  • Exact colors: anti-aliased edges are grouped, and the SVG uses 76 fill colors, not the BMP's 760.
  • Pixel accuracy: rendered back at the same size, only 14% of pixels matched the BMP exactly, although the average difference was under 5 levels.
  • Compactness for 1-bit art: a 1-bit copy of the label traced into 660 paths and 250,304 bytes.

Limits

  • One BMP per request.
  • Tracing stops at 12,000,000 pixels with a 413 that tells you to set ImageWidth.
  • Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
  • 413 for bitmaps over 100,000,000 pixels.
  • 504 after 120 seconds.

Where teams use it

Logos and signage kept only as bitmaps

Artwork that exists as a BMP from an old design tool can be traced into SVG for printing at larger sizes or for editing in a vector program.

Labels and diagrams for laser or plotter output

Cutters and plotters follow paths, not pixels. A traced label or floor diagram gives them outlines to follow.

Questions

Which settings keep a QR code scannable?

For the label, the default settings and CurveMode=polygon kept it readable. Preset=bw, Preset=photo and FilterSpeckle=20 did not. Test with your own codes, since module size matters.

Is the SVG made of real paths?

Yes, only filled path elements, 173 for the sample, and no embedded bitmap.

How do your defaults compare with ConvertAPI's?

Three differ when the option is left out: GradientStep 16 against 10, CornerThreshold 60 against 55, SpliceThreshold 45 against 35. Send ConvertAPI's numbers explicitly to match its settings.

Why is my SVG bigger than expected?

Each color cluster becomes its own paths. Photos, dithering and anti-aliased text produce many; raise FilterSpeckle, lower ColorPrecision or use CurveMode=polygon to cut the size.

Convert your first BMP file in a minute.