Mobile Device Detection

By John Boxall

How do you detect a mobile browser?

One solution relies on inspecting the User-Agent header that a browser sends when it makes an HTTP request. In theory each browser sends an identifiable User-Agent. If we knew what browsers sent which User-Agents then we could identify the mobile browsers!

The problem is there are about a bajillion unique mobile device User-Agents and no clear way to distinguish what makes a User-Agent mobile. But what if we reversed the problem?

How do you detect a desktop browser?

At some point someone smart sat down and decided that desktop User-Agents would be predictable. Turns out most of them include the name of the desktop OS they are running inside the string. If we know what browsers include a desktop OS string then ..!

Enough talk, let's code it.
First we'll setup regular expressions to detect desktop OSs in User-Agents:

import re

RE_DESKTOP = re.compile(r"(windows|linux|os\s+[x9]|solaris|bsd)", re.I)

Next we'll pick the browser User-Agent from an HTTP request and use our regular expressions to test whether it looks like the browser is running on a desktop OS:

def is_desktop(user_agent):
  return bool(
def view(request):
  user_agent = request.headers.get('HTTP_USER_AGENT', '')
  if is_desktop(user_agent):
    return desktop_response()
    return mobile_response()

Like most theories there are a few "except after c" clauses. Specifically:

Let's deal with these wrinkles:
import re

# Some mobile browsers which look like desktop browsers.
RE_MOBILE = re.compile(r"(iphone|ipod|blackberry|android|palm|windows\s+ce)", re.I)
RE_DESKTOP = re.compile(r"(windows|linux|os\s+[x9]|solaris|bsd)", re.I)
RE_BOT = re.compile(r"(spider|crawl|slurp|bot)", re.I)

def is_desktop(user_agent):
  Anything that looks like a phone isn't a desktop.
  Anything that looks like a desktop probably is.
  Anything that looks like a bot should default to desktop.
  return not bool( and \
    bool( or \

def get_user_agent(request):
  # Some mobile browsers put the User-Agent in a HTTP-X header
  return request.headers.get('HTTP_X_OPERAMINI_PHONE_UA') or \
         request.headers.get('HTTP_X_SKYFIRE_PHONE') or \
         request.headers.get('HTTP_USER_AGENT', '')

def view(request):
  user_agent = get_user_agent(request)
  if is_desktop(user_agent):
    return desktop_response()
    return mobile_response()
This code is used to display an image of a desktop or phone below.

Looks like you're browsing on a ...



Your User-Agent (grabbed from the HTTP_USER_AGENT):

CCBot/2.0 (

Doesn't look right?

This is really just the tip of the iceberg of browser detection. Interesting leads:

In the end your method of detection depends on your website. Accept the fact that with User-Agent detection logic there will always be some browsers that slip through the cracks. Decide whether it's worse to show a mobile view to your desktop users or a desktop view to your mobile users and try to do the least amount of damage.

Thanks to Rob Manson for the inspiration!
The code is available on GitHub - forks away!

March 31st Update:

This algorithm has been run against the two hundred and thirty two unique User-Agent strings that have so far visited the site. Of those fifteen were actual mobile device User-Agents, all of which were correctly identified by the updated algorithm. Seven non-mainstream bots and scrapers were misidentified as mobile.


View Comments