jpegoptim shrinks JPEGs on the command line. You set the trade-off between file size and fidelity. This covers installation, the flags you will actually use, and ready-to-run batch commands. Lossless optimisation, a ceiling on compression, a hard file-size target, stripping EXIF and comments, forcing progressive output, and processing whole folder trees are all covered. Copy the commands and point them at your own files.
Install Jpegoptim on Linux, MacOS, and Windows
Get the Binary
Install jpegoptim before running any of the commands below. The package manager depends on your operating system.
- Debian/Ubuntu: sudo apt install jpegoptim
- Fedora: sudo dnf install jpegoptim
- macOS Homebrew: brew install jpegoptim
- Windows: Use WSL (Windows Subsystem for Linux). Inside a WSL terminal, run the install command for your chosen Linux distribution, for example sudo apt install jpegoptim.
After installation, verify it by running jpegoptim --version in your terminal. You should see a version number.
Basic Lossless Optimization
With no options, jpegoptim performs a lossless optimisation. It rewrites the Huffman tables in the JPEG file to a more efficient form. Visual fidelity is unchanged. File size drops, but only if the tool finds a smaller representation. The original file is overwritten in place. If the optimised version is not smaller, the original is left untouched.
Run this on a single file:
jpegoptim photo.jpgThis is the safest starting point. No fidelity is lost. Run it on many files by listing them:
jpegoptim photo1.jpg photo2.jpg photo3.jpgBecause the command overwrites the original, test on a copy first. Get comfortable with how it behaves on your system before you run it on your only copy of an image.
Set a Maximum Quality with Jpegoptim Max Quality
Cap the Compression
Use the -m or --max flag to shrink files more aggressively. This sets a ceiling on the quality level. Jpegoptim re-encodes only files that are above that ceiling. Files already at or below the limit are left alone.
Re-encode a photo so its quality does not exceed 85:
jpegoptim -m85 photo.jpgThe jpegoptim max quality setting is a number. Lower numbers mean more compression and lower fidelity. The tool uses the same quality scale as the original JPEG encoder, so 85 is a common balance for web images.
Combine this with other flags. Strip metadata and cap quality in one pass:
jpegoptim -m85 --strip-all photo.jpgTarget a Specific File Size with Jpegoptim --size
Hit a Hard File-Size Limit
Skip the quality level. Tell jpegoptim the exact file size you need with the -S or --size flag. Give the size in kilobytes as a plain number, or as a percentage of the original file size.
Make a file that is at most 200 kilobytes:
jpegoptim -S200 photo.jpgReduce a file to 50% of its current size:
jpegoptim -S50% photo.jpgJpegoptim adjusts the quality level to meet your target. It will not exceed the limit. The resulting fidelity depends on the image content and may be higher or lower than what a fixed quality flag would produce.
Use this when you face a hard limit, such as an upload cap or a maximum thumbnail size. Run jpegoptim --size in a batch to bring many images under the same ceiling.
Strip Metadata and Preserve Details
Remove Hidden Bloat
JPEG files carry EXIF data, comments, and ICC colour profiles. This extra information adds weight without changing the picture. The -s or --strip-all flag removes every metadata marker.
jpegoptim --strip-all photo.jpgThis is the quickest way to shed bytes, especially for phone photos that embed a lot of EXIF.
Watch out for ICC profiles. Removing the profile can shift colours on wide-gamut images because the profile tells your monitor and browser how to interpret the colours. Keep the ICC profile but remove everything else with finer-grained options:
- --strip-exif removes EXIF data (camera settings, GPS)
- --strip-com removes comment markers
These let you keep the colour profile while stripping the rest. --strip-all is equivalent to both --strip-exif and --strip-com together, but it also removes the ICC profile. If you are unsure, test on a copy.
Progressive and Baseline Output
Choose Progressive or Baseline
JPEGs are either baseline or progressive. Baseline loads top to bottom. Progressive loads in passes, showing a blurry preview that sharpens. Progressive files are often smaller for large images and feel faster on slow connections.
Convert all output to progressive with --all-progressive:
jpegoptim --all-progressive photo.jpgThis forces progressive output even if the original was baseline. Force baseline output with --all-normal:
jpegoptim --all-normal photo.jpgUse these flags when you have a mix and want a consistent format. They affect the output format, not the fidelity. Combine them with quality or size options.
Batch Processing a Recursive Folder
Process a Whole Directory Tree
Real workflows demand processing many images across a directory tree. Combine find with xargs. This finds every .jpg file (case-insensitive) in the current directory and all subdirectories, then passes them to jpegoptim with a quality cap of 85 and metadata stripping:
find . -iname "*.jpg" -print0 | xargs -0 jpegoptim -m85 --strip-allThe -print0 and -0 options handle file names with spaces or special characters. -iname "*.jpg" matches both .jpg and .JPG.
Write Output to a Separate Directory
Keep originals untouched. Use the -d (or --dest) flag to write optimised files into a different folder. Save everything into a folder called optimized:
find . -iname "*.jpg" -print0 | xargs -0 jpegoptim -m85 --strip-all -d optimizedCreate the destination directory first, or jpegoptim will fail. When you use -d, the directory structure is not preserved. All files land flat in the destination. Keeping the folder structure requires a more complex script.
Preview and Measure Savings
Before running a large batch, do a dry run with -n (or --noaction). See what jpegoptim would do without changing any files:
find . -iname "*.jpg" -print0 | xargs -0 jpegoptim -m85 --strip-all -nThis prints the expected savings for each file. Remove the -n flag to actually process the files.
Add the -t (or --totals) flag to get a summary. It shows a final line with total bytes saved and the percentage reduction.
Keep original file timestamps with the -p (or --preserve) flag. This matters for archiving or when you need to maintain file modification times.