What Browser Compression Actually Saves
September 1, 2026
Every compression tool on the web says it makes files smaller. Almost none of them say how much, on what, or when it fails. We build four of these tools, and until last week we could not answer those questions about our own either.
So we measured them. Every number below came from driving the live tool in a real browser with a public test corpus — not from a spec sheet, and not from a local command-line encoder that would produce different numbers than the tool actually does.
Several results surprised us enough that we fixed the tools before publishing this article — including one bug that only shows up after you have used the tool several times in a row, which is exactly the kind of thing clicking around never finds.
How we measured it
We opened each live tool in headless Chromium, fed it real files, and read the
resulting blob back out of the page. That matters: these tools encode with the browser’s
own canvas.toBlob or with ffmpeg.wasm, so measuring with a local Python or native
encoder would give numbers the tool never produces.
Images — Kodak Lossless True Color Image Suite (24 images). The standard photographic test set used in compression research (24 PNG images, 768x512). Real photographs, not synthetic imagery.
Video — Blender open-movie trailers + Jellyfish test clip (7 clips). Publisher-encoded releases, cut to five seconds with a stream copy — we did not re-encode them, so the input bitrate is a published fact rather than a choice of ours. The same film is included at 480p, 720p and 1080p so the ratio can be read against the source bitrate.
Quality is reported as SSIM against the original (Wang et al., 2004). 1.0 is identical.
For video we used FFmpeg’s ssim filter; local FFmpeg is only ever a decoder and
measuring instrument here — every byte being measured was produced by the tool.
Two honest limits before the numbers: the video corpus is six animation clips and one live-action clip, so it under-represents camera footage; and SSIM is known to punish dithering, which matters in one section below. Raw data is linked at the end.
How much smaller does JPEG or WebP actually get?
Converting the 24 Kodak reference photos at quality 80:
| Output format | Files | Median result | Median SSIM | Lowest SSIM | Median time |
|---|---|---|---|---|---|
| PNG (lossless) | 24 | 39.6% larger | 1.0000 | 1.0000 | 2.02 s |
| JPEG quality 80 | 24 | 88.9% smaller | 0.9520 | 0.9376 | 0.18 s |
| WebP quality 80 | 24 | 91.2% smaller | 0.9558 | 0.9396 | 0.17 s |
WebP came out 91.2% smaller than the source PNG at the median, against 88.9% for JPEG, at SSIM 0.9558 versus 0.9520. On this corpus WebP won on both axes at the same quality number — smaller and closer to the original.
Either way the practical gap between them is far smaller than the gap between using a lossy format and not using one, which is the decision that actually matters.
Does re-saving a PNG make it smaller? No — it makes it bigger
The PNG row above is negative: converting these PNGs to PNG produced files
39.6% larger at the median. That is not a bug in the tool, it is what a browser does.
canvas.toBlob("image/png") is a plain, fast PNG encoder with no filter search or
palette optimisation, while the Kodak reference files have been optimised. Anything a
browser re-encodes to PNG will tend to come out bigger than an already-optimised PNG.
The practical read: PNG is a format choice, not a compression step. If you are converting to PNG to make a file smaller, that is not going to work — in any browser-based tool, ours included.
The same thing bites the default compression setting
Our image compressor defaults to Keep original format. On these PNGs that default produced 0.0% change on 24 of 24 images — byte-for-byte identical output. The tool was behaving correctly (it refuses to hand back a file bigger than the one you gave it), but it displayed a bare “0%” and left people thinking it was broken.
Switching the same files to JPEG at quality 80 gives 88.9% smaller at SSIM 0.9520. So the saving was always available; the tool just never said so.
Does converting a video to GIF reduce the file size?
Usually the opposite. Here is every clip through the GIF converter on its default settings (12 fps, 480 px wide, high-quality dithering):
| Clip | Source | Output | Size change | SSIM |
|---|---|---|---|---|
| Big Buck Bunny 1080p | 3.99 MB | 451 KB | -89.0% | 0.9893 |
| Big Buck Bunny 480p | 1.46 MB | 431 KB | -71.1% | 0.9875 |
| Big Buck Bunny 720p | 2.39 MB | 460 KB | -81.2% | 0.9872 |
| Jellyfish 720p (live action) | 1.43 MB | 2.58 MB | +80.6% | 0.9134 |
| Sintel 1080p | 1.57 MB | 255 KB | -84.2% | 0.9977 |
| Sintel 480p | 388 KB | 250 KB | -35.4% | 0.9979 |
| Sintel 720p | 747 KB | 256 KB | -65.8% | 0.9978 |
One of the 7 clips came out larger. The live-action clip went from 1.43 MB to 2.58 MB — 80.6% bigger, and took the longest of any clip to encode.
This is the single most useful thing we measured, and it is not a flaw in any particular converter: GIF has no interframe compression. H.264 stores most frames as differences from their neighbours; GIF stores whole frames from a 256-colour palette. For detailed moving footage that is simply a worse container, and no amount of tuning fixes it. GIF wins on autoplay-everywhere compatibility, never on size.
There is a second, quieter result in that table. The same film at 480p, 720p and 1080p produced GIFs within 2% of each other in size — because the output is always 480 px at 12 fps regardless of what you put in. A GIF’s size is set by your output settings and the content, not by your source resolution. Feeding the tool a bigger file does not give you a bigger GIF; it just takes longer.
Which dithering option gives the smallest GIF?
| Dithering | Files | Median result | Median SSIM | Lowest SSIM | Median time |
|---|---|---|---|---|---|
| High quality dithering (default) | 7 | 71.1% smaller | 0.9893 | 0.9134 | 1.65 s |
| “Smaller size” dithering | 7 | 81.2% smaller | 0.9466 | 0.8789 | 1.22 s |
| No dithering | 7 | 83.6% smaller | 0.9932 | 0.9192 | 1.01 s |
The option labelled “Smaller size” was never the smallest. No dithering produced a smaller file than Smaller size on 7 of 7 clips — every one — and did it faster. “Smaller size” is smaller than High quality, which is presumably what the label meant, but a reader picking from three options will not read it that way.
About the SSIM column: do not read it as a verdict. SSIM is measured against the full-colour source, and it penalises the high-frequency noise that dithering deliberately adds — a well-known limitation when evaluating dithered or halftoned images. It is fair to say no-dither files are smaller and faster; it is not fair to conclude from these numbers that they look better. Dithering trades visible noise for smoother gradients, and that trade is a judgement this metric cannot make for you.
How much does browser video compression actually save?
| Preset | Files | Median result | Median SSIM | Lowest SSIM |
|---|---|---|---|---|
| High quality (CRF 23) | 7 | 24.7% smaller | 0.9708 | 0.9628 |
| Balanced (CRF 28, default) | 7 | 64.3% smaller | 0.9676 | 0.9591 |
| Small file (CRF 32) | 7 | 78.5% smaller | 0.9609 | 0.9484 |
Read the spread, not the median. At the High quality preset the results ranged from +47.4% on Jellyfish 720p (live action) to -76.2% on Big Buck Bunny 480p — the same setting, the same tool, opposite outcomes.
| Clip | Source | Output | Size change | SSIM |
|---|---|---|---|---|
| Big Buck Bunny 1080p | 3.99 MB | 1002 KB | -75.5% | 0.9744 |
| Big Buck Bunny 480p | 1.46 MB | 356 KB | -76.2% | 0.9681 |
| Big Buck Bunny 720p | 2.39 MB | 587 KB | -76.0% | 0.9708 |
| Jellyfish 720p (live action) | 1.43 MB | 2.10 MB | +47.4% | 0.9843 |
| Sintel 1080p | 1.57 MB | 1.18 MB | -24.7% | 0.9628 |
| Sintel 480p | 388 KB | 307 KB | -20.7% | 0.9726 |
| Sintel 720p | 747 KB | 564 KB | -24.5% | 0.9670 |
The reason is that re-encoding only helps if the source was encoded less efficiently than your target. A trailer mastered at a high bitrate has slack to give up; a clip that is already near the limit has none, and re-encoding it costs quality without buying size.
The uncomfortable part is that you cannot tell which case you are in from the file’s metadata. In our corpus the clip that grew was not the lowest-bitrate one — a Sintel clip at a lower bitrate still shrank, because animation is far cheaper to encode than water and particles. Resolution, duration and bitrate together did not predict the direction.
What we changed because of these numbers
Measuring your own product is only worth it if you act on it. These shipped before this article did:
1. The compressor now tells you when it cannot help. When compression yields no saving in the current format, the tool encodes that exact file to JPEG and reports the real number — “Cannot be made smaller in this format. JPEG: 102.5 KB (86% smaller)” — with a one-click convert button. That is the message our first reference photo now produces; the figure is measured on your own file rather than averaged from ours.
2. Videos with an odd width or height no longer fail silently. x264 refuses dimensions
that are not divisible by two, and a very common 480p rendition is 853 px wide. The encoder
never started, ffmpeg.wasm returned an empty file rather than raising an error, and the
tool cheerfully offered a 0-byte MP4 for download. We only found it because a corpus clip
happened to hit it. The tool now crops to even dimensions, and both video tools now refuse
to hand you an empty file instead of calling it a success.
3. We removed our own size estimate, because it was wrong. The compressor used to predict an output size before you pressed the button. Against these measurements it was off by up to 69 percentage points: at High quality (CRF 23) on one clip it promised 6% smaller and delivered 75.5%. It had been calibrated on hard live-action footage, so it under-promised on everything else — telling people a file would barely shrink when it was about to shrink by three quarters. Since the direction is not predictable from metadata, the honest fix was not a better constant. The tool now shows the measured range for the preset you picked and says plainly that the result depends on your video.
4. A failed compression no longer poisons the whole page. This was the worst of the four, and the benchmark is the only reason we know about it: once one encode failed, every later attempt on that page failed too — sixteen in a row in our run — because the engine was cached after it had already died, and nothing suggested reloading. Both video tools now throw away a dead engine and start a fresh one on the next attempt.
The raw data
Every measurement behind this article, including per-file rows:
image-compress— measured 2026-09-01image-convert— measured 2026-09-01video-to-gif— measured 2026-09-01video-compress— measured 2026-09-01
The corpora are public. Images are the Kodak Lossless True Color Image Suite; video clips are Blender Foundation open-movie trailers (CC-BY) and a Jellyfish test clip, cut to five seconds with a stream copy so the bitrate is the publisher’s and not ours. If you repeat this and get different numbers, we would like to know.
Want to know the moment our next game is playable? Get launch updates →