ImagePDF.Tools
Performance & SEO

Progressive JPEGs: The Forgotten Optimization That Still Matters

N
NikolaLast updated on June 20, 2026 · 9 min read

Summary

Progressive JPEGs show a full-image blurry preview instantly, then sharpen. They're 2–8% smaller than baseline and make images feel faster. Here's how to use them.

You've compressed your hero image to 150 KB, set fetchpriority="high", and the LCP is still 2.8 seconds on 4G. The image downloads, but it feels slow, because baseline JPEG rendering is top-to-bottom, and on a slow connection the bottom half of the image remains blank while the top loads in. The page looks broken.

Progressive JPEG encoding fixes this perceptual problem without any additional compression. The image shows a complete blurry preview in the first pass, users see the full composition immediately, then sharpens in subsequent passes as more data arrives. For the same quality setting, progressive is also 2–8% smaller than baseline for images above about 10 KB. It's one of the most impactful, most overlooked optimisations in image delivery.

Progressive JPEG scan comparison: scan 1 blurry full image, scan 2 medium detail, scan 3 near-full detail, scan 4 complete | ImagePDF.Tools
Progressive JPEGs show the full image immediately at low quality, then sharpen with each scan.

Baseline vs. Progressive JPEG: The Technical Difference

Both are valid JPEG files. The difference is in how image data is ordered within the file:

Baseline JPEG stores image data as a sequence of rows from top to bottom. The browser paints each row as it receives the data. On a fast connection, this is invisible. On a slow connection or with a large file, the image paints progressively from top to bottom, users see half an image while waiting for the rest.

Progressive JPEG stores the image as multiple scans, each covering the entire image at increasing levels of detail. Scan 1 contains a very low-resolution (but complete) version of the full image. Scan 2 adds medium-frequency detail. Scan 3 and beyond add high-frequency detail. The browser can display the complete image, blurry but recognisable, after receiving only the first scan (typically 5–15% of the file).

ℹ️

Progressive JPEG is a perceptual optimisation first and a size optimisation second. The perceived quality difference, seeing the full image vs. a blank area, is significant on slow connections. The size difference (2–8% smaller for large images) is real but secondary. Both benefits come for free at encode time.

File Size: Progressive vs. Baseline at the Same Quality

Image sizeContent typeBaseline sizeProgressive sizeSaving
200×200px (thumbnail)Portrait photo12 KB13 KB−8% (baseline wins)
800×600pxLandscape photo85 KB80 KB+6%
1200×800px (hero)Mixed content180 KB168 KB+7%
2000×1333px (full quality)Portrait photo450 KB418 KB+7%
Flat UI screenshot800×600px110 KB115 KB−5% (baseline wins)
Progressive vs. baseline JPEG file size at the same quality, image size and content type affect the differential

The crossover point is roughly 10 KB. For thumbnails and small images, baseline is sometimes smaller. For anything above 50 KB, hero images, product photos, article images, progressive is almost always smaller and always perceptually better on constrained connections.

How Progressive JPEG Decoding Works in the Browser

When a browser receives a progressive JPEG, it decodes and displays each scan as it arrives. Scan 1 is displayed immediately when the initial data arrives, this might be after receiving only 5–20% of the bytes. The image appears complete (if blurry). Subsequent scans update the display, sharpening the image in real time as data streams in.

This is fundamentally different from baseline JPEG, where the browser must receive all the bytes for a given row before it can paint that row. On a page with a 300 KB hero image loading over a 5 Mbps connection (slow 4G), baseline shows the top 30–40% of the image for a noticeable pause, then snaps to full quality. Progressive shows the full composition immediately at low quality, then sharpens seamlessly, the same bytes, dramatically different user experience.

How to Encode Progressive JPEGs

bash
# jpegtran, losslessly convert existing JPEG to progressive
# No quality change, just re-orders the scan structure
jpegtran -progressive -copy none input.jpg output-progressive.jpg

# ImageMagick, convert to progressive during resize or quality change
magick convert input.jpg -interlace Plane -quality 80 output-progressive.jpg

# cjpeg (libjpeg-turbo), encode from source with progressive flag
cjpeg -progressive -quality 80 -outfile output.jpg input.ppm

# Sharp (Node.js), progressive flag in the JPEG output options
sharp('input.jpg')
  .jpeg({ quality: 80, progressive: true })
  .toFile('output-progressive.jpg');

# Verify progressive encoding with ImageMagick identify:
identify -verbose output.jpg | grep Interlace
# Interlace: Plane = progressive
# Interlace: None  = baseline

Progressive JPEG in Build Pipelines

Most modern image processing pipelines support progressive encoding as a flag. The key is ensuring it's enabled where your JPEG files are produced, not just locally:

  • Webpack / Vite (imagemin-mozjpeg): Set progressive: true in the plugin options
  • Gulp (gulp-imagemin): imageminMozjpeg({ progressive: true, quality: 80 })
  • Cloudinary CDN: Add fl_progressive to the transformation URL
  • Imgix CDN: Add fm=pjpg to the request URL
  • Cloudflare Images: Progressive output is enabled by default in their pipeline
  • Lightroom Classic: Export → Format: JPEG → check "Save as progressive scan"

Browser and CDN Support for Progressive Decoding

All modern browsers (Chrome, Firefox, Safari, Edge) support progressive JPEG decoding. The progressive scan order is transparent to the browser, it displays each scan as it arrives, regardless of whether the developer is aware of it. There is no CSS or JavaScript needed to enable progressive rendering; it's built into the JPEG format and the browser's image decoder.

CDN caveats: some CDNs strip progressive encoding when transcoding JPEGs. Cloudflare, Cloudinary, and Imgix all preserve or can re-add progressive encoding. AWS S3 + CloudFront does not transcode, it serves whatever you upload. If your CDN processes images, check that progressive encoding is preserved or can be enabled in the CDN's image optimisation settings.

Progressive JPEG vs. Blur-Up Placeholder Techniques

A popular alternative to progressive JPEG is the "blur-up" placeholder technique: serve an inline base64 SVG or very small JPEG as an immediate placeholder, then load the full image lazily. Next.js uses this by default for blurred placeholder images. The result is similar, the user sees something immediately, but it requires JavaScript and additional markup.

Progressive JPEG achieves the same perceptual effect without JavaScript, without additional markup, and without a separate placeholder image. For static sites and non-React pages, progressive encoding is the simpler solution. For React and Next.js apps, the blur-up technique is often already built in; use progressive encoding as well for any JPEG that isn't handled by the framework's Image component.

When Progressive JPEGs Are Not Worth It

  • Thumbnails under 20 KB: Images this small load in under 50ms even on slow connections, the progressive effect isn't perceptible and baseline may be slightly smaller
  • Already-WebP images: WebP doesn't have a "progressive" mode in the same sense; use incremental decoding instead, which modern browsers handle automatically
  • Images below the fold with lazy loading: These load on scroll, when the user is already engaged, the progressive effect is less meaningful than for above-fold content
  • PNG and GIF: Progressive encoding is a JPEG-specific technique; PNG uses "Adam7" interlacing for similar effect but the benefit is smaller

Bottom Line

Progressive JPEG is a low-cost, high-leverage optimisation. It requires adding one flag at encode time, costs nothing at delivery time, and improves both perceived load speed and actual file size for images above 50 KB. For any site serving large hero images or galleries over JPEG, enabling progressive encoding across the pipeline is one of the few true free wins in image performance. Start with your hero images, compress them first to reduce the total bytes, then convert to progressive to improve the experience as those bytes arrive.

Frequently asked questions

What is a progressive JPEG?
A progressive JPEG stores image data as multiple scans, each covering the entire image at increasing detail levels. The first scan delivers a complete (blurry) preview of the image; subsequent scans sharpen it. This allows the browser to show the full image composition immediately rather than loading top-to-bottom. The alternative, baseline JPEG, stores data row by row, showing a partial image while loading.
Are progressive JPEGs smaller than baseline JPEGs?
Generally yes, for images above about 10 KB. Progressive encoding is typically 2–8% smaller than baseline at the same quality level for medium and large images. For thumbnails under 10 KB, baseline is sometimes slightly smaller. The size savings are a secondary benefit; the primary benefit is better perceived load performance.
How do I convert a JPEG to progressive encoding?
The most lossless method is jpegtran: jpegtran -progressive -copy none input.jpg output.jpg. This reorders the scan structure without re-encoding, so there is no quality loss. ImageMagick also works: magick convert input.jpg -interlace Plane output.jpg. For Node.js pipelines, the Sharp library accepts a progressive: true option in its jpeg() output configuration.
Do all browsers support progressive JPEG?
Yes. All modern browsers, Chrome, Firefox, Safari, Edge, and their mobile variants, support progressive JPEG decoding and display each scan as it arrives. Progressive JPEG support has been universal since the early 2000s. No JavaScript or CSS is needed; the behavior is built into the browser's image decoder.
Should I use progressive JPEG or WebP?
These solve different problems and can be combined. WebP is the better format for file size: lossy WebP is 25–35% smaller than JPEG at equivalent quality, which reduces download time for any connection speed. Progressive JPEG improves perceived performance on slow connections by showing a blurry preview immediately. If you're serving JPEG (e.g. as a fallback in a element), use progressive encoding. If you've already switched to WebP for the primary format, progressive encoding applies to the JPEG fallback.

Sources & references

This article was researched and written by Nikola, drawing on the following primary sources and documentation:

Ready to try it?

All tools run entirely in your browser, no uploads, no account required.

Compress Image
You're offline, cached tools still work