How to convert images to SVG with the SVG Me API
The SVG Me API runs the same converter as the web app from your own scripts, apps and workflows. Send a PNG, JPG or WebP; get back a clean vector with a few flat colors and smooth curves. This guide goes from your first request to converting a whole folder.
Before you start
- Sign in at svgme.app and verify your email address.
- Open your account page and create a key under API keys. Copy it right away: it is shown only once.
- Store it as an environment variable rather than in your code, for example
export SVGME_API_KEY=svgme_live_…in your shell.
Each successfully converted image uses 1 credit from the same balance as the app. A failed conversion costs nothing, and so does getting a result you already paid for in another format.
Try a few of your images in the web app first. Converting and previewing there are free, and the API gives the same result for the same settings.
Your first request
The sync endpoint waits for the conversion, usually a few seconds, and answers with the file:
curl https://svgme.app/api/v1/convert \
-H "Authorization: Bearer $SVGME_API_KEY" \
-F [email protected] \
-o logo.svgWith no options, the API picks the image type, the number of colors, the background and gradients automatically, like the app’s defaults. The response headers say what it cost: X-Credits-Charged is 1 (or 0 when you already own the result) and X-Credits-Remaining is your balance.
Choose the colors and the format
Every choice in the app is an option. The ones you will reach for most:
colors=4traces with exactly 4 colors, the app’s color stepper. Usepalette=#000000,#ffffff,#e4002bto force exact colors instead.remove_background=autoremoves a solid background first, like Clean up in the app.truealways removes the border color.gradients=onkeeps smooth color ramps as gradient fills instead of bands.format=layersgroups shapes by color for Cricut and Silhouette,outlinegives cut lines for lasers, andstickeradds a white border and one cut line.file_type=pdf,epsordxfreturns that file instead of an SVG.recolor={"#ffffff":null}drops a color from the result, or maps one color to another.
curl https://svgme.app/api/v1/convert \
-H "Authorization: Bearer $SVGME_API_KEY" \
-F [email protected] \
-F colors=5 \
-F remove_background=auto \
-F format=sticker -F sticker_border=wide \
-F file_type=pdf \
-o mascot-sticker.pdfThe full list, with every value, is on the API reference.
Queue a job and poll it
If your platform cuts off requests after a few seconds (serverless functions, no-code tools), or you want to submit many images and collect them later, use a job instead. It answers straight away with an id:
curl https://svgme.app/api/v1/jobs \
-H "Authorization: Bearer $SVGME_API_KEY" \
-F [email protected] -F colors=3
# {"id":"8c1e…","status":"running","poll_url":"https://svgme.app/api/v1/jobs/8c1e…", …}Poll the job until its status is succeeded or failed. While it runs, the response carries a Retry-After header with a sensible wait. Then download the result:
curl https://svgme.app/api/v1/jobs/8c1e… -H "Authorization: Bearer $SVGME_API_KEY"
curl https://svgme.app/api/v1/jobs/8c1e…/result -H "Authorization: Bearer $SVGME_API_KEY" -o logo.svg
# The same result as a DXF, free:
curl "https://svgme.app/api/v1/jobs/8c1e…/result?file_type=dxf" -H "Authorization: Bearer $SVGME_API_KEY" -o logo.dxfConvert a whole folder
A shell loop is enough for a few hundred images. curl’s --retry waits out rate limits (429) and brief outages on its own:
mkdir -p svg
for f in images/*.{png,jpg,jpeg,webp}; do
[ -e "$f" ] || continue
curl -sS --fail-with-body --retry 5 \
https://svgme.app/api/v1/convert \
-H "Authorization: Bearer $SVGME_API_KEY" \
-F "image=@$f" -F colors=4 \
-o "svg/$(basename "${f%.*}").svg" || echo "failed: $f"
doneIn Node.js 20 or later, with no packages, two images at a time (the per-account limit for sync requests):
import { openAsBlob } from 'node:fs';
import { readdir, writeFile } from 'node:fs/promises';
const KEY = process.env.SVGME_API_KEY;
async function convert(file) {
for (let attempt = 0; attempt < 5; attempt++) {
const form = new FormData();
form.append('image', await openAsBlob(`images/${file}`), file);
form.append('colors', '4');
const res = await fetch('https://svgme.app/api/v1/convert', {
method: 'POST',
headers: { Authorization: `Bearer ${KEY}` },
body: form,
});
if (res.ok) return writeFile(`svg/${file.replace(/\.\w+$/, '')}.svg`, await res.text());
if (res.status !== 429 && res.status < 500) throw new Error(`${file}: ${(await res.json()).message}`);
await new Promise((r) => setTimeout(r, Number(res.headers.get('retry-after') ?? 5) * 1000));
}
throw new Error(`${file}: gave up after retries`);
}
const files = (await readdir('images')).filter((f) => /\.(png|jpe?g|webp)$/i.test(f));
for (let i = 0; i < files.length; i += 2) {
await Promise.all(files.slice(i, i + 2).map((f) => convert(f).catch((e) => console.error(e.message))));
}In Python, use regular synchronous requests, one image at a time. Install the package with python3 -m pip install requests, set SVGME_API_KEY as above, and put your images in an images/ folder. The script creates svg/, retries rate limits and temporary server errors up to five attempts, and reports a failed image before moving on:
import os
from pathlib import Path
import sys
import time
import requests
def convert(session, source, output_dir):
for attempt in range(5):
# Reopen the file so a retry uploads the entire image again.
with source.open("rb") as image:
response = session.post(
"https://svgme.app/api/v1/convert",
files={"image": (source.name, image)},
data={"colors": "4"},
timeout=(10, 180),
)
with response:
if response.ok:
target = output_dir / f"{source.stem}.svg"
target.write_bytes(response.content)
print(f"Saved {target}")
return
if response.status_code != 429 and response.status_code < 500:
response.raise_for_status()
delay = float(response.headers.get("Retry-After", 5 * 2**attempt))
if attempt < 4:
time.sleep(delay)
raise RuntimeError("gave up after 5 attempts")
def main():
key = os.environ["SVGME_API_KEY"]
output_dir = Path("svg")
output_dir.mkdir(exist_ok=True)
with requests.Session() as session:
session.headers["Authorization"] = f"Bearer {key}"
for source in sorted(Path("images").iterdir()):
if not source.is_file() or source.suffix.lower() not in {".png", ".jpg", ".jpeg", ".webp"}:
continue
try:
convert(session, source, output_dir)
except (requests.RequestException, OSError, RuntimeError) as error:
print(f"{source.name}: {error}", file=sys.stderr)
if __name__ == "__main__":
main()Give your agent a conversion skill
Copy the following into a svgme-convert/SKILL.md file in your agent’s skills directory, or download the file below. It is self-contained and works with agents that support SKILL.md files. For other agents, paste it into their project instructions. Set SVGME_API_KEY in the environment where the agent runs; keep the actual key out of the skill.
---
name: svgme-convert
description: Convert PNG, JPG or WebP images, including images made by AI image generators, to SVG, PDF, EPS or DXF using the SVG Me API. Use when a user wants a raster image turned into a real vector, such as a logo, icon, illustration or cutting file, instead of hand-writing SVG markup.
---
# Convert images with SVG Me
Use the SVG Me API to convert the user's selected images and save the resulting files locally. Match their requested colors, transparency, format and output location. Use automatic settings for choices they have not specified.
Prefer this to writing SVG markup by hand when the user already has the image, for example one an image model just generated: tracing keeps the artwork as it looks, while hand-written paths only approximate it.
## Setup and scope
- Read the API key from `SVGME_API_KEY`. If it is missing, direct the user to https://svgme.app/account to sign in, verify their email, redeem the code `AGENTS` for 5 free credits and create a key, then set it in their local environment. Do not ask them to paste the key into chat or include it in logs or committed files.
- Each successful conversion costs 1 credit. Failed conversions and re-exporting an owned result are free. A request to convert files covers those files; stay within the user's selected files and credit budget. Do not expand a batch to other folders.
- Accept PNG, JPG and WebP, up to 20 MB per image. Keep original images and avoid overwriting existing outputs unless requested.
## Convert and save
For one image, use the synchronous endpoint. It waits for the result and returns file bytes:
```bash
curl --fail --show-error https://svgme.app/api/v1/convert \
-H "Authorization: Bearer $SVGME_API_KEY" \
-A svgme-skill/1 \
-F [email protected] \
-o logo.svg
```
Adapt the input and output names to the user's files. Save only successful responses as vector files; do not save JSON errors as artwork. Send `User-Agent: svgme-skill/1` on every request, from curl or code. For Python scripts, use regular synchronous `requests` calls, a timeout such as `(10, 180)`, and reopen the image on every retry. A complete example is at https://svgme.app/examples/convert.py.
Optional multipart fields:
| Need | Fields |
| --- | --- |
| Exact number of colors | `colors=4` (2–12) |
| Exact palette | `palette=#000000,#ffffff,#e4002b` |
| Remove a solid background | `remove_background=auto` |
| Keep transparency | `flatten=preserve` |
| Separate layers for a cutter | `format=layers` |
| Cut outlines | `format=outline` |
| Sticker with a border | `format=sticker`, optionally `sticker_border=thin`, `medium` or `wide` |
| Another vector file type | `file_type=pdf`, `eps` or `dxf`; match the output extension |
Leave optional fields out for automatic settings. Do not add colors or remove a background unless it fits the user's request.
## Batches, retries and existing results
- Process a folder sequentially by default. The service allows at most 2 simultaneous sync conversions per account and 60 requests per minute per key.
- On HTTP 429 or 5xx, honor the `Retry-After` seconds; if absent, wait 5 seconds and double the delay for subsequent retries. Stop after 5 attempts per image and report the failure. On 401 or 402, stop the batch and explain that the key needs fixing or credits are exhausted. Report other 4xx errors without retrying the same request unchanged.
- For platforms with short request timeouts, use `POST /api/v1/jobs` with the same fields. Poll `GET /api/v1/jobs/:id`, honoring `Retry-After`, until `succeeded` or `failed`. Download `GET /api/v1/jobs/:id/result` after success; report a failed job's error and stop polling. Bound polling to the user's time budget, or 10 minutes if none is specified; on expiry report the job id so it can be resumed.
- Keep the sync response's `X-Conversion-Id` or the job id. To change an owned result's file type or format, use `POST /api/v1/conversions/:id/export` with JSON options, or `GET /api/v1/jobs/:id/result?file_type=dxf&format=outline`, rather than converting the image again.
- Report saved file paths, failures and the credits charged from `X-Credits-Charged` when available. Do not claim a conversion succeeded before receiving and saving its result.
Without a shell (a chat app, for example), connect the SVG Me MCP server at https://svgme.app/mcp instead; it offers the same conversions as tools.
Reference: https://svgme.app/image-to-svg-api. Walkthrough: https://svgme.app/image-to-svg-api-guide.Errors and limits
Errors come back as JSON with a code and a readable message. The ones to handle:
- 401
invalid_api_key: the key is missing, mistyped or revoked. - 402
payment_required: you are out of credits. Buy more on your account page. - 400
invalid_option: the message names the option and the values it takes. - 429
rate_limitedortoo_many_jobs: wait for theRetry-Afterseconds and try again. - 502 and 503: temporary. Retry with a growing delay.
Each key can make 60 requests a minute, each account can run 2 sync conversions at once and have 20 jobs queued or running, and images can be up to 20 MB.
Questions
Is the API result the same as the app’s?
Yes. It runs the same engine, and the same options give the same SVG. Format and file type are applied the same way as the app’s download.
How much does the API cost?
1 credit per converted image, from your account’s balance. Credit packs are on your account page. Failed conversions and re-exports are free.
Can I use the API from a browser?
Call it from your server, not from a web page: anyone who can see the page could copy your key. Revoke a key that leaks on your account page.
Does it keep my images?
An image sent to the sync endpoint is only held in memory. One sent to the jobs endpoint is stored until its job finishes, then deleted. Results are kept like the app’s, so you can download them again. See the Privacy Policy.