Compress images, PDFs, video, audio and GIFs entirely in your browser — hardware-accelerated where available. Zero uploads, zero tracking. Your files stay on your device — always.
Choose a format to get started. Everything runs locally in your browser.
Privacy first. All compression runs locally in your browser. Files are never uploaded to any server. Video, audio, and GIF compression loads FFmpeg.wasm (~30 MB) from CDN on first use — cached by your browser after that.
Compressly is a 100% client-side compression tool built with TypeScript and Vite. Your files never leave your device. All processing uses WebAssembly, the Canvas API, and modern Web platform APIs.
Compiled Rust/C FFmpeg to WebAssembly. Handles video (H.264/H.265/VP9/AV1), audio (MP3/AAC/Opus/OGG/FLAC/WAV), and GIF compression with full codec support. Multithreaded when SharedArrayBuffer is available.
OffscreenCanvas + ImageBitmap for hardware-accelerated image decoding and encoding. WebP and AVIF are natively encoded by the browser's own codec (GPU path in Chrome).
PDF.js 4.4 renders each page to a canvas at configurable DPI. pdf-lib 1.17 repackages the re-compressed images into a new PDF document. Pure JavaScript, no WASM, no server needed.
W3C API for hardware-accelerated video encode/decode. Used as the GPU tier-2 fallback when FFmpeg.wasm is unavailable. Supported in Chrome 94+ and Safari 16.4+.
The project is a standard Vite app with strict TypeScript. No framework — pure DOM manipulation with typed components. Deploys to Cloudflare Pages in seconds.
Zero-dependency TypeScript SVG optimiser. Strips XML declarations, comments, metadata, Inkscape/Sodipodi namespaces, empty groups, compacts path data, and rounds coordinates.
Compressly has no backend. No files are uploaded anywhere. All processing happens on your device using local compute. You can verify this by watching your Network tab — no file data ever leaves the browser.
Images are decoded via createImageBitmap() then re-encoded to JPEG/WebP/AVIF/PNG via OffscreenCanvas.convertToBlob(). A 14-iteration binary search hits exact target sizes. AVIF automatically falls back to WebP on Firefox.
Each PDF page is rendered at a configurable scale using PDF.js, then re-embedded as a compressed JPEG via pdf-lib. Three presets (Low/Recommended/Extreme) control quality and render scale. A target-size mode binary-searches per-page JPEG quality across 12 iterations.
Three-tier fallback: (1) FFmpeg.wasm with multithreading when SharedArrayBuffer is available (requires COOP/COEP headers — set automatically on Cloudflare Pages via _headers), (2) WebCodecs API for GPU-accelerated H.264 on Chrome/Safari, (3) MediaRecorder canvas capture as universal fallback.
FFmpeg.wasm handles all audio formats: MP3 (libmp3lame), AAC, Vorbis OGG, Opus (VBR mode 10 — best quality-per-bit codec), FLAC level 8, and WAV PCM. Custom bitrate and sample rate controls. Can also extract audio from video containers.
Two-pass palettegen (up to 256 colours with stats_mode=diff) + paletteuse with Bayer dithering and diff_mode=rectangle — the gold-standard GIF compression pipeline used by professional tools. Alternatively converts to WebM VP9 for 70–95% size reduction.
Technical reference for Compressly's compression options and browser compatibility.
format — Output format: image/webp (default), image/jpeg, image/png, image/avifquality — 0.01–0.99. Ignored for PNG (always lossless). Default: WebP 0.82, JPEG 0.85, AVIF 0.70.maxWidth / maxHeight — Downscale if either dimension exceeds the limit (aspect ratio preserved, lanczos).targetSizeKB — Binary-search quality over 14 iterations to hit this file size. Ignores quality.pdfCompressionLevel
low — quality 0.85, scale 2.0 (high DPI, minimal loss)recommended — quality 0.60, scale 1.5 (best balance)extreme — quality 0.30, scale 1.0 (maximum compression)pdfRenderScale — DPI multiplier (1.0–3.0). Higher = better quality and larger output.pdfImageFormat — image/jpeg (default, smaller) or image/png (lossless pages).targetSizeKB — Binary-searches per-page JPEG quality to approximate target total size.videoCodec — h264 (default), h265, vp9, vp8, av1quality — 0–1 maps to CRF 18–35 for H.264/H.265; VP9/AV1 use equivalent CRF with -b:v 0.videoBitrate — Target bitrate in bps (used in bitrate mode).targetSizeKB — Calculates bitrate as (size × 8) / duration and applies it as max bitrate.fps — Output framerate. 0 = preserve source FPS.maxWidth — Scale down keeping aspect ratio (lanczos). Height auto-calculated.videoPreset — ultrafast / fast (default) / medium / slowaudioFormat — mp3, aac, ogg, opus, flac, wavaudioBitrate — kbps. Defaults: mp3→192, aac→160, ogg→128, opus→96. Ignored for FLAC/WAV.audioSampleRate — e.g. 44100, 48000. 0 = preserve source rate.stripMetadata — Removes ID3/tags/cover art from output (-map_metadata -1).gifToVideo — Convert to WebM VP9 instead of re-optimising as GIF. Dramatic size savings.quality — 0–1 controls palette size (16–256 colours). Default 0.82 = 213 colours.maxWidth — Lanczos resize applied before palette generation.fps — Target framerate (decimation via FFmpeg fps filter).The project deploys to Cloudflare Pages automatically via GitHub Actions. The public/_headers file sets the required COOP/COEP headers for SharedArrayBuffer (FFmpeg multithreading).
npm run builddist_headers on Cloudflare Pages).