Bun.Image for Blazing Fast, Zero-Install Image Processing

If you’ve ever built a web application that handles user uploads, you know the drill. You need to resize an avatar, generate a thumbnail, or convert a massive JPEG into a modern WebP format. For years, the undisputed king of this domain in the Node.js ecosystem has been sharp.
But sharp comes with a catch: heavy native module installs, platform-specific binaries, and occasional compilation headaches.
Bun is changing the game again. With its latest release, Bun now ships with Bun.Image—a built-in, chainable image processing API that handles JPEG, PNG, WebP, GIF, and BMP out of the box with zero native module installs.
Let’s dive into what makes Bun.Image a drop-in, ultra-fast alternative for server-side image operations.
The Power of Zero-Install Chains
Bun.Image provides a beautiful, fluent API for decoding, transforming, and encoding images. Because it’s built directly into the runtime, it requires no external dependencies.
Here is how simple it is to resize, rotate, and convert a photo to WebP:
await Bun.file("photo.jpg")
.image()
.resize(1024, 1024, { fit: "inside" })
.rotate(90)
.webp({ quality: 85 })
.write("thumb.webp");
Complete HTTP Request/Response Integration
One of Bun's coolest features is how deeply integrated Bun.Image is with the web platform. You can pass a Bun.Image instance directly into a standard web Response. Bun will handle the processing and automatically set the correct Content-Type header.
Here is a complete example of an HTTP server that generates a 200x200 JPEG thumbnail on the fly from an uploaded image:
Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
if (req.method === "POST" && url.pathname === "/thumbnail") {
const formData = await req.formData();
const upload = formData.get("image");
if (upload instanceof File) {
// Generate a thumbnail and stream it directly back to the client
return new Response(
new Bun.Image(upload).resize(200, 200, { fit: "cover" }).jpeg()
);
}
}
return new Response("Send a POST request with an 'image' file.", { status: 400 });
},
});
Inputs, Transforms, and Outputs
Bun.Image is incredibly flexible with what it accepts and how it outputs data.
Flexible Input Sources
You don’t have to worry about converting formats before feeding them to the pipeline. It natively accepts:
File path strings ("path/to/image.jpg")
ArrayBuffer / TypedArray (using zero-copy memory allocation)
Blob, BunFile, and S3File
data: URLs
Powerful Transforms
The chainable pipeline gives you granular control over your assets:
Geometry: .resize(w, h?, {filter, fit, withoutEnlargement}), .rotate(90|180|270), .flip(), and .flop().
Color: .modulate({brightness, saturation}).
Advanced Filters: All standard sharp filters are supported, including nearest, bilinear, cubic, lanczos3, and the ultra-modern mks2021.
Asynchronous Terminal Methods
Except for .metadata(), all image processing runs entirely off the main thread, keeping your server responsive. You can output your final image using:
.bytes(), .buffer(), or .blob()
.toBase64() or .dataurl()
.write(dest) (saves directly to disk)
Example: Generating Blur-Up Placeholders & Metadata
Modern UI patterns require displaying a tiny, blurred placeholder while a large image loads. Bun.Image makes this a one-liner using Thumbhash.
// 1. Grab image metadata
const meta = await new Bun.Image("hero.jpg").metadata();
console.log(`Dimensions: \({meta.width}x\){meta.height}, Format: ${meta.format}`);
// 2. Generate a blur-up thumbhash data URL
const placeholderUrl = await Bun.file("hero.jpg")
.image()
.placeholder(); // Returns a tiny thumbhash data URL
Platform Support Matrix
To keep binary sizes small, Bun handles core web formats identically across all platforms using statically linked codecs. For heavier, ecosystem-specific formats (like HEIC and AVIF), it lazily resolves native OS system backends (like Apple's ImageIO or Windows WIC) for zero startup cost.
With Bun.Image, the Bun team has eliminated one of the last major reasons developers had to rely on complex external C++ bindings for simple server side tasks. It’s fast, incredibly lightweight on developer workflows, and fits perfectly into standard Web APIs.
Give it a spin in your next Bun project! Turn on your servers, drop sharp, and start chaining.



