How to compress a PDF via API (Python and Node.js)
Large PDFs slow down uploads, blow past email limits, and cost you storage. This guide shows how to shrink a PDF from your own code with a single HTTP request, with copy-paste examples in curl, Python, and Node.js.
Why compress PDFs in code
Doing it by hand in a desktop app does not scale. When your app accepts PDF uploads, generates reports, or emails invoices, you want compression to happen automatically in your backend. A small API call keeps your code simple and your files small, without bundling a heavy PDF engine into your own service.
FileAlloy exposes a single endpoint for this: POST /v1/compress. It takes a PDF and returns a smaller one. Files are processed in memory and deleted the moment the response is sent, so nothing is stored.
Step 1: Get an API key
Create a free account at app.filealloy.com and generate a key. You pass it in the X-API-Key header on every request. The free plan is enough to test and build.
Step 2: A quick test with curl
Before writing any code, confirm it works from your terminal:
curl -X POST https://api.filealloy.com/v1/compress \
-H "X-API-Key: fa_live_your_key" \
-F "[email protected]" \
-F "level=medium" \
-o compressed.pdf You now have a compressed.pdf next to your input. The level field is optional and controls the quality/size trade-off (more on that below).
Step 3: Compress a PDF in Python
Using the requests library, send the file as multipart form data and write the response bytes to disk:
import requests
with open("input.pdf", "rb") as f:
resp = requests.post(
"https://api.filealloy.com/v1/compress",
headers={"X-API-Key": "fa_live_your_key"},
files={"file": ("input.pdf", f, "application/pdf")},
data={"level": "medium"},
)
resp.raise_for_status()
with open("compressed.pdf", "wb") as out:
out.write(resp.content)
print("Saved", len(resp.content), "bytes") Step 4: Compress a PDF in Node.js
Node 18+ ships with fetch, FormData, and Blob built in, so there are no dependencies to install:
import { readFile, writeFile } from "node:fs/promises";
const bytes = await readFile("input.pdf");
const form = new FormData();
form.append("file", new Blob([bytes], { type: "application/pdf" }), "input.pdf");
form.append("level", "medium");
const res = await fetch("https://api.filealloy.com/v1/compress", {
method: "POST",
headers: { "X-API-Key": "fa_live_your_key" },
body: form,
});
if (!res.ok) throw new Error(`Compress failed: ${res.status}`);
const out = Buffer.from(await res.arrayBuffer());
await writeFile("compressed.pdf", out);
console.log("Saved", out.length, "bytes"); Choosing a compression level
The optional level field trades size against quality:
low- smallest file (images down to 72dpi). Best for on-screen viewing and email.medium- balanced (150dpi). A good default for most documents.high- best quality (300dpi). Use when the PDF will be printed.
How much you save depends on the content. Image-heavy PDFs and scans shrink the most; a text-only PDF is already small, so expect modest gains.
Handling errors and quotas
The API returns standard HTTP status codes. A 401 means the key is missing or wrong, a 400 means the input was not a valid PDF, and a 429 means you hit your plan's monthly quota. Each response also carries X-Quota-Limit and X-Quota-Used headers so you can track usage. Always check the status before writing the output, as both examples above do.
Wrapping up
That is the whole thing: one endpoint, one call, a smaller PDF back. Because the operation is deterministic and stateless, you can run it in parallel across a batch, and because files are never stored, it is safe for sensitive documents. Try the same pattern with the other operations, converting to Word, running OCR, or merging, they all follow the identical shape.