# Frequently Asked Questions

## What is WebP? Why should I use it?

WebP is a method of lossy and lossless compression that can be used on a large
variety of photographic, translucent and graphical images found on the web.
The degree of lossy compression is adjustable so a user can choose the
trade-off between file size and image quality. WebP typically achieves an
average of 30% more compression than JPEG, without loss of image quality (see
the [WebP Lossy Study](https://developers.google.com/speed/webp/docs/webp_study)). WebP lossless images are
26% smaller in size compared to PNGs (see the
[WebP Lossless and Alpha Study](https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study)).

The WebP format essentially aims at creating smaller, better looking images
that can help make the web faster.

## Which web browsers natively support WebP?

Webmasters interested in improving site performance can easily create
optimized WebP alternatives for their current images, and serve them on a
targeted basis to browsers that support WebP.

- WebP lossy support
  - Google Chrome (desktop) 17+
  - Google Chrome for Android version 25+
  - Microsoft Edge 18+
  - Firefox 65+
  - Opera 11.10+
  - Native web browser, Android [4.0+](https://developer.android.com/guide/topics/media/media-formats#image-formats) (ICS)
  - Safari 14+ (iOS 14+, macOS Big Sur+)
- WebP lossy, lossless \& alpha support
  - Google Chrome (desktop) 23+
  - Google Chrome for Android version 25+
  - Microsoft Edge 18+
  - Firefox 65+
  - Opera 12.10+
  - Native web browser, Android 4.2+ (JB-MR1)
  - Pale Moon 26+
  - Safari 14+ (iOS 14+, macOS Big Sur+)
- WebP Animation support
  - Google Chrome (desktop and Android) 32+
  - Microsoft Edge 18+
  - Firefox 65+
  - Opera 19+
  - Safari 14+ (iOS 14+, macOS Big Sur+)

See also:

- [Wikipedia WebP article](https://en.wikipedia.org/wiki/WebP#Support)
- [Can I use](https://caniuse.com/webp)

## How can I detect browser support for WebP?

You'll want to serve WebP images only to clients that can display them
properly, and fall back to legacy formats for clients that can't. Fortunately
there are several techniques for detecting WebP support, both on the
client-side and server-side. Some CDN providers offer WebP support detection
as part of their service.

### Server-side content negotiation via Accept headers

It is common for web clients to send an "Accept" request header, indicating
which content formats they are willing to accept in response. If a
browser indicates in advance that it will "accept" the *image/webp* format,
the web server knows it can safely send WebP images, greatly simplifying
content negotiation. See the following links for more information.

- [Deploying New Image Formats on the Web](https://www.igvita.com/2012/12/18/deploying-new-image-formats-on-the-web/)
- [Serving WebP Images to Visitors Using HTML Elements](https://www.digitalocean.com/community/tutorials/how-to-create-and-serve-webp-images-to-speed-up-your-website#step-5-%E2%80%94-serving-webp-images-to-visitors-using-html-elements)

### Modernizr

**[Modernizr](https://modernizr.com/)** is a JavaScript library for conveniently detecting HTML5 and
CSS3 feature support in web browsers. Look for the properties
*Modernizr.webp* , *Modernizr.webp.lossless* , *Modernizr.webp.alpha* and
*Modernizr.webp.animation*.

### HTML5 `<picture>` element

HTML5 supports a `<picture>` element, which allows you to list multiple,
alternative image targets in priority order, such that a client will request
the first candidate image that it can display properly. See
[this discussion on HTML5 Rocks](https://www.html5rocks.com/en/tutorials/responsive/picture-element/#toc-file-type). The `<picture>` element is
[supported by more browsers](https://caniuse.com/#search=picture) all the time.

### In your own JavaScript

Another detection method is to attempt to decode a very small WebP image that
uses a particular feature, and check for success. Example:

    // check_webp_feature:
    //   'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
    //   'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
    function check_webp_feature(feature, callback) {
        var kTestImages = {
            lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
            lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
            alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
            animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
        };
        var img = new Image();
        img.onload = function () {
            var result = (img.width > 0) && (img.height > 0);
            callback(feature, result);
        };
        img.onerror = function () {
            callback(feature, false);
        };
        img.src = "data:image/webp;base64," + kTestImages[feature];
    }

Note that image-loading is non-blocking and asynchronous. This means that any
code that depends on WebP support should preferably be put in the callback
function.

## Why did Google release WebP as open source?

We deeply believe in the importance of the open source model. With WebP in
open source, anyone can work with the format and suggest improvements. With
your input and suggestions, we believe that WebP will become even more useful
as a graphic format over time.

## How can I convert my personal images files to WebP?

You can use the WebP command line utility to convert your personal image files
to WebP format. See [Using WebP](https://developers.google.com/speed/webp/docs/using) for more details.

If you have many images to convert you can use your platform's shell to
simplify the operation. For example, to convert all jpeg files in a folder try
the following:

Windows:

    > for /R . %I in (*.jpg) do ( cwebp.exe %I -o %~fnI.webp )

Linux / macOS:

    $ for F in *.jpg; do cwebp $F -o `basename ${F%.jpg}`.webp; done

## How can I judge WebP image quality for myself?

Currently, you can view WebP files by converting them into a common format
that uses lossless compression, such as PNG, and then view the PNG files in
any browser or image viewer. To get a quick idea of WebP quality, see the
[Gallery](https://developers.google.com/speed/webp/gallery) on this site for side-by-side photo
comparisons.

## How do I get the source code?

The converter code is available on the
[downloads section](https://developers.google.com/speed/webp/download) of the WebP open-source project
page. The code for the lightweight decoder and the VP8 specification are on
the [WebM site](https://www.webmproject.org/). See the
[RIFF Container](https://developers.google.com/speed/webp/docs/riff_container) page for the container
specification.

## What is the maximum size a WebP image can be?

WebP is bitstream-compatible with VP8 and uses 14 bits for width and height.
The maximum pixel dimensions of a WebP image is 16383 x 16383.

## What color spaces does the WebP format support?

Consistent with the VP8 bitstream, **lossy WebP** works exclusively with an
8-bit Y'CbCr 4:2:0 (often called YUV420) image format. Please refer to Section
2, "[Format Overview](https://datatracker.ietf.org/doc/html/rfc6386#section-2)"
of RFC 6386,
[VP8 Data Format and Decoding Guide](https://datatracker.ietf.org/doc/html/rfc6386)
for more detail.

**Lossless WebP** works exclusively with the RGBA format. See the
[WebP Lossless Bitstream specification](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification).

## Why does my lossless WebP file differ from the original?

The
[Simple Encoding API](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)
functions (`WebPEncodeLosslessRGB()`, `WebPEncodeLosslessBGR()`,
`WebPEncodeLosslessRGBA()`, `WebPEncodeLosslessBGRA()`), use the library's
default settings. For lossless this means 'exact' is disabled. RGB values in
fully transparent areas (that is, areas with alpha values equal to `0`) will be
modified to improve compression. To avoid this, use `WebPEncode()` and set
`WebPConfig::exact` to `1`. See the
[Advanced Encoding API](https://developers.google.com/speed/webp/docs/api#advanced_encoding_api)
documentation.

## Can a WebP image grow larger than its source image?

Yes, usually when converting from a lossy format to WebP lossless or
vice versa. This is mainly due to the colorspace difference (YUV420 vs ARGB)
and the conversion between these.

There are three typical situations:

1. If the source image is in lossless ARGB format, the spatial downsampling to YUV420 will introduce new colors that are harder to compress than the original ones. This situation can typically happen when the source is in PNG format with few colors: converting to lossy WebP (or, similarly to a lossy JPEG) will potentially result in a larger file size.
2. If the source is in lossy format, using lossless WebP compression to capture the lossy nature of the source will typically result in a larger file. This is not particular to WebP, and can occur when converting a JPEG source to lossless WebP or PNG formats, for instance.
3. If the source is in lossy format and you are trying to compress it as a lossy WebP with higher quality setting. For instance, trying to convert a JPEG file saved at quality 80 to a WebP file with quality 95 will usually result in a larger file, even if both formats are lossy. Assessing the source's quality is often impossible, so it is advised to lower the target WebP quality if the file size is consistently larger. Another possibility is to avoid using the quality setting, and instead target a given file size using the `-size` option in the `cwebp` tool, or the equivalent API. For instance, targeting 80% of the original file size might prove more robust.

Note that converting a JPEG source to lossy WebP, or a PNG source to lossless
WebP are not prone to such file size surprises.

## Does WebP support progressive or interlaced display?

WebP does not offer a progressive or interlaced decoding refresh in the JPEG or
PNG sense. This is likely to put too much pressure on the CPU and memory of the
decoding client as each refresh event involves a full pass through the
decompression system.

On average, decoding a progressive JPEG image is equivalent to decoding the
*baseline* one 3 times.

Alternatively, WebP offers *incremental* decoding, where all available incoming
bytes of the bitstream are used to try and produce a displayable sample row as
soon as possible. This both saves memory, CPU and re-paint effort on the
client while providing visual cues about the download status. The incremental
decoding feature is available through the
[Advanced Decoding API](https://developers.google.com/speed/webp/docs/api#advanced_decoding_api).

## How do I use the libwebp Java bindings in my Android project?

WebP includes support for JNI bindings to the simple encoder and decoder
interfaces in the `swig/` directory.

Building the library in [Eclipse](https://www.eclipse.org/):

1. Make sure you have the [ADT plugin](https://developer.android.com/sdk/installing/installing-adt.html) installed along the with NDK tools and your NDK path is set correctly (**Preferences** \> **Android** \> **NDK**).
2. Create a new project: **File** \> **New** \> **Project** \> **Android
   Application Project**.
3. [Clone](https://www.webmproject.org/code/#libwebp-webp-image-library) or unpack libwebp to a folder named `jni` in the new project.
4. Add `swig/libwebp_java_wrap.c` to the `LOCAL_SRC_FILES` list.
5. Right-click on the new project and select **Android Tools** \> **Add
   Native Support ...** to include the library in your build.
6. Open the project properties and go to **C/C++ Build** \> **Behaviour** . Add
   `ENABLE_SHARED=1` to the `Build (Incremental build)` section to build
   libwebp as a shared library.

   **Note** Setting `NDK_TOOLCHAIN_VERSION=4.8` will in general improve
   32-bit build performance.
7. Add `swig/libwebp.jar` to the `libs/` project folder.

8. Build your project. This will create `libs/<target-arch>/libwebp.so`.

9. Use `System.loadLibrary("webp")` to load the library at runtime.

Note that the library can be built manually with `ndk-build` and the included
`Android.mk`. Some of the steps described above can be reused in that case.

## How do I use libwebp with C#?

WebP can be built as a DLL which exports the libwebp API. These functions can
then be imported in C#.

1. Build libwebp.dll. This will set WEBP_EXTERN properly to export the API
   functions.

       libwebp> nmake /f Makefile.vc CFG=release-dynamic

2. Add libwebp.dll to your project and import the desired functions.
   Note if you use the
   [simple API](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)
   you should call `WebPFree()` to free any buffers returned.

       [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)]
       static extern int WebPEncodeBGRA(IntPtr rgba, int width, int height, int stride,
                                        float quality_factor, out IntPtr output);
       [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)]
       static extern int WebPFree(IntPtr p);

       void Encode() {
         Bitmap source = new Bitmap("input.png");
         BitmapData data = source.LockBits(
             new Rectangle(0, 0, source.Width, source.Height),
             ImageLockMode.ReadOnly,
             PixelFormat.Format32bppArgb);
         IntPtr webp_data;
         const int size = WebPEncodeBGRA(data.Scan0,
                                         source.Width, source.Height, data.Stride,
                                         80, out webp_data);
         // ...
         WebPFree(webp_data);
       }

## Why should I use animated WebP?

**Advantages of animated WebP compared to animated GIF**

1. WebP supports 24-bit RGB color with an 8-bit alpha channel, compared to
   GIF's 8-bit color and 1-bit alpha.

2. WebP supports both lossy and lossless compression; in fact, a single
   animation can combine lossy and lossless frames. GIF only supports
   lossless compression. WebP's lossy compression techniques are well-suited
   to animated images created from real-world videos, an increasingly popular
   source of animated images.

3. WebP requires fewer bytes than GIF^[1](https://developers.google.com/speed/webp/faq#fn1)^.
   Animated GIFs converted to lossy WebPs are 64% smaller, while lossless
   WebPs are 19% smaller. This is especially important on mobile networks.

4. WebP takes less time to decode in the presence of seeking. In
   [Blink](https://www.chromium.org/blink), scrolling or changing tabs can
   hide and show images, resulting in animations being paused and then
   skipped forward to a different point. Excessive CPU usage that results in
   animations dropping frames can also require the decoder to seek forward in
   the animation. In these scenarios, animated WebP takes 0.57x as much total
   decode time^[2](https://developers.google.com/speed/webp/faq#fn2)^ as GIF, resulting in less jank
   during scrolling and faster recovery from CPU utilization spikes. This is
   due to two advantages of WebP over GIF:

   - WebP images store metadata about whether each frame contains alpha,
     eliminating the need to decode the frame to make this determination.
     This leads to more accurate inference of which previous frames a given
     frame depends on, thereby reducing unnecessary decoding of previous
     frames.

   - Much like a modern video encoder, the WebP encoder heuristically adds
     key-frames at regular intervals (which most GIF encoders do not do).
     This dramatically improves seeking in long animations. To facilitate
     inserting such frames without significantly increasing image size, WebP
     adds a
     ['blending method' flag](https://developers.google.com/speed/webp/docs/riff_container#animation)
     for each frame in addition to the frame disposal method that GIF uses.
     This allows a keyframe to draw as if the entire image had been cleared
     to the background color without forcing the previous frame to be
     full-size.

**Disadvantages of animated WebP compared to animated GIF**

1. In the absence of seeking, straight-line decoding of WebP is more
   CPU-intensive than GIF. Lossy WebP takes 2.2x as much decode time as
   GIF, while lossless WebP takes 1.5x as much.

2. WebP support is not nearly as widespread as GIF support, which is
   effectively universal.

3. Adding WebP support to browsers increases the code footprint and
   attack surface. In Blink this is approximately 1500 additional lines
   of code (including the WebP demux library and Blink-side WebP image
   decoder). Note that this problem could be reduced in the future if
   WebP and WebM share more common decoding code, or if WebP's
   capabilities are subsumed in WebM's.

**Why not simply support WebM in `<img>`?**

It may make sense long-term to support video formats inside the `<img>`
tag. However, doing so now, with the intent that WebM in `<img>` can fill
the proposed role of animated WebP, is problematic:

1. When decoding a frame that relies on previous frames, WebM requires
   50% more memory than animated WebP to hold the minimum number of
   previous frames^[3](https://developers.google.com/speed/webp/faq#fn3)^.

2. Video codec and container support varies widely across browsers and
   devices. To facilitate automatic content transcoding (e.g. for
   bandwidth-saving proxies), browsers would need to add accept headers
   indicating what formats their image tags support. Even this might be
   insufficient, as MIME types like "video/webm" or "video/mpeg" still
   don't indicate the codec support (e.g. VP8 vs. VP9). On the other
   hand, the WebP format is effectively frozen, and if vendors who ship
   it agree to ship animated WebP, the behavior of WebP across all UAs
   should be consistent; and since the "image/webp" accept header is
   already used to indicate WebP support, no new accept header changes
   are necessary.

3. The [Chromium](https://www.chromium.org/) video stack is optimized for
   smooth playback, and assumes there's only one or two videos playing at a
   time. As a result, the implementation is aggressive in consuming system
   resources (threads, memory, etc.) to maximize playback quality. Such an
   implementation does not scale well to many simultaneous videos and would
   need to be redesigned to be suitable for use with image-heavy webpages.

4. WebM does not currently incorporate all the compression techniques
   from WebP. As a result,
   [this image](https://storage.googleapis.com/downloads.webmproject.org/webp/images/dancing-banana.gif)
   compresses significantly better with WebP than the alternatives:

   - [GIF (85 KB)](https://storage.googleapis.com/downloads.webmproject.org/webp/images/dancing-banana.gif)
   - [WebM with alpha (32 KB)](https://storage.googleapis.com/downloads.webmproject.org/webp/images/dancing_banana2.webm)
   - [Lossless animated WebP (5 KB)](https://storage.googleapis.com/downloads.webmproject.org/webp/images/dancing_banana2.lossless.webp) ^[4](https://developers.google.com/speed/webp/faq#fn4)^

*** ** * ** ***

^1^ For all comparisons between animated GIF and animated WebP, we
used a corpus of about 7000 animated GIF images taken randomly from the web.
These images were converted to animated WebP using the 'gif2webp' tool using
default settings (built from the latest
[libwebp source tree](https://chromium.googlesource.com/webm/libwebp)
as of 10/08/2013). The comparative numbers are the average values across these
images.

^2^ The decode times were computed using the latest libwebp + [ToT
Blink](https://chromium.googlesource.com/chromium/blink) as of 10/08/2013
using a [benchmark tool](https://codereview.chromium.org/23532077). "Decode time
with seeking" is computed as "Decode the first five frames, clear the frame
buffer cache, decode the next five frames, and so forth".

^3^ WebM keeps 4 YUV reference frames in memory, with each frame
storing (width+96)\*(height+96) pixels. For YUV 4:2:0, we need 4 bytes per 6
pixels (or 3/2 bytes per pixel). So, these reference frames use
`4*3/2*(width+96)*(height+96)` bytes of memory. WebP on the other hand would
only need the previous frame (in RGBA) to be available, which is
`4*width*height` bytes of memory.

^4^ Animated WebP rendering requires Google Chrome version 32+