EML to WebP API
POST an .eml file to /v2/convert/eml/to/webp and each page of the message returns as a lossless WebP. With PageSize=letter and ImageResolution=110, the roof inspection sample gave two 935 × 1210 images of 109,530 and 143,210 bytes.
- Endpoint
- POST /v2/
convert/ eml/ to/ webp - Accepts
- eml
- Sample timing
- 35 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/eml/to/webp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@roof-inspection-418-linden.eml \
--form-string PageSize=letter \
--form-string ImageResolution=110 \
-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/eml/to/webp",
headers={"Authorization": f"Bearer {key}"},
files=[
("File", open("roof-inspection-418-linden.eml", "rb")),
],
data={
"PageSize": "letter",
"ImageResolution": "110",
},
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 = "roof-inspection-418-linden.eml";
form.append("File", new Blob([await readFile(file)]), file);
form.append("PageSize", "letter");
form.append("ImageResolution", "110");
const url = "https://api.pdfconversionapi.com/v2/convert/eml/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.035,
"Files": [
{
"FileName": "roof-inspection-418-linden-1.webp",
"FileExt": "webp",
"FileSize": 109530,
"FileData": "UklGRtKrAQBXRUJQVlA4TMar…"
},
{
"FileName": "roof-inspection-418-linden-2.webp",
"FileExt": "webp",
"FileSize": 143210,
"FileData": "UklGRmIvAgBXRUJQVlA4TFYv…"
}
]
}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
- roof-inspection-418-linden.eml (77 KB)
- Output
- roof-inspection-418-linden-1.webp (107 KB)roof-inspection-418-linden-2.webp (140 KB)
- Source
- A fictional two-page roof inspection email with an inline roof plan and four attachments, written and drawn by us for this site. (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 a4 | Paper size the message is paginated on. The sample sends letter (8.5 × 11 in); the message still needs two pages.Values: a0–a9, b0–b5, letter, legal, ledger |
ImageResolutioninteger, default 150 | How many pixels per inch of paper. Letter at 110 gives the sample's 935 × 1210; A4 at the default 150 gives 1240 × 1753. WebP has no field for it, so nothing is recorded in the file.Values: 36–600 |
ImageWidthinteger | Exact pixel width for every page; the height follows the paper's proportions.Values: 1–20,000 |
ImageHeightinteger | Exact pixel height, or with ImageWidth a box the page must fit in.Values: 1–20,000 |
PageRangestring | Limits the response to some pages, for example 1 for a preview of the header and opening lines.Values: 1, 2, 1-2, 2- |
ConvertHeaderboolean, default true | Whether page 1 starts with the subject line and the From, To, Cc and Date table. |
PageOrientationenum, default portrait | Lay the message out on paper turned sideways.Values: portrait, landscape |
PageWidthinteger | Paper width in mm. Matching it to a viewer column, such as 180, keeps text large on screen.Values: 10–30,000 (mm) |
PageHeightinteger | Paper height in mm, which sets where a long message breaks into the next image.Values: 10–30,000 (mm) |
MarginTopinteger, default 5 | Top margin in millimeters.Values: 0–500 (mm) |
MarginRightinteger, default 5 | Right margin in millimeters.Values: 0–500 (mm) |
MarginBottominteger, default 5 | Bottom margin in millimeters.Values: 0–500 (mm) |
MarginLeftinteger, default 5 | Left margin in millimeters.Values: 0–500 (mm) |
TransparentColorstring | Makes pixels of exactly that color transparent. With white the page background drops out, which suits a dark-mode viewer that supplies its own backdrop.Values: Color names, #RRGGBB or R,G,B |
BackgroundColorstring, default white | Backdrop painted under each page before the WebP is encoded.Values: Color names, #RRGGBB or R,G,B |
ColorSpaceenum, default default | gray turns every pixel gray (page 1 at 50 dpi dropped from 43,700 to 31,278 bytes); the WebP itself is still a three-channel RGB image.Values: default, rgb, gray, monochrome |
IgnoreAttachmentErrorsboolean, default false | Has no effect here and is accepted for compatibility. |
Mergeboolean, default true | Has no effect; WebP files are always one per page. |
FileNamestring | Replaces roof-inspection-418-linden in the result names; page numbers are still appended. |
StoreFileboolean, default false | Stores the WebPs for 3 hours and returns their URLs instead of base64. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageQuality | Our WebP encoder writes lossless images only. ConvertAPI's default of 75 is accepted; any other value returns 400 "ImageQuality is not supported yet for EML → WebP". |
TemplateFile | Refused; the header block cannot be restyled. |
DateTimeFormat | Refused; the Date row uses ISO 8601. |
ConvertAttachments | Refused when true. Fetch attachments with /v2/convert/email/to/extract. |
What carries over, and what doesn't
Kept
- Exact pixels: the pages are VP8L (lossless) WebP, so text edges and the thin table rules are not blurred by compression
- The full header block, the CSS-styled findings and estimate tables, the callout box and the quoted reply, laid out over two Letter pages
- The inline roof plan from the message's cid: part
- An opaque page with no alpha channel, unless you send
TransparentColor, which adds one - The attachment line at the bottom of page 2 with the four file names and sizes
Lost or not yet supported
- A lossy, smaller mode: the encoder only writes lossless WebP, and
ImageQualitycannot change that. - Resolution metadata. The 110 dpi of the sample is not stored anywhere in the WebP.
- Remote content. Images and backgrounds the HTML loads by URL are not fetched, and a sized remote img leaves an empty rectangle.
- HTML 3-era formatting attributes (bgcolor, font color and size, align on cells), which our layout ignores; CSS is applied.
- Searchable or selectable text and working links.
- Reply-To, In-Reply-To and Bcc, none of which appear in the header block.
Limits
- One .eml file per request.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- Image sides up to 20,000 px when set with
ImageWidthorImageHeight; drawing over 16,000 px on a side, or over 100,000,000 pixels, returns 413. - Up to 2,000 pages per request.
- Uploads that are not email messages return 422.
- Each conversion has 120 seconds before a 504.
Where teams use it
Email views in a web app
A support portal or an archive search page can show the message as WebP images inside an img tag. Nothing from the original HTML runs in your page, and the files are smaller than PNG at the same resolution.
Case files shown in the browser
When an emailed report has to be viewed next to photos and notes, store its pages as WebP alongside the other images. The header block on page 1 keeps the sender and date with the picture.
Questions
How much smaller is WebP than PNG here?
For this message, about half or less: 41% to 51% of the PNG bytes. At A4 and 150 dpi the two pages were 167,810 and 202,046 bytes as WebP and 410,518 and 403,425 bytes as PNG, both lossless. With the sample's Letter and 110 dpi, WebP gave 109,530 and 143,210 bytes against 265,570 and 282,820 for PNG.
Can I set a WebP quality?
No. The output is always lossless, so there is no quality to set; ImageQuality=75 is accepted because it is ConvertAPI's default, and other values return 400. If you need a lossy image, use /v2/convert/eml/to/jpg, which reads ImageQuality.
Are the WebP images transparent?
Not by default: the pages are opaque RGB images on a white page, with no alpha channel. Send TransparentColor=white to add one and make the background transparent; in our test the page corner came back as (255, 255, 255, 0).
Can I get the whole email as one tall image?
Yes, by making the page tall enough: with PageHeight=600 (millimeters) the sample fit on one page and came back as a single 413 × 1181 WebP at 50 dpi. The page is drawn to its full height even below the last line, so do not overshoot: 30,000 mm at 50 dpi would be 59,055 pixels tall and returns 413.
Convert your first EML file in a minute.