How Browsers Compress Images (Canvas API Explained)
Every browser has a built-in image encoder. When tools like MiniPx compress your photos without a server, they are using the Canvas API's toBlob() and toDataURL() methods. Here is exactly how that works.
The Canvas pipeline
Browser-based compression follows a simple pipeline: decode the source image into raw pixel data, draw those pixels onto a Canvas, then re-encode the canvas contents into a compressed format.
The decode step happens when you set an Image element's src. The browser reads the file (JPEG, PNG, WebP, whatever) and converts it into an uncompressed bitmap in memory. The encode step happens when you call toBlob() or toDataURL() โ the browser runs its built-in encoder to produce a new compressed file.
toBlob() โ the main compression method
The toBlob() method is where compression actually happens. It takes three arguments:
canvas.toBlob( callback, // function that receives the Blob mimeType, // "image/jpeg", "image/webp", or "image/png" quality // 0 to 1 (only for JPEG and WebP) );
The quality parameter is the key control. At 1.0, you get maximum quality with minimal compression. At 0.1, you get aggressive compression with visible artifacts. The sweet spot for most photos is 0.7 to 0.85.
Quality parameter deep dive
The quality value maps to the internal quantization tables used by the JPEG encoder. Here is how different values affect a typical 3 MB photo:
The relationship between quality and file size is not linear. Dropping from 0.95 to 0.85 saves a lot of space with almost no visible difference. Dropping from 0.40 to 0.20 saves much less space but introduces very visible degradation.
Format differences in toBlob()
JPEG (image/jpeg)
JPEG is lossy and works best for photographs. The quality parameter works as expected. One catch: JPEG does not support transparency. If your canvas has transparent areas, they will be filled with black in the JPEG output.
WebP (image/webp)
WebP supports both lossy and lossless compression. With a quality parameter, it behaves like JPEG but produces 25-35% smaller files. WebP also supports transparency, making it a good all-around format.
PNG (image/png)
PNG is always lossless in the Canvas API. The quality parameter is ignored. PNG files from the Canvas API tend to be larger than optimized PNGs because the browser uses basic deflate compression without advanced techniques like color quantization.
Browser differences matter
Different browsers use different encoder implementations. Chrome uses libjpeg-turbo for JPEG and libwebp for WebP. Firefox has its own implementations. Safari uses Apple's native image frameworks.
In my tests, the same image at quality 0.8 produced a 487 KB file in Chrome, 512 KB in Firefox, and 495 KB in Safari. The visual quality was comparable across all three, but Chrome's output was consistently a few percent smaller.
OffscreenCanvas for background processing
Regular canvas operations block the main thread. For large images or batch processing, OffscreenCanvas lets you run compression in a Web Worker.
// In your Web Worker:
self.onmessage = async (e) => {
const { imageBitmap, quality } = e.data;
const canvas = new OffscreenCanvas(
imageBitmap.width,
imageBitmap.height
);
const ctx = canvas.getContext('2d');
ctx.drawImage(imageBitmap, 0, 0);
const blob = await canvas.convertToBlob({
type: 'image/jpeg',
quality: quality
});
self.postMessage({ blob });
};Note the API difference: OffscreenCanvas uses convertToBlob() (which returns a Promise) instead of toBlob() (which uses a callback). This is how MiniPx keeps the interface responsive during batch compression.
Limitations and workarounds
Canvas size limits. Most browsers cap canvas dimensions at 16,384 x 16,384 pixels. Some mobile browsers have lower limits. If an image exceeds this, you will need to downscale it before drawing to the canvas.
No EXIF preservation. The Canvas API strips all metadata. This is good for privacy but means you lose orientation data. Always apply EXIF orientation before drawing to the canvas, or your rotated photos will appear sideways.
Color space issues. Canvas works in sRGB by default. If your source image uses a different color space (like Adobe RGB or Display P3), colors may shift during compression. For most web images, this is not a problem.
Frequently asked questions
Related tools
Compress, convert, and resize images in your browser. Nothing gets uploaded.
Open MiniPx โ