How to Convert JPG Images to WebP in Bulk
Convert whole JPG folders to WebP with cwebp or ImageMagick, preserve originals, control quality and metadata, and troubleshoot common batch errors.
Use Google’s cwebp encoder in a shell loop to convert every JPG in a folder, writing separate .webp files and keeping the originals. Test one representative image first, choose lossy or lossless encoding, decide which metadata to retain, then process the folder.
cwebp accepts JPEG input and writes WebP output. The command-line reference documents quality controls, lossless mode, presets, and EXIF, ICC, and XMP metadata handling. Read the cwebp reference and the WebP FAQ.
1. Prepare a safe bulk-conversion workflow
- Keep your JPG/JPEG files in the source directory.
- Create a separate output directory, or write distinct filenames ending in
.webp. - Convert one representative photo before running a batch.
- Inspect dimensions, visual quality, transparency expectations, color, and metadata.
- Process the rest of the folder.
- Keep the originals until the WebP files have been reviewed and backed up.
Conversion does not guarantee a smaller file or perceptually identical output. The result depends on the source image, encoder version, quality setting, and whether you choose lossy or lossless encoding.
2. Convert one JPG first with cwebp
Install the WebP command-line tools for your operating system, then confirm that the encoder is available:
cwebp -version
For a lossy conversion, choose a quality value from 0 to 100. Lower values generally produce smaller files and lower quality; 100 is the highest quality within lossy mode. Google’s getting-started example uses 80 as an example setting, not as a universal recommendation.
cwebp -q 80 photo.jpg -o photo.webp
For lossless encoding:
cwebp -lossless photo.jpg -o photo.webp
Compare the source and output at their intended display size. For photographs, try several quality values on a representative sample and select the smallest result that still meets your visual requirements.
3. Bulk conversion on Windows Command Prompt
Google’s WebP FAQ documents this Windows Command Prompt pattern for JPG files in one directory:
for %I in (*.jpg) do ( cwebp.exe %I -o %~fnI.webp )
Run it from the folder containing the JPG files. In a .bat file, double the percent sign:
for %%I in (*.jpg) do ( cwebp.exe "%%I" -q 80 -o "%%~dpnI.webp" )
The documented example matches .jpg. If your files use the .jpeg extension, run a separate loop:
for %I in (*.jpeg) do ( cwebp.exe "%I" -q 80 -o "%~fnI.webp" )
To write results to a separate folder, create it first and use an explicit output path in a batch script. Test the quoting with filenames containing spaces before processing a large directory.
4. Bulk conversion with PowerShell
PowerShell uses different loop syntax from Command Prompt. This command handles both .jpg and .jpeg files in the current directory and writes outputs to a webp subdirectory:
$source = Get-Location
$output = Join-Path $source "webp"
New-Item -ItemType Directory -Force -Path $output | Out-Null
Get-ChildItem -File | Where-Object { $_.Extension -in ".jpg", ".jpeg" } | ForEach-Object {
$target = Join-Path $output ($_.BaseName + ".webp")
& cwebp.exe -q 80 $_.FullName -o $target
if ($LASTEXITCODE -ne 0) {
Write-Error "Conversion failed: $($_.FullName)"
}
}
For recursive conversion, enumerate subdirectories and preserve their relative paths:
$root = (Get-Location).Path
$outputRoot = Join-Path $root "webp"
Get-ChildItem -Path $root -Recurse -File | Where-Object { $_.Extension -in ".jpg", ".jpeg" } | ForEach-Object {
$relative = $_.FullName.Substring($root.Length).TrimStart('\/')
$relativeDirectory = Split-Path $relative -Parent
$destinationDirectory = Join-Path $outputRoot $relativeDirectory
New-Item -ItemType Directory -Force -Path $destinationDirectory | Out-Null
$target = Join-Path $destinationDirectory ($_.BaseName + ".webp")
& cwebp.exe -q 80 $_.FullName -o $target
if ($LASTEXITCODE -ne 0) {
Write-Error "Conversion failed: $($_.FullName)"
}
}
5. Bulk conversion on macOS or Linux
In a POSIX shell, this loop processes JPG and JPEG files in the current directory:
mkdir -p webp
for file in ./*.jpg ./*.jpeg; do
[ -f "$file" ] || continue
name=$(basename "$file")
stem="${name%.*}"
cwebp -q 80 "$file" -o "webp/$stem.webp" || echo "Conversion failed: $file" >&2
done
For recursive conversion while preserving the directory structure:
find . -type f \( -iname '*.jpg' -o -iname '*.jpeg' \) -print0 |
while IFS= read -r -d '' file; do
relative=${file#./}
directory=$(dirname "$relative")
name=$(basename "$relative")
stem="${name%.*}"
mkdir -p "webp/$directory"
cwebp -q 80 "$file" -o "webp/$directory/$stem.webp" || echo "Conversion failed: $file" >&2
done
The null-delimited form safely handles spaces, quotes, and most unusual characters in filenames. Shell behavior differs across environments, so check the command with a small sample first.
6. Use ImageMagick instead
ImageMagick is an alternative command-line workflow with WebP quality and lossless controls. Convert one file with:
magick photo.jpg -quality 80 photo.webp
Convert all JPG files in a directory to a separate output directory:
mkdir -p webp
for file in ./*.jpg ./*.jpeg; do
[ -f "$file" ] || continue
name=$(basename "$file")
stem="${name%.*}"
magick "$file" -quality 80 "webp/$stem.webp" || echo "Conversion failed: $file" >&2
done
ImageMagick also supports lossless WebP through its WebP encoder settings. Check the version-specific ImageMagick WebP documentation before relying on advanced options. No comparative speed or quality winner between ImageMagick and cwebp is established here; compare both on your own representative files.
7. Choose lossy, lossless, presets, and metadata
Lossy quality
Use -q 0 through -q 100 with cwebp. A lower value generally reduces file size and image quality. There is no single correct value for every image type. Photographs, screenshots, illustrations, and text-heavy graphics can require different settings.
cwebp -q 60 input.jpg -o output.webp
cwebp -q 80 input.jpg -o output.webp
cwebp -q 95 input.jpg -o output.webp
Lossless encoding
Use -lossless when preserving the decoded image data matters more than minimizing the output size:
cwebp -lossless input.jpg -o output.webp
Presets
The encoder documents presets such as photo, picture, drawing, icon, and text. Presets can override most other options, so read the encoder reference and verify the resulting output when combining a preset with quality or other flags.
cwebp -preset photo -q 80 input.jpg -o output.webp
Metadata
The documented metadata setting accepts all, none, exif, icc, or xmp. The default is to copy none. Select metadata deliberately:
cwebp -q 80 -metadata exif input.jpg -o output.webp
cwebp -q 80 -metadata icc input.jpg -o output.webp
cwebp -q 80 -metadata all input.jpg -o output.webp
cwebp -q 80 -metadata none input.jpg -o output.webp
Preserve EXIF when downstream systems need camera or orientation data. Preserve ICC profiles when color management matters. Treat location and other personal metadata as a separate privacy decision.
8. Handle common edge cases
.jpgversus.jpeg: match both extensions explicitly; a loop for one does not automatically process the other.- Uppercase extensions: Windows matching is usually case-insensitive, while Unix tools may not be. Use case-insensitive matching such as
-inameinfind. - Existing outputs: decide whether to overwrite, skip, or write to a new directory. Keeping a separate output directory prevents accidental replacement.
- Duplicate base names: files such as
cover.jpgandcover.jpegproduce the samecover.webpname if placed together. Detect collisions before running the batch. - Animated or unusual inputs: JPEG is normally a single-frame format, but malformed or mislabeled files can fail. Validate files that produce errors.
- Color shifts: inspect images with embedded profiles and use the appropriate ICC metadata option when required.
- Very large images: conversion can consume substantial memory and disk space. Process in manageable batches and monitor available storage.
- Web publishing: update references, responsive image markup, caches, and content manifests after conversion. A converted file is not automatically used by your site.
9. Verify a bulk conversion
- Count source JPG/JPEG files and generated WebP files.
- Check that every expected output exists and has a nonzero size.
- Open a sample from each important image category.
- Compare dimensions and orientation.
- Check metadata that your workflow requires.
- Measure file sizes before deleting or archiving originals.
A simple POSIX count comparison:
find . -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.jpeg' \) | wc -l
find ./webp -maxdepth 1 -type f -iname '*.webp' | wc -l
Counts alone do not prove correctness: one failed conversion, a filename collision, or an output written to the wrong directory can still make the totals misleading.
10. Troubleshooting
| Error or symptom | Likely cause | Fix |
|---|---|---|
cwebp: command not found or not recognized |
The WebP tools are not installed or are not on PATH. |
Install the official WebP command-line tools for your operating system, then reopen the shell and run cwebp -version. |
| No files are converted | The loop is running in the wrong directory or the extension does not match. | Print the current directory, list files, and include both .jpg and .jpeg patterns. |
| Output names are overwritten | Different source extensions or directories share the same base name. | Write to a separate directory that preserves paths, or add a collision check before conversion. |
| Files with spaces fail | Input or output paths are not quoted. | Quote every path variable, for example "$file" or "%I". |
| Output is unexpectedly soft or blocky | The lossy quality value is too low for that image. | Raise -q, test several values, or use -lossless when exact decoded data matters. |
| Output is larger than the JPG | The source is already highly compressed, or lossless encoding is being used. | Compare representative files, try an appropriate lossy quality, and do not assume WebP always reduces size. |
| Camera or color metadata is missing | The default metadata behavior copies none. | Request exif, icc, xmp, or all as required. |
| Batch stops midway | A malformed input, permission problem, full disk, or command error interrupted the loop. | Capture failures, check exit codes and disk space, then rerun only the missing files. |
PowerShell treats cwebp as a script or alias |
The executable is not resolved as expected. | Use the full executable path or & cwebp.exe ..., and verify with Get-Command cwebp. |
11. Performance, reliability, and cost
Performance
Processing time depends on image dimensions, encoder settings, storage, CPU, and the number of files. Benchmark a representative subset on the same machine and settings you will use in production. The reviewed documentation does not establish a comparative speed winner between cwebp and ImageMagick.
For large collections, process files in batches, write to a separate destination, and avoid running more parallel jobs than the machine can support. Parallel conversion can increase throughput but also increases CPU, memory, and disk contention.
Reliability
- Keep source files immutable during conversion.
- Check each command’s exit status.
- Log failed filenames.
- Use deterministic output names.
- Make the batch rerunnable so existing successful outputs can be skipped safely.
- Review a sample after every encoder or configuration change.
Cost
Local conversion has no per-image API charge, but it uses your own CPU, storage, and operational time. Budget temporary disk space for both the original and converted collections, especially when testing lossless output.
12. Or skip the browser setup
If your JPG files come from web pages and you actually need WebP screenshots rather than local file conversion, ScreenshotNeo returns a WebP screenshot from one GET request. It does not replace a local JPG-to-WebP encoder for files already on disk, but it can remove the browser automation setup from a URL-capture workflow.
See the ScreenshotNeo API documentation for parameters and options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
13. FAQ
Is WebP always smaller than JPG?
No. The result depends on the source, quality setting, metadata, and whether encoding is lossy or lossless. Measure your own files.
Should I use quality 80?
Use it as a starting sample because Google’s guide shows 80 as an example. Select the final value by inspecting representative images and comparing sizes.
Can I delete the JPG files after conversion?
Keep them until outputs are verified, backed up, and confirmed in every system that uses them.
Does cwebp preserve EXIF data automatically?
No. The documented default copies no metadata. Select the metadata categories you need.
Can ImageMagick and cwebp produce identical files?
Not necessarily. They may use different versions, defaults, and encoder settings. Compare output quality, size, and processing time on your own sample set.
Can ScreenshotNeo convert a local folder of JPG files?
No. ScreenshotNeo captures URLs and returns screenshot images, including WebP. Use cwebp or ImageMagick for local bulk conversion.


