I am trying to server webp images to supporting browsers by using the code below. I have already .webp images in addition to .png and .jpg images of the same file.

For example if have an image named vacation.jpg, i also have vacation.jpg.webp.

The code below works but it was overwriting my other location blocks before i switched to a CDN. Now i am using CDN that code block has no effect, no WEBP images in response and also not overwriting my other location blocks.

Here is how to do it:

Add to the /etc/nginx/mime.types

“image/webp webp”

Add to the main nginx.conf file:

map $http_accept $webp_suffix {
  default “”;
  “~*webp” “.webp”;

Add to the server block:

location ~* ^/wp-content/.+\.(png|jpg)$ {
  add_header Vary Accept;
  try_files $uri$webp_suffix $uri =404;

Restart or reload nginx.

Example of my other location blocks:

Disable Hot-Linking

location ~ .(ico|gif|png|jpe?g|svg|webp)$ {
    valid_referers none blocked example.com *.example.com;
    if ($invalid_referer) {
       return 403;

Allow Cross-Origin For Static Domain Files

    location ~ \.(ico|gif|png|jpe?|svg|webp|eot|otf|ttf|ttc|woff|woff2|ogg|js|css|font.css)$ {
        add_header Access-Control-Allow-Origin "*";
        #gzip_vary on;
        expires 30d;
  • 2
    The edit to the question makes it completely different question. When you have a CDN, you cannot do what you are trying without fixing URLs in your CMS. Oct 25, 2016 at 5:08

1 Answer 1


The original question was changed completely after I posted this answer and this answer is no longer relevant to the question.

Even though your intention is good, the fact that you do a 302 redirect when a .webp version is found, makes the gain smaller.

The redirect adds two round-trips in latency to picture loading time, and if the picture is small enough, it will take longer to receive the .webp version than the original.

To fix this, you should generate the URLs in your website code directly.

However, to answer your current question, you can use this set of rules:

location ~ ^(/wp-content.+)\.(jpe?g|png)$ {
    set $red Z;

    if ($http_accept ~* "webp") {
        set $red A;

    if (-f $request_filename.webp) {
        set $red "${red}B";

    if ($red = "AB") {
        add_header Vary Accept;
        return 302 $1.webp;

The idea here is that one has already captured the first part of the filename in your location directive. Therefore the first part of the new location is in the $1 regex capture variable. So, one simply uses the $1 in the return directive. I use return here, since it is faster than rewrite.

  • Thanks for the explanation. How about the rewrite (.*) $1.webp redirect; ? And also some files don't have .webp version with the new plugin i use. (it doesn't create them if they will become larger than the current image) In the current code if i end up with the .webp extension only in the url. Is there a way to modify it so we can continue to server jpg or png when webp is not available? Oct 24, 2016 at 1:16
  • You can use the rewrite version too, it is just slower. For the other question, I don't think you cannot do that without nginx lua scripting. You should also have included that in your original question and not as a surprise question. However, the best way to address all these things is to fix your CMS so that it automatically generates proper URLs. Making a nginx config hack is not a good solution in the long run. Oct 24, 2016 at 9:32
  • I have changed the question and the code. Thanks for looking into this by the way. Let me ask you another question. Normally Wordpress images are like this: example.com/wp-content/uploads/2016/10/image.jpg. How can i rewrite it to make like example.com/image.jpg? Oct 24, 2016 at 23:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.