Skip to main content

Sharp vs Jimp vs Squoosh: Node.js Image Processing 2026

·PkgPulse Team

Sharp processes images 25x faster than squoosh-cli in benchmarks. squoosh-cli is 6x faster than jimp. But speed isn't the only dimension: Squoosh (Google's image codec project) focuses on modern codecs (WebP, AVIF, JXL), jimp is pure JavaScript with zero native dependencies, and sharp is the production workhorse used by Next.js's image optimization pipeline. For Node.js image processing in 2026, the choice depends on whether you need codec flexibility, zero native dependencies, or maximum throughput.

TL;DR

Sharp for production image processing pipelines — 9M+ weekly downloads, 25x faster than alternatives, used by Next.js next/image, native libvips with prebuilt binaries for all platforms. Jimp when you can't use native binaries (serverless environments with size limits, edge-adjacent runtimes, or zero-dependency requirements) — pure JavaScript, works anywhere. Squoosh (@squoosh/lib) when you need cutting-edge codec control — WebP, AVIF, JXL, and OxiPNG encoding with Wasm codecs that mirror what the Google Squoosh web app uses. For most production use cases, sharp is the obvious choice.

Key Takeaways

  • Sharp: 9M+ weekly downloads, libvips (C library), 25x faster than squoosh, supports JPEG/PNG/WebP/AVIF/TIFF/GIF
  • Jimp: 1.5M weekly downloads, pure JavaScript (no native deps), slower but universally compatible, JPEG/PNG/BMP/GIF
  • Squoosh (@squoosh/lib): Google's codec project, WebAssembly codecs, best WebP/AVIF encoding quality control
  • Next.js: Uses sharp for its next/image automatic optimization (AVIF and WebP conversion)
  • Sharp benchmarks: 4-40x faster than jimp, 25x faster than squoosh-cli for resize operations
  • Format support: Sharp supports WebP and AVIF natively; Jimp lacks WebP/AVIF in core; Squoosh is codec-focused

Sharp

Package: sharp Weekly downloads: 9M+ GitHub stars: 29K Creator: Lovell Fuller

Sharp is built on libvips — a C library designed for fast, low-memory image processing. It's the standard for any Node.js application that needs to process images at scale.

Installation

npm install sharp
# Prebuilt native binaries for macOS, Windows, Linux (x64/arm64)
# No libvips compilation needed in most environments

Basic Usage

import sharp from 'sharp';

// Resize and convert format
await sharp('input.jpg')
  .resize(800, 600, {
    fit: 'cover',       // Crop to fill dimensions
    position: 'center', // Center the crop
  })
  .webp({ quality: 85 })
  .toFile('output.webp');

// Or to buffer (for HTTP responses):
const buffer = await sharp('input.jpg')
  .resize(400)  // Resize width to 400, maintain aspect ratio
  .jpeg({ quality: 90, progressive: true })
  .toBuffer();

Format Conversion

// Convert to WebP (40-50% smaller than JPEG at same quality)
await sharp('photo.jpg').webp({ quality: 80 }).toFile('photo.webp');

// Convert to AVIF (50-60% smaller than JPEG, better quality)
await sharp('photo.jpg')
  .avif({
    quality: 60,  // AVIF is efficient — 60 looks like JPEG 85
    effort: 6,    // Encoding effort 0-9 (higher = slower, smaller)
  })
  .toFile('photo.avif');

// PNG with optimization
await sharp('image.png')
  .png({ compressionLevel: 9, palette: true })
  .toFile('optimized.png');

Pipeline for User Uploads

import sharp from 'sharp';

interface ResizeOptions {
  width: number;
  height: number;
  quality?: number;
}

async function processUpload(
  inputBuffer: Buffer,
  options: ResizeOptions
): Promise<{ webp: Buffer; avif: Buffer; thumbnail: Buffer }> {
  const image = sharp(inputBuffer)
    .rotate()  // Auto-rotate based on EXIF
    .resize(options.width, options.height, {
      fit: 'inside',     // Don't crop, scale down to fit
      withoutEnlargement: true,  // Don't upscale
    });

  // Process multiple outputs in parallel
  const [webp, avif, thumbnail] = await Promise.all([
    image.clone().webp({ quality: options.quality ?? 85 }).toBuffer(),
    image.clone().avif({ quality: 60 }).toBuffer(),
    image.clone().resize(200, 200, { fit: 'cover' }).jpeg({ quality: 80 }).toBuffer(),
  ]);

  return { webp, avif, thumbnail };
}

Metadata Extraction

const metadata = await sharp('image.jpg').metadata();
console.log(metadata);
// {
//   width: 2000,
//   height: 1500,
//   format: 'jpeg',
//   size: 1234567,
//   exif: Buffer,
//   icc: Buffer,
//   orientation: 1,
//   density: 72
// }

// Strip EXIF (privacy — remove GPS, camera info)
await sharp('photo.jpg')
  .withMetadata(false)  // Remove all metadata
  .toFile('clean.jpg');

Performance Benchmark

Resize 100 images (2000x1500 → 300x200, JPEG):

Sharp:        ~1.5s (60 images/second)
squoosh-cli:  ~37s  (2.7 images/second)
jimp:         ~220s (0.45 images/second)

Sharp is ~25x faster than squoosh, ~150x faster than jimp.

Sharp in Next.js

Sharp is used by Next.js's next/image component for automatic image optimization:

// next.config.js
module.exports = {
  images: {
    // Next.js uses sharp to serve WebP/AVIF automatically
    formats: ['image/avif', 'image/webp'],
    // Based on Accept header, serves AVIF or WebP instead of JPEG
  },
};
// In your component:
import Image from 'next/image';

// Sharp converts and caches the image server-side
<Image
  src="/hero.jpg"
  width={1200}
  height={600}
  alt="Hero"
  priority
/>
// Browser receives WebP or AVIF automatically

Sharp Limitations

  • Native binaries — can't run in true edge runtimes (Cloudflare Workers, Vercel Edge Functions)
  • Requires prebuilt binaries for the target platform (CI/CD considerations)
  • Not available in browser environments

Jimp

Package: jimp Weekly downloads: 1.5M+ GitHub stars: 14K

Jimp is 100% JavaScript — no native dependencies. It's slower than sharp but runs in any environment where JavaScript runs.

Installation

npm install jimp

Basic Usage

import Jimp from 'jimp';

const image = await Jimp.read('input.jpg');

image
  .resize(800, 600)          // Resize
  .quality(85)               // JPEG quality
  .greyscale()               // Convert to grayscale
  .write('output.jpg');      // Save

// To buffer:
const buffer = await image.getBufferAsync(Jimp.MIME_JPEG);

Image Manipulation

import Jimp from 'jimp';

const image = await Jimp.read('photo.jpg');

// Composite (overlay logo)
const logo = await Jimp.read('logo.png');
logo.resize(100, Jimp.AUTO);

image
  .composite(logo, image.bitmap.width - 110, image.bitmap.height - 110)
  .brightness(0.1)        // Adjust brightness
  .contrast(0.1)          // Adjust contrast
  .blur(2)                // Gaussian blur
  .write('branded.jpg');

Format Support

// Jimp supports: JPEG, PNG, BMP, GIF, TIFF
// Does NOT natively support: WebP, AVIF

// For WebP in Jimp, you'd need a plugin or sharp instead:
import Jimp from 'jimp';
import '@jimp/plugin-webp';  // Third-party plugin

const image = await Jimp.read('input.jpg');
await image.writeAsync('output.webp');

When Jimp Makes Sense

// Serverless environments with strict size limits:
// - AWS Lambda (ZIP size constraints)
// - Functions that can't include native binaries

// Pure Node.js scripts with no native dependency build step:
// npm install jimp && immediately works

// Simple image tasks that don't need high throughput:
// Resize one image on user upload (not bulk processing)

Jimp Limitations

  • 100-150x slower than sharp for bulk operations
  • No WebP or AVIF support in core
  • High memory usage for large images (no streaming)
  • Not suitable for production image pipelines handling scale

Squoosh

Package: @squoosh/lib GitHub: GoogleChromeLabs/squoosh Status: Based on Google's Squoosh project

Squoosh is Google's open-source image compression tool. The @squoosh/lib npm package brings its Wasm-based codecs to Node.js — the same codecs the squoosh.app web UI uses.

What Squoosh Does Differently

Squoosh's value isn't speed — it's codec quality control. The Wasm codecs (mozjpeg, WebP, AVIF/AV1, JXL) give you fine-grained control over encoding parameters that sharp doesn't always expose:

import { ImagePool } from '@squoosh/lib';
import { cpus } from 'os';

const imagePool = new ImagePool(cpus().length);

const imageFile = readFileSync('./input.jpg');
const image = imagePool.ingestImage(imageFile);

// Decode
await image.decoded;

// Encode with specific codec options
const { binary, extension, optionsUsed } = await image.encode({
  mozjpeg: {
    quality: 80,
    progressive: true,
    auto_subsample: true,
  },
  webp: {
    quality: 75,
    target_size: 0,
    method: 4,
  },
  avif: {
    cqLevel: 33,
    speed: 8,
    subsample: 1,
  },
  oxipng: {
    level: 2,
  },
});

// binary is the optimized file buffer
writeFileSync('output.webp', binary.webp.binary);

await imagePool.close();

When to Use Squoosh

Squoosh is best for build-time image optimization (not runtime), where you want maximum compression quality and don't need bulk throughput:

# CLI usage:
npx @squoosh/cli --webp '{"quality":80}' --avif '{"cqLevel":33}' *.jpg
# Outputs optimized WebP and AVIF versions of each image

# Good for:
# - Build step: compress images before deployment
# - Quality experimentation: find the right quality settings
# - Format comparison: see WebP vs AVIF file sizes for your images

Squoosh Limitations

  • Much slower than sharp (25x slower for resize operations)
  • Wasm-based codecs have startup overhead
  • @squoosh/lib is less actively maintained than sharp

Comparison

FeatureSharpJimpSquoosh
Weekly downloads9M1.5MLow (CLI/lib)
SpeedFastest (native)Slowest (pure JS)Medium (Wasm)
Native depsYes (libvips)NoNo (Wasm)
WebP supportYesPlugin onlyYes (mozjpeg/WebP)
AVIF supportYesNoYes (AV1)
JPEG XLNoNoYes
Edge runtimeNoLimitedNo
Next.js imageDefaultNoNo
Use caseProduction pipelinePortabilityBuild-time optimization

Decision Guide

Choose Sharp if:

  • Processing user uploads at scale
  • You need WebP/AVIF conversion in production (Next.js, custom image service)
  • Performance matters — bulk processing, CDN image optimization
  • You're on a standard Node.js server (not edge runtime)

Choose Jimp if:

  • You cannot use native dependencies (certain serverless environments)
  • Simple one-off image tasks without performance requirements
  • You need zero-native-dependency portability
  • Quick prototyping before switching to sharp for production

Choose Squoosh if:

  • Build-time image optimization (compress source images before deployment)
  • You need fine-grained AVIF/WebP encoding control
  • Quality comparison between codecs for your specific images
  • You're using it as a CLI tool, not a library

Compare image processing package downloads on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.