MSG to WebP API
POST an Outlook .msg file to /v2/convert/msg/to/webp and each page of the message comes back as a lossless WebP. The sample asks for PageRange=1 at ImageResolution=100 and gets one 826 × 1169 image of 143,584 bytes: the header, both tables and the chart.
- Endpoint
- POST /v2/
convert/ msg/ to/ webp - Accepts
- msg
- Sample timing
- 22 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/msg/to/webp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@site-report-week-9.msg \
--form-string PageRange=1 \
--form-string ImageResolution=100 \
-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/msg/to/webp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("site-report-week-9.msg", "rb"))],
data={
"PageRange": "1",
"ImageResolution": "100",
},
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 = "site-report-week-9.msg";
form.append("File", new Blob([await readFile(file)]), file);
form.append("PageRange", "1");
form.append("ImageResolution", "100");
const url = "https://api.pdfconversionapi.com/v2/convert/msg/to/webp";
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.022,
"Files": [
{
"FileName": "site-report-week-9-1.webp",
"FileExt": "webp",
"FileSize": 143584,
"FileData": "UklGRtgwAgBXRUJQVlA4TMww…"
}
]
}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
- site-report-week-9.msg (48 KB)
- Output
- site-report-week-9-1.webp (140 KB)
- Source
- A fictional Outlook message with a weekly building site report, an inline chart and two attachments, written by us and saved to the Outlook file layout by our own script. (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 |
|---|---|
PageRangestring | The pages you want back. The sample's 1 skips page 2, which holds the last paragraph, a site-visit note, the sign-off and the attachment list.Values: 1, 2, 1-2, 2- |
ImageResolutioninteger, default 150 | Pixels per inch of A4 paper: 100 gives 826 × 1169, 150 gives 1240 × 1753. It decides the image size only, as WebP stores no resolution.Values: 36–600 |
ImageWidthinteger | A fixed pixel width, for example the width of your viewer pane.Values: 1–20,000 |
ImageHeightinteger | A fixed pixel height, or a bounding box together with ImageWidth.Values: 1–20,000 |
ConvertHeaderboolean, default true | Leave it on to show who sent the message and when; false starts with the greeting. |
PageSizeenum, default a4 | The paper format behind the page breaks.Values: a0–a9, b0–b5, letter, legal, ledger |
PageOrientationenum, default portrait | Paper direction; landscape suits wide screens.Values: portrait, landscape |
PageWidthinteger | Your own paper width in millimeters.Values: 10–30,000 (mm) |
PageHeightinteger | Your own paper height in millimeters; a taller page means fewer, longer images.Values: 10–30,000 (mm) |
MarginTopinteger, default 5 | Top white space.Values: 0–500 (mm) |
MarginRightinteger, default 5 | Right white space.Values: 0–500 (mm) |
MarginBottominteger, default 5 | Bottom white space.Values: 0–500 (mm) |
MarginLeftinteger, default 5 | Left white space.Values: 0–500 (mm) |
TransparentColorstring | One exact color, typically white, that becomes transparent; only then does the WebP get an alpha channel.Values: Color names, #RRGGBB or R,G,B |
BackgroundColorstring, default white | Page color where the HTML sets none.Values: Color names, #RRGGBB or R,G,B |
ColorSpaceenum, default default | Gray or black-and-white pixel values, stored in an RGB WebP.Values: default, rgb, gray, monochrome |
IgnoreAttachmentErrorsboolean, default false | Accepted and does nothing here. |
Mergeboolean, default true | Accepted and does nothing here. |
FileNamestring | Stem for the file names (<stem>-1.webp). |
StoreFileboolean, default false | Return links valid for 3 hours instead of base64 WebP data. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageQuality | The WebP output is lossless only. 75, ConvertAPI's default, passes; other values return 400 "ImageQuality is not supported yet for MSG → WebP". |
TemplateFile, DateTimeFormat | Any value returns 400. |
ConvertAttachments | true returns 400. |
What carries over, and what doesn't
Kept
- The complete first page of the sample: subject, sender, two To recipients, the Cc, the Date row and the greeting
- The schedule table with its blue heading row and green and red status words
- The progress chart stored in the .msg as an attachment with a content ID
- The cost table's right-aligned figures and the numbered list of decisions
- Lossless pixels (VP8L) in an opaque RGB image, with no alpha channel unless you set
TransparentColor
Lost or not yet supported
- A lossy mode. There is no quality setting to trade detail for bytes; use
msg/to/jpgwithImageQualityfor that. - The resolution value, which WebP has no place for.
- Attachment files: only their names and sizes are printed, on the last page.
- Bcc recipients, and the Date row when the .msg was saved without internet headers.
- Remote images and links: nothing is downloaded, and links in the image cannot be clicked.
Limits
- One .msg per request.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- Up to 2,000 pages per request; image sides from 1 to 20,000 px when set, at most 16,000 px when drawn, and at most 100,000,000 pixels.
- Damaged .msg files and other Office compound files (.ppt, .vsd, .pub) return 422.
- Outlook files saved with 4096-byte sectors return 422.
- 120 seconds per conversion, then 504.
Where teams use it
Outlook messages on an intranet or portal page
Browsers cannot open a .msg file. Convert it once and serve page 1 as a WebP in the page that lists the message, so staff can read it without downloading anything.
Lighter previews than PNG
WebP keeps the same lossless pixels in fewer bytes. For the sample's first page at 150 dpi, that was 233,304 bytes instead of 529,702 for PNG, which adds up across a mailbox of previews.
Questions
Why can't I set a WebP quality?
The encoder writes lossless WebP only, so there is nothing for a quality value to change. Rather than ignore it, the API refuses any value other than 75 with a 400 that names ImageQuality, and 75 is accepted because it is ConvertAPI's documented default.
How does WebP compare with JPEG for this message?
At the default A4 and 150 dpi, page 1 of the sample was 233,304 bytes as lossless WebP and 341,461 bytes as a quality 85 JPEG, so WebP was smaller here and exact as well.
Can I send .eml files here?
Yes. The endpoint reads the first bytes of the upload, and an .eml is handled the same way as on eml/to/webp.
How do I show only the visible top of the message?
Ask for PageRange=1 and, if you want a fixed size for your layout, ImageWidth. For a short message that does not fill page 1, the rest of the image is white page, which TransparentColor=white can turn transparent.
Convert your first MSG file in a minute.