ICO to PDF API
POST an icon to /v2/convert/ico/to/pdf and get a one-page PDF. The best entry of the .ico is stored without loss as an RGB image plus an 8-bit soft mask, so its transparent corners show the page underneath.
- Endpoint
- POST /v2/
convert/ ico/ to/ pdf - Accepts
- ico
- Sample timing
- 3 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/ico/to/pdf \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@paper-plane-app-icon.ico \
-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/ico/to/pdf",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("paper-plane-app-icon.ico", "rb"))],
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 = "paper-plane-app-icon.ico";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/ico/to/pdf";
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.003,
"Files": [
{
"FileName": "paper-plane-app-icon.pdf",
"FileExt": "pdf",
"FileSize": 22192,
"FileData": "JVBERi0xLjcKJYCAgIAKMSAw…"
}
]
}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
- paper-plane-app-icon.ico (34 KB)
- Output
- paper-plane-app-icon.pdf (22 KB)
- Source
- A four-size app icon we drew and assembled ourselves: 16, 32 and 48 px entries stored as 32-bit bitmaps with a 1-bit mask, and a 256 px entry stored as PNG. The paper plane design is fictional. (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 |
|---|---|
PageSizeenum, default default | Left out (or default, auto), the page is the icon's size at 96 px per inch: 192 × 192 pt, 2.67 in square, for the 256 px sample. A named sheet keeps the icon at that size and centers it; it never enlarges it.Values: default, auto, a3, a4, a5, letter, legal |
PageOrientationenum, default default | landscape turns a named sheet sideways (letter becomes 792 × 612 pt). With the default page size there is nothing to turn.Values: default, portrait, landscape |
Rotateinteger | Whole degrees to turn the icon clockwise. A quarter turn of the square sample keeps the 192 × 192 pt page; 45 grows it to 271.53 pt square so the corners fit. Left out, empty or none, the icon stays upright: an .ico has no orientation tag to follow.Values: -360 to 360 |
MarginHorizontalinteger, default 0 | Millimeters of empty page left and right of the icon. On the default page it adds to the width: 10 gave 248.69 × 192 pt. On a named sheet it narrows the space the icon must fit in: on A4, 100 mm a side shrank the icon to 1 cm, and 105 mm returned 400.Values: 0–500 (mm) |
MarginVerticalinteger, default 0 | The same above and below. 5 adds 14.17 pt at the top and at the bottom, so with MarginHorizontal=10 the page is 248.69 × 220.35 pt.Values: 0–500 (mm) |
FileNamestring | Name of the PDF; the icon's file name is used by default. |
StoreFileboolean, default false | Store the PDF for 3 hours and return a URL to it. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ColorSpace | default and TrueColors are accepted and give the same PDF; gray, rgb and other values return 400. |
ColorProfile | Only default. |
Pdfa | Only false. Send the PDF to /v2/convert/pdf/to/pdfa for an archival version. |
What carries over, and what doesn't
Kept
- The pixels and alpha of the icon's 256 px entry: the image and soft mask pulled back out of the sample PDF match it value for value
- Lossless storage, compressed with Flate
- Transparency, as an 8-bit DeviceGray soft mask next to the DeviceRGB image
- Physical size tied to pixels: 256 px is 2.67 in on every page size, unless margins leave less room
- The stored image when the icon is turned or given margins: only the drawing position changes, and the image and mask streams stay byte for byte the same
Lost or not yet supported
- The other entries in the .ico; one image is placed.
- Upscaling.
ImageWidthandImageHeightare not options of this route, so they are ignored rather than refused, a named sheet never scales a small icon up, and margins can only make it smaller. - Vector sharpness. The icon stays a 256 × 256 bitmap, so zooming in shows its pixels.
Limits
- One icon, one page, per request. Use
/v2/convert/images/to/pdffor several images in one file. - Margins from 0 to 500 mm in whole numbers. On a named sheet they must leave at least 1 pt for the icon in each direction, or the request returns 400.
- 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
Icon sheets for review or print
When icons are reviewed or signed off in a PDF viewer, convert each one to a page with a margin around it, then put the pages in one file with /v2/convert/pdf/to/merge.
Systems that accept only PDF attachments
Ticketing tools, procurement portals and archives that take PDF only can still receive an application's icon, with its transparency stored as a mask rather than flattened onto a color.
Questions
How big is the PDF page?
Without PageSize, the page matches the icon at 96 pixels per inch, plus any margins. The 256 px sample icon gives a 192 × 192 pt page, 2.67 inches square.
Can I make the icon fill an A4 page?
Not on this route. A named sheet centers the icon at its own size. For a bigger icon, convert it with /v2/convert/ico/to/png and ImageWidth first, then send the PNG to /v2/convert/png/to/pdf.
What do the transparent corners look like?
They are transparent in the PDF: the soft mask hides those pixels, so a viewer shows the white page and a printer leaves the paper blank there.
Which way does Rotate turn the icon?
Clockwise: with Rotate=90 the icon's left edge ends up at the top. The turn is part of the page's drawing instructions, and the PDF sets no page rotation flag, so the page size you get is the size you see.
Why did my margins return 400?
On a named sheet the margins come out of the sheet's own size. A4 is 210 mm wide, so MarginHorizontal=105 leaves nothing for the icon and the API answers "MarginHorizontal and MarginVertical leave no room for the image on the page". Without PageSize the page grows instead, by up to 500 mm on each side of the icon.
Convert your first ICO file in a minute.