PNG to BMP API
POST a PNG to /v2/convert/png/to/bmp and get a Windows bitmap back in the JSON. The sample's alpha goes unchanged into the fourth byte of each pixel of a 32-bit bitmap, so transparent corners and partly transparent shadows survive; a PNG with no see-through pixels becomes a plain 24-bit bitmap.
- Endpoint
- POST /v2/
convert/ png/ to/ bmp - Accepts
- png
- Sample timing
- 1 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/png/to/bmp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@garden-plot-badge.png \
-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/png/to/bmp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("garden-plot-badge.png", "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 = "garden-plot-badge.png";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/png/to/bmp";
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.001,
"Files": [
{
"FileName": "garden-plot-badge.bmp",
"FileExt": "bmp",
"FileSize": 360122,
"FileData": "Qk26fgUAAAAAAHoAAABsAAAA…"
}
]
}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
- garden-plot-badge.png (39 KB)
- Output
- garden-plot-badge.bmp (352 KB)
- Source
- A round garden-plot sticker with a QR code, a transparent background and a soft drop shadow, drawn by us for these pages. (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 | Width of the bitmap. The badge is square, so ImageWidth=150 makes it 150 × 150 (90,122 bytes); alpha is resampled with the colors.Values: 1–20000 |
ImageHeightinteger | Height of the bitmap; on its own it sets the width too (ImageHeight=100 gives 100 × 100). With ImageWidth it defines a box: 200 × 100 fits the badge at 100 × 100.Values: 1–20000 |
ScaleProportionsboolean, default true | Turn it off to fill the box exactly. With ImageWidth=200 and ImageHeight=100 the round badge becomes a 200 × 100 oval. |
ScaleIfLargerboolean, default false | With true a PNG smaller than the requested width is left alone: asking for 600 px returns the 300 × 300 bitmap, not a 600 × 600 one of 1,440,122 bytes. |
ScaleImageboolean, default true | false crops the top-left ImageWidth × ImageHeight pixels without scaling, transparent corner included; 120 × 90 comes back 120 × 90. |
ImageResolutioninteger | Stored in the header in pixels per metre, so 96 becomes 3,780. The PNG's own pHYs value (144 dpi in the sample) is not carried over without it.Values: 10–800 |
ColorSpaceenum, default default | gray turns the green badge gray while the alpha byte is kept; the bitmap stays 32 bits per pixel.Values: default, rgb, gray, monochrome; cmyk is refused |
FileNamestring | Sets the output name. Left out, garden-plot-badge.png becomes garden-plot-badge.bmp. |
StoreFileboolean, default false | Ask for true to receive Files[].Url instead of inline base64. The link expires after 3 hours. |
What carries over, and what doesn't
Kept
- The alpha channel, value for value: all 90,000 RGBA pixels of the sample matched the PNG
- Soft shadows and anti-aliased edges, since partial alpha is stored, not rounded to on or off
- Palette and grayscale PNGs, expanded to 8 bits per color channel: 32-bit with alpha when some pixel is transparent, 24-bit when none is
- The pixel grid, unless you ask for a new size
- The upright view of a PNG tagged with an EXIF orientation: a 300 × 200 test PNG tagged Orientation 6 came back as a 200 × 300 bitmap
Lost or not yet supported
- Compression. The 40,051-byte PNG becomes a 360,122-byte bitmap, 300 × 300 × 4 bytes plus the header.
- 16-bit depth. A 16-bit grayscale PNG is reduced to 8 bits per channel.
- The PNG's 144 dpi and its text chunk. The header records 0 dpi unless you send
ImageResolution. - Embedded color profiles. A PNG with an sRGB profile produced the same bytes as one without.
- Animation. An animated PNG gives a bitmap of its first frame.
- A choice of background.
AlphaColorhas no effect here, so transparent areas stay transparent rather than becoming white.
Limits
- Exactly one PNG per request.
- Request bodies up to 10 MB on the Free plan or 100 MB on paid plans.
- No more than 100,000,000 pixels per image (413 above that).
- Width and height between 1 and 20,000 px.
- 120 seconds of conversion time, then 504.
Where teams use it
Icons and sprites for Windows tools that read .bmp
A transparent PNG exported from a design tool can go to a program that loads bitmaps with an alpha channel. The badge's 21,347 fully transparent pixels and 13,498 partly transparent edge and shadow pixels arrive with the same alpha values.
Fixed-size art for firmware or kiosks
Send ImageWidth and ImageHeight with ScaleProportions=false to get a bitmap at exactly the panel size, then let the device read raw pixels with no PNG decoder on board.
Questions
Will the transparent background show as transparent?
The transparency is in the file: each pixel's fourth byte is its alpha, taken straight from the PNG. Whether it shows depends on the program reading the BMP, since some programs display bitmaps as opaque. The header's color space field is 0, and the image tools built into macOS opened the sample with its transparency.
How do I get a BMP with a solid white background instead?
AlphaColor is not read on this route; the bitmap came back byte-identical with it. Flatten first: convert with png-to-pnm and AlphaColor=#FFFFFF (or any color), then convert that file to BMP. We tested this with #F3EFE6 and got a fully opaque 24-bit bitmap of 270,054 bytes with that color in the corners.
Why is the file nine times bigger than the PNG?
PNG compresses; the bitmap we write does not. At four bytes a pixel the 300 × 300 badge needs 360,000 bytes of pixel data plus a 122-byte header.
What happens to a 16-bit or palette PNG?
Both are reduced to 8 bits per channel. A 64 × 64 palette PNG with a transparent index came back as a 16,506-byte 32-bit bitmap with that index transparent. The same picture without a transparent index, and a 64 × 64 16-bit gray PNG, each came back as a 12,342-byte 24-bit bitmap.
Convert your first PNG file in a minute.