Skip to main content

Image Compressor — Reduce JPG, PNG & WebP File Size

Drop in a JPG, PNG, or WebP and cut its file size by 50-90% with a quality slider and optional max-width downscale. See the before/after byte comparison, preview the result, and download in one click. Free and 100% client-side — your image never leaves the browser.

Drop an image to compress

JPG, PNG, WebP, or GIF · processed locally

Quality + Downscale

Fine-grained quality slider (1-100) plus optional max-width downscale. Combined they typically achieve 70-90% file-size reduction at imperceptible visual cost.

JPEG, WebP, PNG

Convert to JPEG (best for photos), WebP (~25-35% smaller than JPEG), or PNG (lossless — quality slider has no effect; use for graphics).

Live Before/After

See original vs compressed file size and percentage saved in real time as you adjust settings. Tune compression until the trade-off looks right.

100% Client-Side

All compression happens via the Canvas API in your browser. No uploads, no signup. Works offline once the page is loaded.

Image Compressor: Shrink JPG, PNG & WebP in Your Browser

An image compressor re-encodes a picture at lower quality or smaller dimensions so the file weighs less. This one decodes your JPG, PNG, or WebP onto an HTML Canvas, then re-encodes it with canvas.toBlob() at the quality and max-width you choose, showing a live before/after byte comparison before you download. It runs 100% in your browser — free, with no upload.

How to compress an image

  1. Drag an image onto the drop zone, or click to pick a JPG, PNG, WebP, GIF, or AVIF file.
  2. Choose an output format: JPEG for photos, WebP for the smallest modern files, or PNG to stay lossless.
  3. Set quality with the slider (1–100) or a preset — High 92, Balanced 75, Compact 50, or Tiny 30. The slider has no effect on PNG.
  4. Optionally drag max-width down to shrink the pixel dimensions; aspect ratio is preserved and the image is never upscaled.
  5. Read the before/after file size and percent saved, compare the side-by-side preview, then click Download to save the result.

How browser image compression actually works

Your browser decodes the source image, paints it onto a <canvas>, and re-encodes the pixels with canvas.toBlob(type, quality) — the same native encoder that backs "Save for Web" exports. The quality argument is a number from 0 to 1 that only applies to lossy formats. As the MDN HTMLCanvasElement.toBlob() reference states, the quality value is used "if the requested type is image/jpeg or image/webp. If this argument is anything else, the default value for image quality is used." That is why this tool's slider does nothing for PNG — PNG is lossless, so the only lever left is dimension.

"A good Largest Contentful Paint score is 2.5 seconds or less" for at least 75% of page visits.web.dev, Largest Contentful Paint (LCP). On most pages the LCP element is an image, so a heavy hero file is the fastest way to blow that budget.

Two lossy formats use distinct math. JPEG splits the image into 8×8 blocks and applies a discrete cosine transform (DCT), discarding high-frequency detail the eye barely notices. WebP uses VP8-based intra-frame prediction borrowed from video coding, which models smooth gradients and textures more efficiently — typically 25–35% smaller than JPEG at matching quality, with alpha transparency on top. PNG, by contrast, is always lossless: it stores every pixel exactly, so it is right for screenshots, logos, and text but oversized for photographs.

Worked examples: input → output

3.2 MB photo (4000px) · JPEG · quality 75 · max-width 1600

Downscaling to 1600px then re-encoding at 75% usually lands near 180–320 KB — roughly a 90% reduction with no artefacts visible at the display size.

Same photo · WebP · quality 75 · max-width 1600

WebP at the same settings typically comes out 25–35% smaller than the JPEG above — often around 120–220 KB — for visually identical output.

UI screenshot with text · PNG · max-width 1280

Keep PNG so text edges stay crisp. The quality slider is inert; shrinking max-width is the only way to cut bytes here. Converting to JPEG would blur the text.

Edge case · transparent PNG → JPEG

JPEG has no alpha channel, so this tool fills the canvas white before drawing (ctx.fillStyle = '#ffffff') — transparent areas become white, not black, which is the usual failure of naive Canvas exports. If you need to keep transparency, output WebP or PNG instead.

Image Format Comparison (2026)

FormatBest ForTransparencyLosslessTypical Size
JPEGPhotographs, complex gradients, real-world imageryNoNoBaseline (1.0×)
WebP (lossy)Modern websites — replaces JPEG for photos and PNG for graphicsYes (alpha)Yes (separate mode)~0.70× of JPEG at same visual quality
AVIFNext-gen photo compression; supported in modern browsersYes (alpha)Yes~0.50× of JPEG; slower to encode
PNGScreenshots, logos, line art, images needing transparencyYes (alpha)Always lossless5-10× of JPEG for photographs

Default recommendation for new web content in 2026: WebP for photos and graphics, with PNG fallback only for very small icons where the format header would dominate.

How to Pick the Right Quality Level

Quality RangeVisual Impact & Best Use
95-100Nearly indistinguishable from source. Use when you cannot afford any visible artefacts.
85-94Default for high-quality web photos. Artefacts only visible in side-by-side comparison.
70-84Web standard for body images. Some artefacts visible in solid color areas; usually invisible at normal viewing.
50-69Thumbnails, hero backgrounds, low-stakes images. Compression artefacts become noticeable.
0-49Aggressive — use only for very small thumbnails or when bandwidth is critical. Artefacts are obvious.

Always preview the compressed output at the target display size, not zoomed in — artefacts that are visible at 200% zoom may be invisible at the actual delivery resolution.

The white-fill trap most Canvas compressors miss

When you convert a transparent PNG to JPEG, JPEG cannot store an alpha channel, so the transparent pixels need a backing color. A naive Canvas export leaves them black. This tool paints the canvas white first (ctx.fillStyle = '#ffffff'; ctx.fillRect(...)) before drawing the image, so a logo on a transparent background lands on clean white rather than an ugly black box. If you need to keep transparency, choose WebP or PNG instead.

Two more behaviors worth knowing: the max-width slider only downscales — if you set a width larger than the source, the image stays at its native size (scale = maxWidth < naturalW ? ... : 1), so it never upscales and blurs. And every download is auto-named <original>-compressed.<ext>, so you never clobber your source file.

When and how to compress for web performance

Compress before you worry about quality: resize first. A 4000px photo shown at 800px is roughly 5× too large, so downscale to about 2× the maximum display width (for retina) using the max-width slider, then tune quality. For responsive layouts, export 1×, 2×, and 3× versions and let the browser pick with srcset rather than shipping one giant file to phones. Add loading="lazy" to every <img> below the fold so it does not block first paint, and let the heaviest above-the-fold image stay eager so it can win the LCP race.

Runs 100% in your browser

Your image never leaves your device. Reading, decoding, re-encoding, and downloading all happen locally via the Canvas API and Blob URLs — no uploads, nothing leaves your device — so the tool keeps working offline once the page loads. I tested it on JPG, PNG, and WebP sources from tiny 12 KB icons up to multi-megapixel photos, across every quality preset and a deep max-width downscale, and confirmed in DevTools → Network that no request carries the image. Re-encoding also drops all EXIF (camera make, GPS, timestamps), which is a quiet privacy win when you share the result.

Frequently asked questions

Is this image compressor free?

Yes — 100% free with no signup and no usage cap. Compress as many images as you like, one at a time, and download every result. There is no account.

Are my images uploaded to a server?

No. The entire pipeline — read, decode, re-encode, download — runs in your browser tab via the Canvas API and Blob URLs. No fetch or XHR carries image data, no analytics event ships file bytes, no cookie stores an image ID. The image lives only in the current tab's memory and is cleared on refresh, so sensitive medical, personal, or internal images stay private.

How does the image compressor work?

Your browser decodes the image, draws it onto an HTML Canvas, then re-encodes it with canvas.toBlob(type, quality) — the native browser image encoder. That Blob becomes the download. Everything is local: no server processing. Verify it yourself by opening DevTools, the Network tab, then compressing an image — zero requests fire.

Why is the quality slider greyed out for PNG?

Because PNG is lossless, the quality argument to canvas.toBlob is ignored for image/png — only image/jpeg and image/webp honor it, per the WHATWG HTML spec. For PNG, the only way to cut bytes is to shrink the pixel dimensions, so use the max-width downscale slider instead of quality. For photos, switch the output to JPEG or WebP to get real lossy savings.

Why does WebP compress better than JPEG?

WebP uses VP8-based intra-frame coding adapted from video compression, which handles smooth gradients and textures more efficiently than JPEG's DCT approach. At the same visual quality, WebP files are typically 25-35% smaller than JPEG and also support alpha transparency, so WebP can replace PNG for transparent graphics at a fraction of the size. Every major browser supports WebP natively in 2026.

Will my photo look worse at 75% quality?

Usually not. At 75% JPEG quality the difference from the source is typically imperceptible at normal viewing distance, even side by side. Artefacts appear at 50% and below, mostly in flat-color regions and around sharp edges. Use 75-85% for body images and 92% for hero images you expect people to inspect closely. The PNG slider does nothing because PNG is lossless.

Why is my compressed file LARGER than the original?

Re-encoding an already-compressed image can add bytes instead of removing them. Common causes: the source was already a low-quality JPEG you re-saved at higher quality; you converted a small PNG to JPEG above its effective quality; or the file was already tiny (under ~50 KB) where format overhead dominates. Start from the highest-quality original you have, or lower the quality slider until you see savings.

Does this strip EXIF metadata from my photos?

Yes. The Canvas API does not preserve EXIF when re-encoding, so the output keeps only pixel data — no camera make and model, GPS coordinates, timestamps, or custom tags. That is a privacy win when posting photos online. If you must keep EXIF (for asset-management systems that index by camera), use a tool with metadata pass-through such as mozjpeg --copy-all or ImageMagick without -strip.

Can I compress images in bulk?

Not here — this tool processes one image at a time to keep the byte comparison precise and the UI simple. For dozens or hundreds of files, use a CLI such as ImageMagick, mozjpeg, or sharp via a Node.js script. The same Canvas-to-Blob pipeline can be looped programmatically if you want to replicate this exact algorithm.

Why is there no AVIF output option?

Because canvas.toBlob does not emit AVIF in most browsers as of 2026, so this tool outputs JPEG, WebP, and PNG only. AVIF is typically 30-50% smaller than WebP at the same quality with full alpha and HDR support, and browser decoding is now universal. To encode AVIF, use an external tool like squoosh.app, avif.io, or the avifenc CLI.

Last updated: June 2, 2026 · Runs 100% in your browser — no uploads, nothing leaves your device.

Need a different tool?

Browse all 89 free, in-browser tools — or tell us what we should build next.

Browse all tools