XLTX to WebP API
POST a template to /v2/convert/xltx/to/webp to receive each printed page as a lossless WebP. Asked for the Estimate sheet at ImageWidth=640, the sample returns one 640 × 828 image of 32,084 bytes.
- Endpoint
- POST /v2/
convert/ xltx/ to/ webp - Accepts
- xltx
- Sample timing
- 0.768 s 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/xltx/to/webp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@job-estimate-template.xltx \
--form-string WorksheetName=Estimate \
--form-string ImageWidth=640 \
-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/xltx/to/webp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("job-estimate-template.xltx", "rb"))],
data={
"WorksheetName": "Estimate",
"ImageWidth": "640",
},
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 = "job-estimate-template.xltx";
form.append("File", new Blob([await readFile(file)]), file);
form.append("WorksheetName", "Estimate");
form.append("ImageWidth", "640");
const url = "https://api.pdfconversionapi.com/v2/convert/xltx/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.768,
"Files": [
{
"FileName": "job-estimate-template-1.webp",
"FileExt": "webp",
"FileSize": 32084,
"FileData": "UklGRkx9AABXRUJQVlA4TEB9…"
}
]
}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
- job-estimate-template.xltx (10 KB)
- Output
- job-estimate-template-1.webp (31 KB)
- Source
- Written for this site: a fictional home-repair company's job estimate template with three sheets, one of them hidden, saved as an Excel template (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 | Pixel width of each image; the page is drawn at that width and the height follows Letter's shape (640 gives 828).Values: 1–20000 |
ImageHeightinteger | Pixel height instead, or with ImageWidth a box the page fits inside.Values: 1–20000 |
WorksheetNamestring | Only this sheet. The sample names Estimate, so Rates is not drawn. |
WorksheetIndexinteger | Only the sheet at this position.Values: 1 to the sheet count |
ActiveWorksheetOnlyboolean, default false | Only the sheet selected when the file was saved. |
ImageResolutioninteger, default 150 | Drawing resolution when no width or height is given; not stored in the WebP.Values: 36–600 |
PageSizeenum, default default | Paper for each printed sheet.Values: letter, legal, tabloid, ledger, statement, executive, lettersmall, a3, a4, a4small, a5, b4, b5 |
PageOrientationenum, default default | Orientation for each printed sheet.Values: default, portrait, landscape |
Scaleinteger | Print zoom, overriding the template's fit setting.Values: 10–300 |
FitToPageboolean, default false | Each sheet one page wide. |
ClearPrintAreaboolean, default false | Draws past the saved print area. |
PageRangestring | Only these pages.Values: e.g. 1 |
TransparentColorstring | This exact color becomes transparent.Values: a color name, #RRGGBB or R,G,B |
BackgroundColorstring, default white | Paper color.Values: a color name, #RRGGBB or R,G,B |
Passwordstring | Opens an encrypted template. |
FileNamestring | Stem of the image names. |
StoreFileboolean, default false | 3-hour download links in the response. |
Not supported yet
Setting one of these to anything but its default returns 400.
Refused when set: AutoFitColumns, ThousandsSeparator, DecimalSeparator, DateFormat, IncludeMetadata.
What carries over, and what doesn't
Kept
- The Estimate sheet drawn directly at 640 pixels wide, not shrunk from a larger image
- Exact pixels: the WebP is lossless (VP8L)
- Shading, borders, the gray example lines and the calculated totals
- Opaque pixels in three color channels;
TransparentColoradds an alpha channel when you need one
Lost or not yet supported
- The Rates sheet, because the request names one sheet. The hidden Notes sheet is left out even without
WorksheetName; it is drawn only when named or picked by index. - DPI: WebP has nowhere to store it.
- A lossy option.
ImageQualityhas no effect on WebP output from this route. - The template's saved date, replaced by the conversion date in its =TODAY() cell.
Limits
- One template 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 page images per request; each at most 16,000 pixels per side and 100,000,000 pixels.
- 120 seconds per conversion, then 504.
Where teams use it
Cards in a web template store
A site that offers spreadsheet templates can show a 640-pixel preview on each card. The sample's preview is 32,084 bytes.
Previews in a content library
Knowledge bases and shared drives built on web pages can show the form itself next to the download link, drawn from the file people will get.
Retina-ready images
Draw at twice the display width with ImageWidth and let the browser scale it down. Being lossless, the WebP keeps thin rules and small print sharp.
Questions
What size should I ask for?
Set ImageWidth to the width you display, or twice that for high-density screens. The page is drawn at that width, so text stays sharp: 640 gives the sample's 640 × 828 image.
How does WebP compare with PNG for a template page?
Both are lossless. For the sample template at the default 150 DPI, page 1 is about 77,000 bytes as WebP and 153,000 bytes as PNG. The exact sizes move by a few dozen bytes from day to day, because the Date cell shows the conversion day.
Can I make one preview of the whole workbook?
Not as a single image: each printed page is its own file. Send WorksheetName, WorksheetIndex or ActiveWorksheetOnly to pick the sheet that represents the template best, and PageRange=1 if that sheet runs to several pages.
Convert your first XLTX file in a minute.