# WebP

Canonical URL: https://encode.wiki/codecs/images/webp/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): d3bd35de57e2e0f1a0483a3621edd5782bae0682247e4c95a24279f3fc43ccca

WebP is Google's image format from 2010: a lossy mode derived from the [VP8](/codecs/video/vp8/) video codec, a separate lossless mode (VP8L) added in 2011, and an extended container with alpha, animation, ICC profiles and Exif/XMP metadata. It is standardised as [RFC 9649](https://www.rfc-editor.org/rfc/rfc9649) (informational, 2024) and implemented by Google's [libwebp](https://github.com/webmproject/libwebp), which provides `cwebp`, `dwebp`, `img2webp`, `gif2webp` and `webpmux`.

Its appeal today is compatibility: every current browser, OS image framework and image library decodes it, and it encodes quickly. Newer formats ([AVIF](/codecs/images/avif/), [JPEG XL](/codecs/images/jxl/)) compress better, but WebP is a safe default for web delivery, for transparent images and for replacing GIF.

## Strengths and weaknesses

**Strengths**

- Lossy files noticeably smaller than JPEG at similar visual quality in most cases, with alpha available in lossy files too.
- A lossless mode that is clearly smaller than PNG: on Google's [web-image corpus](https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study) about 40 % smaller than plain libpng output and about 20 % smaller than ZopfliPNG-optimised PNG.
- Animation with 24-bit colour and alpha, and per-frame lossy or lossless coding. Animated WebP is usually considerably smaller than GIF.
- Universal support, fast encoding and decoding, royalty-free.

**Weaknesses**

- Lossy WebP is **8-bit 4:2:0 only**. There is no 4:4:4 or 10-bit lossy mode and no HDR, so saturated red/blue edges and coloured text bleed, and gradients can band.
- Maximum 16,383 × 16,383 pixels in each direction.
- The lossy format is based on VP8 and tends to smooth fine texture; it is clearly less efficient than AVIF or JPEG XL.
- No JPEG-style progressive decode.
- Lossless is 8-bit RGBA only; for 16-bit images use PNG or JPEG XL.

## Support

| Browser            | WebP                                                                       |
| ------------------ | -------------------------------------------------------------------------- |
| Chrome             | 17+ (lossless and alpha from 23, animation from 32)                        |
| Edge               | 18+                                                                        |
| Firefox            | 65+                                                                        |
| Safari / iOS Safari| 14+                                                                        |

(From [MDN's WebP data](https://github.com/mdn/browser-compat-data/blob/main/mediatypes/image/webp.json).) That covers every browser still in use. Older software and some editors and apps are the remaining gaps. See [image and audio support](/reference/image-audio-support/).

## Encode with cwebp

`cwebp` reads PNG, JPEG, TIFF, WebP and PNM.

```sh
cwebp -q 80 -m 6 input.png -o output.webp
```

`-q` is 0–100 (default 75); the scale is not JPEG's, so compare by eye. `-m 6` is the slowest, best compression method (default 4) and is worth it unless you are encoding enormous batches. Add `-mt` to use several threads.

| Goal                                  | Command                                                  | Notes                                                                                      |
| ------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Photo                                 | `cwebp -q 80 -m 6 in.png -o out.webp`                    | `-preset photo`, `picture`, `drawing`, `icon` and `text` tune the encoder for the content type; the preset must come first.                          |
| Sharper colour edges                  | add `-sharp_yuv`                                         | Slower, more careful RGB→YUV 4:2:0 conversion; helps red text and thin coloured lines.     |
| Lossless                              | `cwebp -lossless -z 9 in.png -o out.webp`                | `-z 0`–`9` is the lossless effort preset (`-z` implies `-lossless`); 9 is slowest and smallest. |
| Lossless with a little loss           | `cwebp -near_lossless 60 -z 9 in.png -o out.webp`        | `-near_lossless 0..100`: 100 is off; lower is lossier. Still the lossless codec, so graphics compress better with no visible change. |
| Smaller alpha                         | `cwebp -q 80 -alpha_q 80 in.png -o out.webp`             | Alpha is coded separately and is lossless by default (`-alpha_q 100`); lower it to shrink soft masks. |
| Keep hidden RGB under transparency    | add `-exact`                                             | By default `cwebp` is free to change colours of fully transparent pixels to compress better. |
| Hit a size                            | `cwebp -size 50000 in.png -o out.webp`                   | Searches quality for a target byte size. `-psnr 42` targets a PSNR instead.               |
| Resize while encoding                 | `cwebp -resize 1280 0 -q 80 in.png -o out.webp`          | 0 keeps the aspect ratio.                                                                  |

With `-lossless`, `-q` no longer sets quality; it behaves as effort. Use `-z` instead.

### Metadata and colour

`cwebp` writes **no metadata by default**, including ICC profiles. Wide-gamut images will look desaturated if you drop their profile, so pass `-metadata icc` (or `-metadata all` for Exif, XMP and ICC) when the source has one. `cwebp` does not apply Exif orientation to the pixels, so a rotated phone photo converted with the default `-metadata none` comes out sideways; rotate it first or keep the Exif.

### Animation

```sh
gif2webp -lossy -q 70 -m 6 input.gif -o output.webp
img2webp -loop 0 -lossy -q 70 -d 100 frame1.png frame2.png frame3.png -o animation.webp
```

`gif2webp` is lossless unless you add `-lossy` or `-mixed` (per-frame choice); `-min_size` searches for the smallest result. `img2webp` takes explicit frame lists with a per-frame `-d` duration in milliseconds and per-frame `-lossy`/`-lossless`/`-q`. For video clips, [AVIF](/codecs/images/avif/) animations or a real video format are much smaller. `webpmux` edits and inspects frames and chunks. `dwebp` only decodes still images; use `anim_dump` or a viewer for animations.

## Pitfalls

- Lossless is for graphics, screenshots and masters. A lossless WebP of a photograph is several times the size of a lossy one.
- `-q 100` is lossy, not lossless; use `-lossless`.
- The 16,383-pixel limit applies in both modes; downscale or split larger images first.
- WebP files fed from lossy JPEGs compound loss; encode from the original where possible.
- libwebp's lossless decoder had a heap overflow, [CVE-2023-4863](https://www.cve.org/CVERecord?id=CVE-2023-4863), that was exploited in the wild in 2023. If you embed libwebp to decode untrusted uploads, keep it current.

## Related pages

- [AVIF](/codecs/images/avif/) and [JPEG XL](/codecs/images/jxl/) compress better and support more bit depths.
- [JPEG](/codecs/images/jpeg/) and [PNG](/codecs/images/png/) are the formats WebP most often replaces.
- [VP8](/codecs/video/vp8/) is the video codec behind lossy WebP.

## Full option reference

The tables below are the full parameter references for `cwebp`, `img2webp` and `gif2webp` in libwebp 1.6.0. [Reading option tables](/reference/encoder-parameters/) explains the Default column.

## cwebp parameter reference

<details>
<summary>Complete cwebp 1.6.0 options and defaults</summary>

| Parameter and aliases | Type / accepted values         | Default                             | Meaning and limits                                                                                                                       |
| --------------------- | ------------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `-preset`             | enum                           | default                             | Start from a tuned set (default, photo, picture, drawing, icon, text); resets other options, so put it first. |
| `-q`                  | float 0–100                    | 75                                  | Lossy quality 0–100, or lossless effort with -lossless. Disables -z. |
| `-m`                  | integer 0–6                    | 4                                   | Speed/size trade-off, 0 fast to 6 slowest and smallest. Disables -z. |
| `-z`                  | integer 0–9                    | not enabled                         | Lossless preset 0 (fast) to 9 (slowest); implies -lossless and is ignored if -q or -m is given. |
| `-lossless`           | switch                         | off                                 | Encode with lossless VP8L instead of lossy VP8. |
| `-near_lossless`      | integer 0–100                  | 100 (no preprocessing)              | Lossless with pixel preprocessing: 100 is off, lower values discard more detail for smaller files. |
| `-hint`               | enum                           | default                             | Content hint for lossless coding: photo, picture or graph. |
| `-alpha_q`            | integer 0–100                  | 100                                 | Alpha-plane quality 0–100; below 100 makes alpha lossy, independent of -q. |
| `-alpha_method`       | integer 0–1                    | 1                                   | Alpha compression: 0 stores it raw, 1 uses lossless coding. |
| `-alpha_filter`       | enum                           | fast                                | Alpha-plane prediction filter: none, fast or best. |
| `-exact`              | switch                         | off                                 | Keep RGB values under fully transparent pixels instead of zeroing them. |
| `-alpha_cleanup`      | switch                         | off (-exact is off)                 | Hidden obsolete flag that turns -exact off; has no other effect. |
| `-noalpha`            | switch                         | off                                 | Discard the alpha channel. |
| `-blend_alpha`        | hex RGB                        | not enabled                         | Composite onto a hex RGB background (e.g. 0xffffff) and drop transparency. |
| `-segments`           | integer 1–4                    | 4                                   | Number of VP8 segments, 1–4; fewer is faster but less adaptive. |
| `-sns`                | integer 0–100                  | 50                                  | Spatial noise shaping 0–100; higher spends bits on perceptually important areas. |
| `-f`                  | integer 0–100                  | 60                                  | Loop-filter strength 0–100; 0 turns filtering off. |
| `-sharpness`          | integer 0–7                    | 0                                   | Loop-filter sharpness 0 (most smoothing) to 7 (least). |
| `-strong`             | switch                         | on                                  | Use the strong loop filter, which also filters chroma. |
| `-nostrong`           | switch                         | off                                 | Use the simple loop filter, which is faster. |
| `-sharp_yuv`          | switch                         | off                                 | Slower RGB-to-YUV conversion that preserves sharp color edges better. |
| `-partition_limit`    | integer 0–100                  | 0                                   | Allow quality loss 0–100 so the first partition fits its 512 KiB limit. |
| `-size`               | nonnegative integer bytes      | 0 (no target)                       | Target output size in bytes (lossy only); approximate. Raises -pass from 1 to 6. |
| `-psnr`               | nonnegative float dB           | 0 (no target)                       | Target PSNR in dB (around 42 is typical); overrides -size. Lossy only. |
| `-pass`               | integer 1–10                   | 1; becomes 6 for a size/PSNR target | Analysis passes 1–10 for size or PSNR targeting; more is slower and closer to target. |
| `-qrange`             | two integers                   | 0 100                               | Limit the quality search to MIN MAX within 0–100. |
| `-af`                 | switch                         | off                                 | Experimental: adjust filter strength automatically. |
| `-jpeg_like`          | switch                         | off                                 | Experimental: remap parameters so output size roughly matches JPEG's, with less degradation. |
| `-pre`                | integer bitfield 0–7           | 0                                   | Experimental preprocessing bits: 1 segment smoothing, 2 dithering, 4 sharp YUV conversion. |
| `-mt` | switch | off | Use multithreading where available. |
| `-low_memory`         | switch                         | off                                 | Use less memory at the cost of speed. |
| `-s`                  | two positive integers          | not specified                       | Declare raw YUV420 input of WIDTH HEIGHT; not a resize. |
| `-crop`               | four integers x y width height | not enabled                         | Crop to X Y WIDTH HEIGHT before any resize. |
| `-resize`             | two nonnegative integers       | not enabled                         | Resize to WIDTH HEIGHT after cropping; a zero dimension keeps the aspect ratio. |
| `-resize_mode`        | enum                           | always                              | When -resize applies: always, up_only or down_only. |
| `-metadata`           | comma-separated tokens         | none                                | Copy metadata from the input: all, none, exif, icc, xmp (comma-separated). |
| `-o`                  | path                           | none (encode without saving)        | Output file; - writes to stdout. |
| `-d`                  | PGM path                       | not enabled                         | Write the decoded result of the lossy encode to a PGM file for inspection. |
| `-map`                | integer                        | not enabled                         | Print a diagnostic map of encoder statistics; debugging only. |
| `-print_psnr`         | switch                         | off                                 | Print PSNR of the encoded result against the source. |
| `-print_ssim`         | switch                         | off                                 | Print SSIM of the encoded result against the source. |
| `-print_lsim`         | switch                         | off                                 | Print local-similarity score of the encoded result. |
| `-short`              | switch                         | off                                 | Print a condensed statistics summary. |
| `-quiet`              | switch                         | off                                 | Print nothing. |
| `-v`                  | switch                         | off                                 | Print timing and extra diagnostics. |
| `-progress`           | switch                         | off                                 | Print encoding progress as a percentage. |
| `-noasm`              | switch                         | off                                 | Disable assembly optimizations (SSE, NEON); for debugging. |
| `-h`, `-help`         | action                         | not requested                       | Print the short help. |
| `-H`, `-longhelp`     | action                         | not requested                       | Print the full help. |
| `-version`            | action                         | not requested                       | Print the library and libsharpyuv versions, then exit. |
| `--`                  | action                         | not requested                       | Treat the next argument as the input file and stop parsing options. |

</details>

## img2webp parameter reference

<details>
<summary>Complete img2webp 1.6.0 options and defaults</summary>

| Parameter and aliases | Type / accepted values        | Default                      | Meaning and limits                                                                                                   |
| --------------------- | ----------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `-o`                  | path                          | none (encode without saving) | Output animation file; - writes to stdout. |
| `-loop`               | nonnegative integer           | 0 (infinite)                 | Animation loop count; 0 loops forever. |
| `-min_size`           | switch                        | off                          | Spend more time to minimize size; disables inserted keyframes. |
| `-kmin`               | integer                       | 2147483646                   | Minimum frames between keyframes; the default effectively disables inserted keyframes. |
| `-kmax`               | integer                       | 2147483647                   | Maximum frames between keyframes; 1 makes every frame a keyframe, 0 or less disables inserted ones. |
| `-mixed`              | switch                        | off                          | Pick lossy or lossless per frame automatically; per-frame -lossy and -lossless are then ignored. |
| `-near_lossless`      | integer 0–100                 | 100 (no preprocessing)       | Near-lossless preprocessing 0–100 for lossless frames; 100 is off. |
| `-sharp_yuv`          | switch                        | off                          | Slower RGB-to-YUV conversion with better edges, for lossy frames. |
| `-v`                  | switch                        | off                          | Print frame order and timestamps. |
| `-h`, `-help`         | action                        | not requested                | Print help. |
| `-version`            | action                        | not requested                | Print encoder, mux and libsharpyuv versions, then exit. |
| `-d`                  | positive integer milliseconds | 100                          | Display time in milliseconds for this and following frames. |
| `-lossless`           | switch                        | on                           | Encode following frames losslessly (the default). |
| `-lossy`              | switch                        | off                          | Encode following frames lossily. |
| `-q`                  | float 0–100                   | 75                           | Quality 0–100 for following frames; lossless effort when lossless. |
| `-m`                  | integer 0–6                   | 4                            | Speed/size trade-off 0–6 for following frames; 6 is slowest and smallest. |
| `-exact`              | switch                        | off                          | Keep RGB under transparent pixels in following frames; compositing can still discard it. |
| `-noexact`            | switch                        | on                           | Allow following frames to zero RGB under transparent pixels (the default). |

</details>

## gif2webp parameter reference

<details>
<summary>Complete gif2webp 1.6.0 options and defaults</summary>

| Parameter and aliases | Type / accepted values | Default                      | Meaning and limits                                                                                       |
| --------------------- | ---------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------- |
| `-o`                  | path                   | none (encode without saving) | Output WebP file; - writes to stdout. |
| `-lossy`              | switch                 | off                          | Encode lossy instead of the default lossless. |
| `-mixed`              | switch                 | off                          | Pick lossy or lossless per frame automatically. |
| `-near_lossless`      | integer 0–100          | 100 (no preprocessing)       | Near-lossless preprocessing 0–100 for lossless frames; 100 is off. |
| `-sharp_yuv`          | switch                 | off                          | Slower RGB-to-YUV conversion with better edges, for lossy frames. |
| `-q`                  | float 0–100            | 75                           | Lossy quality 0–100, or lossless effort. |
| `-m`                  | integer 0–6            | 4                            | Speed/size trade-off 0–6; 6 is slowest and smallest. |
| `-min_size`           | switch                 | off                          | Spend more time to minimize size; disables inserted keyframes. |
| `-kmin`               | integer                | 9 lossless; 3 lossy/mixed    | Minimum frames between keyframes; libwebp may adjust inconsistent kmin/kmax pairs. |
| `-kmax`               | integer                | 17 lossless; 5 lossy/mixed   | Maximum frames between keyframes; 1 makes every frame a keyframe, 0 or less disables inserted ones. |
| `-f`                  | integer 0–100          | 60                           | Loop-filter strength 0–100 for lossy frames. |
| `-metadata`           | comma-separated tokens | xmp                          | Copy ICC and XMP from the GIF: all, none, icc, xmp (comma-separated). |
| `-loop_compatibility` | switch                 | off                          | Legacy loop-count handling for Chrome 62 and earlier; skips the GIF-to-WebP count adjustment. |
| `-mt` | switch | off | Use multithreading where available. |
| `-v`                  | switch                 | off                          | Print conversion and mux diagnostics. |
| `-quiet`              | switch                 | off                          | Print nothing. |
| `-h`, `-help`         | action                 | not requested                | Print help. |
| `-version`            | action                 | not requested                | Print encoder, mux and libsharpyuv versions, then exit. |
| `--`                  | action                 | not requested                | Treat the next argument as the input GIF and stop parsing options. |

</details>
