DOC to WebP API
POST /v2/convert/doc/to/webp lays out a Word 97-2003 file and returns one WebP per page, named after the file and page number. The images are lossless (VP8L) RGB, with no alpha channel: the sample's two A4 pages at 150 DPI are 96,610 and 20,266 bytes.
- Endpoint
- POST /v2/
convert/ doc/ to/ webp - Accepts
- doc
- Sample timing
- 58 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/doc/to/webp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@loan-agreement.doc \
-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/doc/to/webp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("loan-agreement.doc", "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 = "loan-agreement.doc";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/doc/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.058,
"Files": [
{
"FileName": "loan-agreement-1.webp",
"FileExt": "webp",
"FileSize": 96610,
"FileData": "UklGRlp5AQBXRUJQVlA4TE15…"
},
{
"FileName": "loan-agreement-2.webp",
"FileExt": "webp",
"FileSize": 20266,
"FileData": "UklGRiJPAABXRUJQVlA4TBZP…"
}
]
}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
- loan-agreement.doc (26 KB)
- Output
- loan-agreement-1.webp (94 KB)loan-agreement-2.webp (20 KB)
- Source
- A two-page equipment loan agreement for a fictional sailing club, written for this site and saved in the Word 97-2003 format, with a shaded table, a footnote, a picture and page-numbered footers. (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 |
|---|---|
ImageResolutioninteger, default 150 | Pixels per inch of page: 1,240 × 1,753 for A4 at the default, and the sample's two pages drop to 47,436 and 9,388 bytes at 80. WebP has no field for DPI, so nothing is recorded in the file.Values: 36–600 |
PageRangestring | Only these pages, such as 1 for a cover thumbnail. PageRange=2 returns just loan-agreement-2.webp.Values: e.g. 1, 2-, 1,2 |
ImageWidthinteger | Target width in pixels, with the height following the page's proportions.Values: 1–20,000 |
ImageHeightinteger | Target height in pixels: ImageHeight=800 gives the sample's pages at 566 × 800.Values: 1–20,000 |
BackgroundColorstring | Paint this color behind each page before drawing; white by default. |
TransparentColorstring | Make pixels of exactly this color fully transparent, for pages laid over a colored web background. |
ColorSpaceenum, default default | gray or monochrome remove the color; cmyk returns 400.Values: default, rgb, gray, monochrome |
UpdateFieldsboolean, default false | Refresh fields before layout. Also accepted as UpdateTableOfContents and UpdateReferences. |
IncludeMarkupboolean, default false | Show comments in margin balloons and tracked changes on the page images. |
FileNamestring | Stem of the image names: FileName=loan gives loan-1.webp and loan-2.webp. |
StoreFileboolean, default false | One link per page image instead of the data; links expire after 3 hours. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageQuality | The WebP is always lossless. ConvertAPI's default, 75, is accepted; any other value returns 400, so you know no lossy setting was applied. |
What carries over, and what doesn't
Kept
- Each page as its own image:
loan-agreement-1.webpandloan-agreement-2.webp - The header line, the burgee picture and the footer "Loan agreement, page 1 of 2"
- The navy header row, the light blue table banding and the red warning line
- Every pixel as drawn: VP8L is lossless, so a WebP decoded back matches the page render
Lost or not yet supported
- The table's navy borders, and its full width: our converter draws the equipment table narrower than the 6.5-inch text width.
- The footnote number at the bottom of page 1; the note text is there without its "1".
- Small file sizes for photo-heavy pages. Lossless WebP suits text and flat color; a page with photographs is smaller as JPG at
/v2/convert/doc/to/jpg.
Limits
- Up to 2,000 pages per request; above that, 413.
- 16,000 pixels per side and 100 million pixels per page image.
- 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.
- Password-protected .doc files return 422 "the input file is password-protected" without
Passwordand 400 "password-protected DOC files can't be converted to WebP yet" with it; an unprotected file ignoresPassword.
Where teams use it
Previews in a document portal
Show the first page of every uploaded .doc as an image in a list or a detail view. Browsers display WebP directly, and PageRange=1 keeps it to one image per file.
Text that stays sharp in a thumbnail
Lossless WebP has no compression artifacts around small type, which matters for contracts and forms where people zoom in to read the numbers.
Questions
Can I get smaller, lossy WebP files?
Not yet. The encoder writes lossless WebP only, so ImageQuality is refused unless it is 75, ConvertAPI's default. To make files smaller, lower ImageResolution or set ImageWidth; at 80 DPI the sample's first page is less than half its size at 150.
Do the images have transparency?
Not by default: the pages are written as RGB, with no alpha channel. With TransparentColor=white, the image gets one and the page's white paper becomes transparent (93.1% of page 1), while the text and table fills stay.
How do I get one file with all pages?
WebP gives one image per page. For a single file with every page, use /v2/convert/doc/to/tiff (multi-page) or /v2/convert/doc/to/pdf.
Convert your first DOC file in a minute.