Last time I wrote about compressing images in the browser with the Canvas API. I ended that post by saying the PDF version of the story was messier. It is, and one of the bugs sat in production longer than I'd like to admit.

Same constraint as before: everything runs on the user's device. No upload, no server, no API.

A PDF has no quality slider

With an image you call canvas.toBlob(resolve, 'image/jpeg', 0.7) and you're done. There's a dial, you turn it.

A PDF is a container. Fonts, vector paths, embedded images, metadata, and a cross-reference table holding it together. No single number makes it smaller. What's making a given file heavy depends entirely on what's inside it, and two documents with the same page count can need completely different treatment.