BMP to ICO API
POST a BMP to /v2/convert/bmp/to/ico and get an icon file holding one 32-bit entry. Bitmaps larger than 256 px on a side are scaled down to fit, so our 400 × 250 label became a 256 × 160 icon.
- Endpoint
- POST /v2/
convert/ bmp/ to/ ico - Accepts
- bmp
- Sample timing
- 4 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/ico \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@shelf-label.bmp \
-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/bmp/to/ico",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("shelf-label.bmp", "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 = "shelf-label.bmp";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/bmp/to/ico";
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.004,
"Files": [
{
"FileName": "shelf-label.ico",
"FileExt": "ico",
"FileSize": 32135,
"FileData": "AAABAAEAAKAAAAAAIABxfQAA…"
}
]
}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
- shelf-label.bmp (293 KB)
- Output
- shelf-label.ico (31 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.
| Parameter | What it does |
|---|---|
ImageWidthinteger | Icon width before the 256 px limit. 64 produced a 64 × 40 icon of 5,019 bytes.Values: 1–20000 |
ImageHeightinteger | Icon height before the limit; 100 gave 160 × 100.Values: 1–20000 |
ScaleProportionsboolean, default true | false with both sizes makes exactly that shape: 48 × 48 gave a square icon of 4,580 bytes, squeezed sideways. |
ScaleIfLargerboolean, default false | true stops a small bitmap from being enlarged; the 256 px cap still applies. |
ScaleImageboolean, default true | false cuts a top-left area of the requested size instead of scaling, a way to pick a square region. |
ColorSpaceenum, default default | Gray or black-and-white pixels inside the same 32-bit entry. monochrome is applied after the fit to 256 × 160, so the icon holds only pure black and white: 4,517 bytes against 32,135 in color.Values: default, rgb, gray, monochrome |
FileNamestring | Name of the .ico without extension. |
StoreFileboolean, default false | Return a link for 3 hours instead of the data. |
What carries over, and what doesn't
Kept
- Colors and detail down to 256 px: the label's QR code still decoded from the 256 × 160 icon
- The bitmap's shape unless you ask for another
- Alpha from 32-bit BMPs that carry an alpha mask; opaque bitmaps get alpha 255 everywhere
Lost or not yet supported
- Pixels above 256 per side, which are resampled away.
- A set of sizes. The .ico has one entry; there are no separate 16, 32 or 48 px images in it.
- Squareness: a 400 × 250 bitmap gives a 256 × 160 icon unless you crop or stretch it.
- Small file size for 1-bit art: a 1-bit version of the label made a 77,708-byte icon, since scaling adds gray edges to the black and white.
Limits
- One BMP per request, one image in the .ico.
- Icon entries never exceed 256 × 256.
- 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.
- 120 seconds per conversion.
Where teams use it
Icons for Windows programs and shortcuts
Toolbar art and logos drawn as BMP can become the .ico an installer, a shortcut or an executable's resources expect.
Favicons from existing bitmaps
A small square crop of a BMP logo, made with ScaleImage=false, gives a .ico for a site's favicon.
Questions
What does the .ico contain?
A single 32-bit image stored as PNG data. For the sample it is 256 × 160 and 32,113 bytes inside a 32,135-byte file.
How do I get a 32 × 32 or 48 × 48 icon?
Send ImageWidth and ImageHeight with the size. To avoid distortion on a non-square bitmap, crop with ScaleImage=false first, or accept the stretched result with ScaleProportions=false.
Can I make the background transparent?
Not with TransparentColor on this route; it is ignored for icons. Start from a BMP with an alpha mask, or from a PNG with transparency.
Convert your first BMP file in a minute.