1. [Home](https://svgmill.com/)
2. PNG to SVG API

# PNG to SVG API

Send an image, get the vector file back in the response. One HTTP call, one credit, and every other format of that trace for free.

## How to convert PNG to SVG with the API

1. **Get an API key**: Sign up (5 free credits), then create a key on your account page. Live keys start with svgmill_live_, test keys with svgmill_test_.
2. **Send the image**: POST it to /v1/vectorize as a multipart file, a public URL or base64, with the format you want.
3. **Save the file and the token**: The response body is the file. The X-Image-Token header fetches other formats of the same trace for free.

## Building an agent?

The same account works over MCP, with tools for converting, downloading and checking your balance.

[Agents and MCP](https://svgmill.com/agents/)

## Convert a PNG in three languages

Each example uploads logo.png, saves logo.svg and prints the token for later downloads.

```
curl https://svgmill.com/v1/vectorize \
  -H "Authorization: Bearer $SVGMILL_KEY" \
  -F image=@logo.png \
  -F format=svg \
  -D headers.txt -o logo.svg

grep -i x-image-token headers.txt
```

```
import os, requests

with open("logo.png", "rb") as f:
    r = requests.post(
        "https://svgmill.com/v1/vectorize",
        headers={"Authorization": f"Bearer {os.environ['SVGMILL_KEY']}"},
        files={"image": f},
        data={"format": "svg"},
    )
r.raise_for_status()
open("logo.svg", "wb").write(r.content)
print(r.headers["X-Image-Token"], r.headers["X-Credits-Remaining"])
```

```
import { readFile, writeFile } from "node:fs/promises";

const form = new FormData();
form.append("image", new Blob([await readFile("logo.png")]), "logo.png");
form.append("format", "svg");

const res = await fetch("https://svgmill.com/v1/vectorize", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SVGMILL_KEY}` },
  body: form,
});
if (!res.ok) throw new Error((await res.json()).error.message);
await writeFile("logo.svg", Buffer.from(await res.arrayBuffer()));
console.log(res.headers.get("x-image-token"));
```

## What comes back

| Header | Meaning |
| --- | --- |
| `X-Image-Token` | Identifies this trace. Use it to download other formats or re-trace with new options. |
| `X-Credits-Charged` | `1` for a paid conversion, `0` for previews, test calls and free downloads. |
| `X-Credits-Remaining` | Your balance after this call. |
| `X-RateLimit-Remaining` | Calls left in the current window (60 a minute per key). |

### Other formats for free

Once a trace is paid for, every other format of it costs nothing. Send the token to `POST /v1/download`:

```
curl https://svgmill.com/v1/download \
  -H "Authorization: Bearer $SVGMILL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token":"img_…","format":"dxf"}' -o logo.dxf
```

### Test mode

A test key (`svgmill_test_…`) never spends credits. It returns the real trace with a watermark, as SVG or PNG, so you can build and run your integration tests for free.

### Safe retries

Send an `Idempotency-Key` header on any POST. If the network drops and you retry with the same key within 24 hours, you get the stored response and are not charged twice.

### Errors

Every error has the same shape, and a request that ends in an error uses no credit:

```
{"error": {"code": "insufficient_credits", "message": "You have no credits left. Buy a pack or a plan to continue."}}
```

The codes, statuses and limits are listed in the [API docs](https://svgmill.com/docs/#errors).

## Price per image at volume

The web app, the API and MCP share one balance. Packs last 12 months; plan credits arrive monthly and last 60 days.

| Images | Pack, per credit | Monthly plan, per credit | Annual plan, per credit |
| --- | --- | --- | --- |
| 100 | $0.25 | $0.175 | $0.14 |
| 1,000 | $0.20 | $0.14 | $0.112 |
| 10,000 | $0.15 | $0.105 | $0.084 |
| 100,000 | $0.05 | $0.035 | $0.028 |

[All packs and plans](https://svgmill.com/pricing/)

## API questions

### Can I send an image URL instead of a file?

Yes. Send JSON with image_url (a public http or https address) or image_base64. Private and local addresses are refused.

### How do I change the color count?

Add colors (2 to 64) to the request, or preset set to bw for black and white. Re-tracing an earlier image with new options takes its token and costs a new credit.

### What are the rate limits?

60 requests a minute per API key. Every response carries X-RateLimit headers, and a 429 includes Retry-After.

### How long are files kept?

30 days. Within that time a token can be downloaded in any format. Your conversion history stays in your account after the files are gone.

---
Source: https://svgmill.com/png-to-svg-api/
