WebP to SVG API
POST a WebP to /v2/convert/webp/to/svg and get an SVG made of traced, filled paths. Fully transparent parts of the WebP are left out of the drawing; FilterSpeckle and CurveMode decide how much fine detail is kept.
- Endpoint
- POST /v2/
convert/ webp/ to/ svg - Accepts
- webp
- Sample timing
- 27 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/webp/to/svg \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@guest-badge.webp \
--form-string FilterSpeckle=2 \
--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
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/webp/to/svg",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("guest-badge.webp", "rb"))],
data={
"FilterSpeckle": "2",
"CurveMode": "polygon",
},
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 = "guest-badge.webp";
form.append("File", new Blob([await readFile(file)]), file);
form.append("FilterSpeckle", "2");
form.append("CurveMode", "polygon");
const url = "https://api.pdfconversionapi.com/v2/convert/webp/to/svg";
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.027,
"Files": [
{
"FileName": "guest-badge.svg",
"FileExt": "svg",
"FileSize": 35733,
"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.

- Input
- guest-badge.webp (9.4 KB)
- Output
- guest-badge.svg (35 KB)
- Source
- A guest pass for a made-up trade show that we drew for this page, saved as a lossy WebP with a transparent background and a soft shadow. (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 |
|---|---|
FilterSpeckleinteger, default 4 | Drops patches smaller than this size. The sample's 2 keeps the QR code's modules, which the default of 4 broke up.Values: 0–128 |
CurveModeenum, default spline | polygon, used in the sample, gave 35,733 bytes; with the same FilterSpeckle=2, a spline trace of the badge was 97,845 bytes. pixel follows the pixel grid.Values: pixel, polygon, spline |
ColorPrecisioninteger, default 6 | Bits per channel used to group colors; lower merges more of the lossy WebP's shades.Values: 1–8 |
GradientStepinteger, default 16 | Color step between stacked layers; smaller steps add layers for gradients like the badge's teal header. 0 worked on the badge, yet a 400 × 300 photo saved as WebP was refused with 422 'this image could not be traced with GradientStep=0; use 1 or more'.Values: 0–128 |
Presetenum, default none | bw makes a black-and-white trace (31,153 bytes); poster and photo start from the tracer's own presets, which your other options then override.Values: none, bw, poster, photo |
ColorModeenum, default color | bw traces two colors only.Values: color, bw |
Layeringenum, default stacked | cutout produced 83 shapes that don't overlap (62,780 bytes).Values: stacked, cutout |
CornerThresholdinteger, default 60 | Joints sharper than this many degrees stay corners.Values: 0–180 |
SegmentLengthnumber, default 4 | Length of curve segments; below 3.5 returns 400.Values: 3.5–10 |
SpliceThresholdinteger, default 45 | Angle in degrees at which splines are split.Values: 0–180 |
ImageWidthinteger | Scales the WebP before tracing; 200 gave a 50,443-byte SVG.Values: 1–20000 |
ImageHeightinteger | Same, by height; with ImageWidth it fits the image inside the box.Values: 1–20000 |
ScaleProportionsboolean, default true | false traces a stretched copy that fills the box. |
ScaleIfLargerboolean, default false | true never enlarges before tracing. |
ScaleImageboolean, default true | false traces only a top-left crop of the requested size. |
ImageInterpolationboolean, default false | Accepted either way; any resize before tracing uses Lanczos. |
FileNamestring | Name of the SVG, guest-badge.svg by default. |
StoreFileboolean, default false | true returns a 3-hour download link instead of the base64 SVG. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageResolution | 200, ConvertAPI's default, is accepted; other values return 400 'ImageResolution is not supported yet for WebP → SVG'. Paths are sized in WebP pixels. |
ColorSpace | Only default and TrueColors, which leave the trace unchanged; gray returns 400 'ColorSpace is not supported yet for WebP → SVG'. Use ColorMode=bw or Preset=bw for a two-color trace. |
ImageQuality | Only 75 is accepted; the trace has no quality setting of that kind. |
What carries over, and what doesn't
Kept
- Clear areas: the four rounded corners stay empty, with 2,510 transparent pixels in a render of the SVG against 2,599 in the WebP.
- A scannable QR code with the sample's settings; a render decoded to the pass text. The default settings lost it.
- Large shapes and lettering: the teal band, GUEST PASS and the yellow B badge come through, though the heading lost the I in BUILDERS.
- The canvas size: 400 × 260 user units.
- EXIF orientation: a 300 × 200 WebP tagged 6 traced into an upright 200 × 300 drawing.
Lost or not yet supported
- Partial transparency. The soft drop shadow, 11,188 partly clear pixels with alpha 1 to 106, became a solid dark shape, because paths are written without opacity.
- Small text: the 13 to 15 px lines broke into fragments.
- Smooth color: the lossy WebP's slight noise was traced into 268 fill colors across 338 paths.
- Animation frames after the first; only frame 1 is traced.
- A viewBox on the root element, which has width and height only.
Limits
- One WebP per request.
- Tracing is capped at 12,000,000 pixels. A 4,000 × 3,001 WebP returned 413 with its size and a hint to set
ImageWidthorImageHeight;ImageWidth=2000then traced it. - Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- Out-of-range options return 400, such as 'CurveMode must be one of: pixel, polygon, spline'.
- Conversions longer than 120 seconds return 504.
Where teams use it
Vector versions of web graphics
Logos, badges and icons downloaded as WebP can be traced into paths for print, signage or a vinyl cutter, then refined in a vector editor.
Cut-outs that stay cut out
Transparent areas of a WebP are not filled in the SVG, so a traced sticker or icon keeps its shape on any background.
Questions
What happens to the WebP's transparency?
Fully transparent pixels are left out, so the SVG has empty corners where the WebP did. Partly transparent pixels are traced as solid color, which turned the badge's soft shadow into a hard dark edge.
Which settings should I start with?
For flat graphics, FilterSpeckle=2 and CurveMode=polygon as in the sample. They kept the QR code readable and gave 35,733 bytes; the defaults gave 80,109 bytes and an unreadable code.
Why are ColorSpace and ImageQuality refused?
ConvertAPI lists them for WebP to SVG, but our tracer doesn't use them. Rather than ignore them silently, the API returns 400 for any value that asks for a change. ColorSpace=default or TrueColors and ImageQuality=75 are accepted and give the same SVG as leaving them out.
Is there a bitmap inside the SVG?
No. The file contains only path elements with solid fills, so it scales without pixels showing.
Convert your first WebP file in a minute.