Detect if browser supports WebP format? (server side)
Asked Answered
R

4

32

There is already a thread about Detecting WebP support using client-side. How to detect WebP support using server side?

Rato answered 10/8, 2013 at 16:36 Comment(3)
This assumes that the first time page is loaded it will load .jpg, which kind of breaks the purpose.Rato
You can get it out of the $_SERVER['HTTP_ACCEPT']?Varick
See this post: https://mcmap.net/q/454044/-if-chrome-use-webp/…Actinium
C
83

Today, you should check the accept header for image/webp. All browsers which support WebP will send this as part of their accept string for all requests (images and non-images). In short:

if( strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false ) {
    // webp is supported!
}

(you might want to use preg_match instead and add word boundary checks and case insensitivity, but in the real world this should be fine)


Here's my original answer from several years ago, when the above was not reliable

The "proper" way is to check the accept header which is sent, but a bug in Chrome means that it won't list image/webp even though it does support it.

This is a relevant forum thread: https://groups.google.com/a/webmproject.org/forum/#!topic/webp-discuss/6nYUpcSAORs

which links to this bugtracker: https://code.google.com/p/chromium/issues/detail?id=169182 which in turn links to this one: https://code.google.com/p/chromium/issues/detail?id=267212

End result? While it isn't implemented just yet, soon Google Chrome will explicitly list image/webp as an accepted type for both image and non-image requests. So your script which serves the HTML can check for that. Opera already sends image/webp as part of its standard accept header (again regardless of whether it is an image request or not).

So, you could check like so:

if( strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false || strpos( $_SERVER['HTTP_USER_AGENT'], ' Chrome/' ) !== false ) {
    // webp is supported!
}

(you might want to use preg_match instead and add word boundary checks and case insensitivity, but in the real world this should be fine. You might also want to check for at least version 6 of Chrome, but there's pretty much nobody running an out-of-date version so there's not a lot of point)

Cheltenham answered 10/8, 2013 at 16:53 Comment(7)
Does anyone know if Chrome supports this yet. The original answer was in August of last year.Naomanaomi
@Naomanaomi The thread on the first bug tracker finishes with "I'm seeing the image/webp header for http requests now too" (dated Feb.), so I'd guess so. Well, simplest way to check is to try it!Cheltenham
Works good! I know it is out of scope of the question, but I would like to add that you can check for server support of WebP aswell with gd_info()["WebP Support"], it returns a neat boolean. That way when you have an application that could be deployed on any server you make sure it works both ways ;-)Shockey
Firefox supports WebP images since version 65 but they decided to remove image/webp from Accept header to main document since version 66.Chloechloette
Seems like Firefox sends image/webp in Accept again.Collective
If using flask, something like this will do: 'image/webp' in request.headers.get('Accept')Peat
Note! Safari on a Mac running Big Sur does currently not send image/webp in the accept header. This is how the accept header looks like for me now in Safari: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Sphene
F
2

Dave answer is good but not working with all browsers. I use this method:

function GetBrowserAgentName($user_agent) {
    if (strpos($user_agent, 'Opera') || strpos($user_agent, 'OPR/')) return 'Opera';
    elseif (strpos($user_agent, 'Edge')) return 'Edge';
    elseif (strpos($user_agent, 'Chrome')) return 'Chrome';
    elseif (strpos($user_agent, 'Safari')) return 'Safari';
    elseif (strpos($user_agent, 'Firefox')) return 'Firefox';
    elseif (strpos($user_agent, 'MSIE') || strpos($user_agent, 'Trident/7')) return 'Internet Explorer';
    return 'Other';
}

So after checking browser:

  $BrowserAgentName = GetBrowserAgentName($_SERVER['HTTP_USER_AGENT']);
  If ($BrowserAgentName == 'Chrome' || $BrowserAgentName =='Opera') {
  // webp is supported!

  }

Here I just add Opera and Chrome, you can use deeper detector for browser version and add more agents to your if{}. But you need update this code as browsers update to support image/webp.

Franz answered 26/8, 2016 at 21:41 Comment(1)
You should avoid checking for features by checking the browser; this leads to brittle code which must be manually maintained (as well as being the main reason behind the current insanely complex & self-contradictory user agent headers sent by browsers). That's why I suggest checking the feature directly by looking for "image/webp" in the accept header. All browsers which support webp will list this. The only reason to have a browser check is to temporarily work around a specific, known (and ideally, reported) bug, as in my original answer.Cheltenham
K
1

Just a small thing I've noticed with Facebook - Their facebookexternalhit bot (The one that crawls your website when someone is posting an address to it) doesn't recognizes webp images yet. So i've added the following check to disable the webp images in my client's website for Facebook's bots:

if (strstr(strtolower($_SERVER["HTTP_USER_AGENT"]), "facebook"))
    return false;

Otherwise, when a webpage is shared, it will display the wrong image (the first JPG it will find in the page).

Kristeenkristel answered 3/4, 2020 at 12:17 Comment(0)
C
1

In my case I was using C# Asp.Net MVC. The SO didn't specify tech so I found myself looking at this thread. For anyone else who happens to come across this looking for similar here is the solution I came up with:

bool acceptsWebP = Request.AcceptTypes.Contains("image/webp");
string ext = Path.GetExtension(image.ImagePath);
string webP = image.ImagePath.Replace(ext, ".webp");
if (acceptsWebP)
{
    <img class="img-fluid lazy" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" data-src="\Uploads\@webP" alt="@item.ProductName">
}
else
{
    <img class="img-fluid lazy" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" data-src="\Uploads\@image.ImagePath" alt="@item.ProductName">
}
Craddock answered 30/10, 2020 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.