Configure NGINX to transparently serve WebP files when supported

ShortPixel Image Optimizer has 2 WebP delivery methods, but sometimes neither of them is able to properly serve your WebP files, especially if you have an NGINX server (which doesn't support .htaccess files). If this is your case, assuming that you have properly configured ShortPixel to generate WebP files, the best option you have is to use NGINX's capabilities and transparently serve the WebP version of your original file when supported.

The solution is straightforward, albeit manual: edit the NGINX config files; either nginx.conf or, if you have a setup with multiple sites, the corresponding config file from /etc/nginx/sites-available.

Stop here! Before reading the instructions, make sure you understand the following:

  • After everything will be configured, your WebP files will be served with the same URL and extension. Your browser will show image.jpg but the image will actually be a WebP file.
  • This solution represents the version we found to be most successful at accomplishing this task. If it doesn't work as expected or if it it doesn't suit your needs, we recommend you to get professional help from an NGINX expert. Hey, if you find something better, drop us a line too!
  • If you are using a CDN, make sure it supports the Vary header and it is correctly configured to serve WebP and/or AVIF from the same URL based on the browser capabilities, so that it knows (and will cache and serve accordingly) that there are 2 different files to be served for the same URL, depending on the Accept header sent by the browser.
    • If you are using a CDN and it doesn't support the Vary header, you shouldn't use this NGINX solution at all, or you may end up serving wrong image formats. Instead, use the ShortPixel's native delivery method "Using the <PICTURE> tag syntax". For more information, visit this page.
    • Examples: bunny.net / Cloudflare

Here's the instructions:

  1. Add this block before the server directive:

    map $http_accept $webp_suffix {
        default "";
        "~*webp" ".webp";
    }
    	

    This sets the $webp_suffix if the browser has the WebP capability.

  2. Add this block inside the server directive:

    location ~* ^(/wp-content/.+)\.(png|jpe?g)$ {
        set $base $1;
        set $webp_uri $base$webp_suffix;
        set $webp_old_uri $base.$2$webp_suffix;
        set $root "<<FULL PATH OF WP-CONTENT PARENT>>";
        root $root;
        add_header Vary Accept;
        if ( !-f $root$webp_uri ) {
            add_header X_WebP_SP_Miss $root$webp_uri;
        }
        try_files $webp_uri $webp_old_uri $uri =404;
    }
    	

    Make sure you replace <<FULL PATH OF WP-CONTENT PARENT>> with the actual absolute path to the wp-content folder, excluding the folder itself. Example: /home/john/public_html/
    The header X_WebP_SP_Miss is not necessary but it's useful for testing - it will set this header if the browser has WebP capabilities but no WebP version of the image was found on disk. You can deactivate it later by commenting out the whole if directive.

  3. Disable ShortPixel's native delivery method. Go to Settings > ShortPixel > Advanced and uncheck the box "Deliver the next generation versions of the images in the front-end":

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.

Still need help? Contact Us Contact Us