Most image compression tools upload your file to a server, which is slow and not always safe. I wanted something faster, simpler, and privacy-friendly — so I built a client-side MB to KB image compressor using only HTML, JavaScript, and the Canvas API.
This tool runs 100% in the browser, compresses images instantly, and never uploads anything to a server.
Live tool: https://mbtokbconverter.org/
💡 Why I Built This:
Many people struggle when they need to reduce image size — photo too big, website upload limit too small.
I kept hearing:
- “My photo is 4 MB but I need 200 KB”
- “Online compressors are slow”
- “Why does it upload my file to a server?”
*So I created a simple JS tool that:
*
- Compresses to a target size (KB)
- Works offline
- Doesn’t upload your image
- Converts PNG → JPEG for better compression
- Lets you resize images for better results
🔧 How It Works (High-Level)
- Load the image using FileReader
- Convert to a
<canvas> - Optionally resize width
- Run a binary search on JPEG quality until size ≤ target
- Generate a blob
- Provide a download link
Everything happens inside the browser.
📌 Core Code Snippets**
Read Image
function readFileAsDataURL(file){
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
Draw to Canvas
function loadImage(src){
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
Compression Logic (Binary Search)
async function compress(img, targetKB, maxWidth){
const canvas = document.createElement("canvas");
let w = img.width;
let h = img.height;
if(maxWidth > 0 && maxWidth < w){
h = Math.round(h * (maxWidth / w));
w = maxWidth;
}
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, w, h);
let low = 0.05;
let high = 0.95;
let best = null;
const targetBytes = targetKB * 1024;
for(let i=0; i<10; i++){
const q = (low + high) / 2;
const blob = await new Promise(res => canvas.toBlob(res, "image/jpeg", q));
if(blob.size <= targetBytes){
best = blob;
low = q;
} else {
high = q;
}
}
return best;
}
🖥 Demo UI (HTML)
<input type="file" id="file" accept="image/*">
<input type="number" id="targetKb" value="100">
<input type="number" id="maxWidth" value="0">
<button id="compressBtn">Compress</button>
<button id="downloadBtn" disabled>Download</button>
✔️ What I Learned
- PNGs do not compress well → converting to JPEG helps
- Some images need dimension resizing to reach very small sizes
- Canvas compression varies between browsers
- A binary-search approach is the fastest method
🔮 What’s Next?
I’m adding:
- WebP output
- Drag & drop support
- Batch compression
- Dark mode UI
If you want these features, tell me!

Top comments (0)