Identifying WebKit (aka Safari, iOS WebView, etc.) Users via JavaScript


#1

Yes, I know that you aren’t supposed to do browser sniffing using user agents. Yes, I also know that you should use feature detection instead. Yes, I also ALSO know that even a trained jellyfish can spoof the user agent to bypass whatever clever code one writes. With that out of the way, there are times in the real world when you need to work around some rendering engine quirk in a good enough fashion to satisfy your typical visitor.

One situation I ran into recently required me to identify whether a user is on a WebKit-based rendering engine. This means detecting whether a user is running Safari on desktop or whether they are running any browser on an iOS device.

Quick Note
As you may know, on iOS devices like our iPhones and iPads, Apple doesn’t allow 3rd party web rendering engines. Only WebKit is supported. This means even browsers like Chrome or Edge on iOS use the WebKit-based rendering engine under the covers. This extends to regular apps that provide some sort of web browsing/rendering capability (think clicking on a link in the Twitter, Facebook, Medium, Linkedin, etc. app). Not to go into too much detail, but a lot of the rendering happens through a system control known as WebView which is powered by, you guessed it, WebKit.

In a nutshell, I needed to account for all these situations and ensure I had a simple JavaScript-based solution to identify (as best as possible) whether someone is accessing my web code in a WebKit-based environment. After unsuccessfully searching the web, I decided to look at the user agents provided by all the various entries Safari’s Develop Menu provides for this purpose:

Based on all the user agents that I saw, I decided to pattern match and come up with a few simple checks that would allow me to identify webkit-based browsers (and WebViews). All of this resulted in the following code:

function checkIfWebKit() {
  var ua = navigator.userAgent.toLowerCase();

  var isWebKit = false;

  if ((ua.indexOf("chrome") === ua.indexOf("android")) && ua.indexOf("safari") !== -1) {
    // accessed via a WebKit-based browser
    isWebKit = true;
  } else {
    // check if accessed via a WebKit-based webview
    if ((ua.indexOf("ipad") !== -1) || (ua.indexOf("iphone") !== -1) || (ua.indexOf("ipod") !== -1)) {
      isWebKit = true;
    } else {
      isWebKit = false;
    }
  }

  return isWebKit;
}

This code checks two things. First, it checks to ensure the useragent string does not contain any mention of chrome or android. Second, it checks that the word safari is present. If all of these requirements are met, it is safe to say that the user is on a webkit-based browser or Apple device.

You can see the full markup and code for a simple example here: https://codepen.io/kirupa/pen/LaXoLw?editors=1111

Hope this helps any of you who were looking for something that worked that also didn’t involve a bunch of regex and other “difficult-to-understand-at-a-glance” code!

Cheers,

Kirupa :sunglasses:


#2

I had a bug where webview users would not be detected. I just fixed the code up a few moments ago to address it.