TIFF to WebP API
POST a TIFF to /v2/convert/tiff/to/webp and get a lossless WebP of the first page, with every pixel kept. Resize it with ImageWidth, make it gray, or key out a background color; lossy WebP is not available.
- Endpoint
- POST /v2/
convert/ tiff/ to/ webp - Accepts
- tiff
- Sample timing
- 2 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/tiff/to/webp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@bin-label-c14.tiff \
-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/tiff/to/webp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("bin-label-c14.tiff", "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 = "bin-label-c14.tiff";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/tiff/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.002,
"Files": [
{
"FileName": "bin-label-c14.webp",
"FileExt": "webp",
"FileSize": 20700,
"FileData": "UklGRtRQAABXRUJQVlA4TMhQ…"
}
]
}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
- bin-label-c14.tiff (42 KB)
- Output
- bin-label-c14.webp (20 KB)
- Source
- A two-page warehouse bin label and cycle-count sheet we drew for this page, saved as an LZW-compressed TIFF at 200 dpi. (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 in pixels; 200 gave a 200 × 150 WebP of 18,558 bytes.Values: 1–20000 |
ImageHeightinteger | Height in pixels, or the second side of a fitting box.Values: 1–20000 |
ScaleProportionsboolean, default true | false lets the page stretch to fill the requested box. |
ScaleIfLargerboolean, default false | true only shrinks, so small scans are never enlarged. |
ScaleImageboolean, default true | false crops the box from the top-left corner instead of scaling. |
ColorSpaceenum, default default | gray halved the label to 10,326 bytes; monochrome reduces it to black and white. cmyk returns 400.Values: default, rgb, gray, monochrome |
TransparentColorstring | One exact color becomes transparent; #FCFBF7 removed the label's paper and gave 22,140 bytes.Values: Color name, #RRGGBB or R,G,B |
ImageResolutioninteger | Validated and ignored: the WebP we write carries no resolution.Values: 10–800 |
ImageInterpolationboolean, default false | Accepted either way; resizing is always Lanczos. |
FileNamestring | Name for the WebP; bin-label-c14.webp for the sample. |
StoreFileboolean, default false | true returns a link valid for 3 hours instead of base64 data. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
ImageQuality | Only lossless WebP is written. 75, ConvertAPI's default, is accepted; other values return 400 'ImageQuality is not supported yet for TIFF → WebP'. |
What carries over, and what doesn't
Kept
- Every pixel of page 1: the WebP decodes to exactly the TIFF page's RGB values.
- Size savings on flat artwork: 20,700 bytes, against 31,866 for a PNG of the same page.
- Sharp text and the QR code, since nothing is lossy-compressed.
- The Orientation tag, applied to the pixels: a 300 × 200 TIFF tagged 6 became an upright 200 × 300 WebP.
- An opaque page as plain RGB: the label's WebP has no alpha channel, while a TIFF with transparency keeps its alpha values.
Lost or not yet supported
- Pages after the first. The count sheet on page 2 is dropped.
- The 200 dpi value and any ICC profile from the TIFF.
- Bit depth: 16-bit TIFFs are reduced to 8 bits per channel.
- Lossy compression: there is no quality setting to trade detail for a smaller file.
Limits
- One TIFF per request.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- 100,000,000 pixels per page, checked before decoding.
- WebP sides of at most 16,384 px: a 16,385 × 20 TIFF returned 413 'WebP images can be at most 16,384 pixels on a side, and this one is 16,385×20', and converted with
ImageWidth=16384. - Palette TIFFs return 422.
- A conversion is stopped after 120 seconds with a 504.
Where teams use it
Scans and diagrams on web pages
Put scanned drawings, forms or labels on a site without a lossy step. For flat graphics like the sample, lossless WebP was smaller than both the LZW TIFF and a PNG of the same page.
Lighter storage for image previews
Keep the TIFF as the master and store a WebP for viewers and apps. Every pixel of the page survives, so the preview can be zoomed without JPEG artifacts.
Questions
Is the WebP lossy or lossless?
Always lossless (VP8L). The sample WebP decodes to the same pixels as the TIFF page. ImageQuality can't switch to lossy mode: any value other than 75 returns 400.
How much smaller is it than the TIFF?
It depends on the content. The sample label, flat colors and text, went from 42,928 bytes of two-page LZW TIFF to 20,700 bytes for page 1, and a PNG of that page was 31,866 bytes.
What happens to the other pages?
They are skipped. The response contains one WebP of page 1 and the status is 200, so check the page count yourself if it matters.
Does the WebP keep the scan's DPI?
No. ImageResolution is accepted but there is nowhere to put it in the WebP we write, so the output is the same with or without it.
Convert your first TIFF file in a minute.