Modern Mobile Redirect Using .htaccess

The following set of rewrite rules will redirect all Android, Blackberry, iOS, Windows and WebOS devices to a specific mobile directory on your website. Additionally, it will redirect Google’s mobile crawler – according to Google search spam czar Matt Cutts this is perfectly acceptable and even somewhat encourage.

To implement these rules:

  1. Replace “mobiledirectoryhere” with the path to your mobile site. If your mobile site is located in a subdirectory, use the full URL (including “http://”) and you can omit the first RewriteCond.
  2. Then copy & paste the ruleset into the site’s .htaccess file or the main apache configuration.

Rationale

Since the last time I wrote about mobile browser detection and redirection in 2009 the mobile device landscape has changed once again. Smartphones dominate the mobile browsing landscape and feature phones are almost not existant in server logs.

The old redirection rules I posted attempt to redirect every mobile phone under the sun. At this point in 2011, it’s probably safe to completely ignore ancient phones and simplify your Apache rules in the process.

95 thoughts on “Modern Mobile Redirect Using .htaccess

  1. Hey Ryan,

    Good call – Lean & fast. If you’re looking for something a little more targeted (eg Android Tablets) check out Handset Detection (www.handsetdetection.com). It uses explicit http header matching against a database of known devices.

    Cheers
    Richard

  2. Hi Ryan,

    Thanks for posting this! Unfortunately I’ve been having a beastly time setting up a mobile redirect from my main site to a subdomain on my main site (http://m.mysite.com). The kicker is I need deep links on the main site to automatically forward to the matching page on m.mysite.com for mobile viewers.

    What would be the best way to accomplish this?

  3. Thank you for the .htaccess inserts… It worked perfectly. A heck of alot better than using a bloated PHP or Javascript code that ultimately slows it down. When using mobile devices, lag time is not easily tolerated.

  4. Ryan,

    This code is a huge help for my websites. I really appreciate the simplicity and speed. I wondered if I could change out “ipad” (I would like ipad to see my desktop version) with “palmos” and add in a few more options from your 2009 post as well?

    Also, does “webos” essentially catch most of the other handheld devices?

    1. If you want iPads to see the desktop version of your site, you can just removed “ipad”.

      “webos” covers most palm & HP devices running webOS, as far as I understand you’ll have to include “palmos” to catch early webOS devices like the Palm Pre and Pixi.

      Hope that helps.

  5. Thanks for posting this Ryan !

    Would the bypass-option still work ? (I have no experience with cookies yet :P)

    RewriteCond %{HTTP_COOKIE} !^.*bypass.*$ [NC]

  6. Maybe a stupid question but what am I doing wrong here? I changed ‘mobiledirectoryhere’ with my subdomain ‘http://m.mysite.com’ and added the code. Now my site doesn’t open on iPhone with an error message ‘Safari cannot open the page because too many redirects occurred’. Thanks

          1. Did you get a resolution to the “too many redirect” problem?  I’m having the same issue?

            Thanks

          2. I’m still having the same issue as well. If I can find a different solution I’ll let you guys know. Please post here if you find a solution also. Thanks!

          3. I responded to kaboom’s question above: http://ohryan.ca/blog/2011/01/21/modern-mobile-redirect-using-htaccess/#comment-266136097

            Hope that helps.

        1. I must be doing something wrong I guess..

          These are the 4 lines that my .htaccess file contains:

          RewriteEngine on
          RewriteCond %{REQUEST_URI} !^/http://m.mysite.com/.*$
          RewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]
          RewriteRule ^(.*)$ /http://m.mysite.com/ [L,R=302]

          1. I must be editing the wrong htaccess file I guess..

            I have 4 websites in the same hosting account (each of them in separate folders such as /www/mysite1, /www/mysite2, etc) and I only need to edit redirect for one of the websites. So the htaccess file I’m editing is the one in the following folder /www/mysite1 (or /public_html/mysite1).

            I noticed that there are other htaccess files, not in website folders. One is in /www (and /public_html) folder, and in other various folders such as /www/_private, /www/_vti_bin, /www/_vti_cnf, /www/_vti_pvt.

            Sorry if it looks a dumb question but could someone guide me please?

            Thanks!

          2. The REQUEST_URI portion of the rule is matching the request URI portion of the request (ie. everything after the host name). That first line is stopping a redirection loop when you are redirecting mobile request to a subdirector. Since you are redirecting to a subdomain, you wouldn’t need that line. Also, the preceding slash in the last line is not right. 

            Try something like this:

            RewriteEngine onRewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]RewriteRule ^(.*)$ http://m.mysite.com/ %5BL,R=302%5D

          3. Hi Ryan,

            Thank you very much for taking the time to help us all out. I tried your code above but it didn’t work for me, and when mobile users attempted to go to the website I would get a 505 server error. Therefore I used the following code instead:

            RewriteEngine On#redirect mobile browsersRewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$RewriteRule ^(.*)$ http://mywebsite/mobile/index.html [R=301]RewriteCond %{HTTP_USER_AGENT} ^.*iPad.*$RewriteRule ^(.*)$ http://mywebsite/mobile/index.html [R=301]RewriteCond %{HTTP_USER_AGENT} ^.*BlackBerry.*$RewriteRule ^(.*)$ http://mywebsite/mobile/index.html [R=301]RewriteCond %{HTTP_USER_AGENT} ^.*Palm.*$RewriteRule ^(.*)$ http://mywebsite/mobile/index.html [R=301]

            Inside the new mobile folder I created a new .htaccess file which has the RewriteEngine Off so that there wouldn’t be the redirect issue. Despite the fact a different solution has come up, I would much rather use your solution because it covers so many different types of mobile devices. Do you have any idea what I was doing wrong when trying to use your solution? I used your most recent post verbatim, except adding in my mobile website location for the URL:

            RewriteEngine onRewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]RewriteRule ^(.*)$http://m.mysite.com/ [L,R=302]

            If you have any helpful hints I am all ears!

            – Will

  7. Hi Ryan, I don’t know what is it that i’m doing, but it’s timing out on me (too many redirects). May be because I’m forcing the index? My main site is site/EN/index.html and site/ES/index.html. I’m using a 301 redirect to force it.

    1. This is the fix to stop the redirect root.

      RewriteCond %{REQUEST_URI} ^/(stats/|missing.html|failed_auth.html|error/).* [NC]
      RewriteRule .* – [L]
       
      RewriteCond %{ENV:REDIRECT_STATUS} 200
      RewriteRule .* – [L]

  8. Great post Ryan, but I have one question.  How do you make that RewriteCond negative for non mobile browsers?

    For example, this doesn’t work. I get internal server errors:
    [code]

    RewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]

    RewriteRule ^cloud /free-cloud-assessment.php [L,R=301]

    RewriteCond %{HTTP_USER_AGENT} !”android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]

    RewriteRule ^cloud /what-is-the-cloud.php [L,R=301]
    [/code]

    How do you take /cloud and send it to one destination for mobile and another destination for non-mobile browsers?

    1. Like you said on twitter, putting the non-mobile version in /cloud and redirecting mobile UAs somewhere else, works. 

      But you answer your question, I think a negative RewriteCond would look something like: 

      RewriteCond %{HTTP_USER_AGENT} “!/android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile/”

  9. Thanks for the post… I’ve found that this is the easiest and most concise redirect for mobile sites, from what I’ve seen. However, how would I make it so that the file structure is preserved? Here’s my code right now:

    RewriteCond %{REQUEST_URI} !^/mobile/.*$RewriteCond %{HTTP_USER_AGENT} “android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]RewriteRule ^(.*)$ /mobile/ [L,R=302]

    I’m trying to make it, so that, for example, if someone on a mobile browser types in http://www.mmisi.com/companies.php, they get redirected to http://www.mmisi.com/mobile/companies.php, instead of http://www.mmisi.com/mobile. Thanks.

  10. Just a note, I’m with the Webfaction host and for my static/PHP site I needed this extra line at the top of my .htaccess file to make your script work:

    RewriteEngine OnThanks much for your script, it works great!

    1. Hi,
      Its a very helpful script, pardon my naivety but where would one add the url for the mobile site to which we want to redirect to?
      Thanks for the example.

  11. This is the best (and lightest way) I’ve seen to do this yet.  Nice snippet!  Quick question though…

    How do you handle a person that wants to view the full or “desktop” version of the site on their mobile device?

    1. Thanks! 

      The easiest way to allow a person to view the desktop version would be to allow them to opt-out of the mobile redirect with a cookie. 1. Create a link that sets a cookie (server-side or onclick with javascript); 2. check for the cookie in the re-write rule (See doc).

      1. In regards to desktop view, there is a better way then cookie staff (what if cookies are disabled?), simply go for MVC and create 3 pages: one for desktop in root (index.php with htaccess staff for mobile), second for mobile with htaccess for desktop (/mobile/index.php – here put link with get var, holding desktop value and check its value in controller class for mobile, if it is true go to third point), third create folder FULL VIEW or whatever, and here in htaccess override rule from root htaccess (without that mobile detector) and put path to MVC classes from root: _autoload($class_name) ./class_name.php”;}. Just for those who are not familiar with MVC, we have the same index.php as in root and still using main classes, just htaccess is different! Good Luck

  12. Hi Ryan, Like some others in this discussion, I’m having problems with a “Too many redirects” error when trying to access my mobile subdirectory. Here is my code:

    RewriteEngine onRewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]RewriteRule ^(.*)$ /http://marilynhorsch.com/mobilesite/mobilesite.html/[L,R=302]

    Any help is appreciated.
    Thanks

    1. Hi Mike,

      This worked for me:

      RewriteEngine On
      #redirect mobile browsers
      RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
      RewriteRule ^(.*)$ http://smstaging.stanford.edu/pem/mobile/index.html [R=301]
      RewriteCond %{HTTP_USER_AGENT} ^.*iPad.*$
      RewriteRule ^(.*)$ http://smstaging.stanford.edu/pem/mobile/index.html [R=301]
      RewriteCond %{HTTP_USER_AGENT} ^.*BlackBerry.*$
      RewriteRule ^(.*)$ http://smstaging.stanford.edu/pem/mobile/index.html [R=301]
      RewriteCond %{HTTP_USER_AGENT} ^.*Palm.*$
      RewriteRule ^(.*)$ http://smstaging.stanford.edu/pem/mobile/index.html [R=301]

      Inside the new mobile folder I created a new .htaccess file which has the RewriteEngine Off so that there wouldn’t be the redirect issue. However this won’t cover all mobile devices. If you have a better solution let me know.

  13. Thank you for the simple implementation. However I am trying to implement the above code with a htaccess code used to eliminate the file extension from the webpage filename. see below:

    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^XXXXXX.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.XXXXXX.com$
    RewriteRule ^/?$ “http://www.XXXXXX.com” [R=301,L]
    RewriteRule (.*).htm$ $1.php [L,QSA]
    Options +FollowSymLinks
    Options -Multiviews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([^.]+)$ $1.php [NC,L]
    RewriteEngine On
    Options -MultiViews

    With the above code I am unable to visit the mobile website in a subdirectory called m.XXXXXX.com

    any suggestions

    1. I was having looping redirect issues with looping on a site built using a PHP framework that redirects all $1 page requests to /index.php/$1 (CodeIgniter, WordPress and many other content management systems and frameworks do this). The above fixes weren’t working for me (was having issues with resources not loading) and putting a separate .htaccess file in a subdirectory wasn’t really an option because of the site structure, but built this solution that seems to work well:

      #modified mobile redirect
      RewriteCond $1 !^(index.php|_assets|robots.txt|favicon.ico|apple-touch-icon|mobile)RewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|symbian|webos” [NC]RewriteRule ^(.*)$ /mobile/ [L,R=301]

      #stock framework/CMS redirect
      RewriteCond $1 !^(index.php|_assets|robots.txt|favicon.ico|apple-touch-icon)RewriteRule ^(.*)$ /index.php/$1 [L] 

      Note that the RewriteCond from the CMS has been repurposed in the mobile detection snippet with the addition of the /mobile path to the end to prevent looping or resource request redirection. The snippet is slightly modified, I added symbian to the user-agent string to detect Nokia browsers (still quite popular outside the US) and changed the redirect to a permanent (301) redirect.

  14. I am sooooo a NuB to this. I need to know what line to put into .htaccess for the following.

    I have the regular site (flash).  but need any and all ios to goto /ios/index.html

    Am I totally missing something from your main post?

    Thank  you, I have been looking for assistance for a few months. (now know it is doable in .htaccess file.

    btw.  (using standard html, no php)

  15. Hi Ryan,

    I’ve been having a few issues with implementing your solution. My .htaccess file is:

    ————————————-
    AddType video/ogg  .ogvAddType video/mp4  .mp4AddType video/webm .webmSetEnvIfNoCase Request_URI .(og[gv]|mp4|m4v|webm)$ no-gzip dont-varyRewriteEngine OnRewriteCond %{REQUEST_URI} !^http://mywebsite/mobile.html.*$RewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]RewriteRule ^(.*)$ http://mywebsite/mobile.html [L,R=302]
    ————————————-

    (without the dashes in the .htaccess file). The 4 top lines are because I am using “Video or Everybody” to play my video on the website and it requires that in there. I have been using an iPhone to test and it gives me the following message:

    “Safari cannot open the page because too many redirects occured”

    But it does successfully take me from the mywebsite/index.html page to the mywebsite/mobile.html page, it just doesn’t render and I get that error message above. Do you know how I can fix this?

  16. Hi Ryan,

    I’ve been having a few issues with implementing your solution. My .htaccess file is:

    ————————————-
    AddType video/ogg  .ogv

    AddType video/mp4  .mp4

    AddType video/webm .webm

    SetEnvIfNoCase Request_URI .(og[gv]|mp4|m4v|webm)$ no-gzip dont-vary

    RewriteEngine On

    RewriteCond %{REQUEST_URI} !^http://smstaging.stanford.edu/pem/mobile.html.*$
    RewriteCond %{HTTP_USER_AGENT} “android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile” [NC]

    RewriteRule ^(.*)$ http://smstaging.stanford.edu/pem/mobile.html [L,R=302]

    ————————————-

    (without the dashes in the .htaccess file). The 4 top lines are because I am using “Video or Everybody” to play my video on the website and it requires that in there. I have been using an iPhone to test and it gives me the following message:

    “Safari cannot open the page because too many redirects occured”

    But it does successfully take me from the mywebsite/index.html page to the mywebsite/mobile.html page, it just doesn’t render and I get that error message above. Do you know how I can fix this?

  17. Script works great. But isn’t it considered best practice to allow mobile users to click a link and go to the full non-mobile version of the site? It doesn’t seem like you would be able to do this using this method. Any ideas?

  18. Hi Ryan,
    First, apologies for bumping this up… 😉
    Second, a big thank you for the code, after a hundred different things, I tried this and is the one that works, or sort of…
    Third, is there a way to add detection for Nokia browsers in general?

    Thanks

  19. Hi,
    The code was working awesome until last the 5 days , folks with firefox 5 have started complaining that they cant get to the regular site on their computer and the code is redirecting them to their mobile site on their computer

    1. I’ve tried the code in almost every possible browser, no a hitch so far… The ONLY “problematic” browser was the Nokia’s handheld homebrew browsers.

      1. Hey,
        Ya, it was working fine until a bunch of users in firefox started complaining that the website on computer still sends them to mobile website. Here is some data from analytics which shows many firefox5 calls coming in and that increased their number since other times it would mostly be iphone. So I am including that , incase if it helps. I removed the rule for now. Let me if there is a clue.

        [Mozilla/5.0 (Windows NT
        6.1; WOW64) AppleWebKit/5
        35.1 (KHTML, like Gecko)
        Chrome/13.0.782.112 Safar
        i/535.1]

        [Mozilla/5.0 (compatible;
        MSIE 9.0; Windows NT 6.1
        ; WOW64; Trident/5.0)]

        [Mozilla/5.0 (Windows NT
        6.1; WOW64; rv:6.0) Gecko
        /20100101 Firefox/6.0]

            [Mozilla/5.0 (Windows NT
        6.1; WOW64; rv:5.0) Gecko
        /20100101 Firefox/5.0]
            [Mozilla/5.0 (Windows NT
        6.0) AppleWebKit/535.1 (K
        HTML, like Gecko) Chrome/
        13.0.782.112 Safari/535.1]

        [Mozilla/5.0 (Macintosh;
        U; Intel Mac OS X 10_6_8;
        en-us) AppleWebKit/533.2
        1.1 (KHTML, like Gecko) V
        ersion/5.0.5 Safari/533.2
        1.1]
        [Mozilla/5.0 (Macintosh;
        Intel Mac OS X 10_6_8) Ap
        pleWebKit/534.50 (KHTML,
        like Gecko) Version/5.1 S
        afari/534.50]

            [Mozilla/5.0 (Windows NT
        6.1) AppleWebKit/535.1 (K
        HTML, like Gecko) Chrome/
        13.0.782.112 Safari/535.1
        ]

            [Mozilla/5.0 (Windows NT
        6.0; rv:6.0) Gecko/201001
        01 Firefox/6.0]

        [Mozilla/5.0 (Windows NT
        5.1) AppleWebKit/535.1 (K
        HTML, like Gecko) Chrome/
        13.0.782.112 Safari/535.1]

  20. This works great except for linking back to view the full site. Obviously it just loops back to the mobile site. Is there a way to set a cookie in the htaccess file to prevent this? Or something else?

    1. I used a php redirect with a cookie that allows mobile users to access the full website. I also only wanted mobile users to go to the mobile site if they are going to the homepage. (This is because we use QR Codes in printed material and offer many more pages on our full website that are indexed in Google’s mobile SERPs but we don’t have mobile pages available.) To do this, I added this code to the index.php file:

      $mobile = ‘http://mobile.mysite.com/’;

      if ((strstr($_SERVER[‘HTTP_USER_AGENT’], ‘iPhone’)) && empty($_COOKIE[“mobilesitecookie”]) && $_SERVER[‘REQUEST_URI’]==”/”) {
      header(“Location: ” . $mobile);
      }

      And this is the code that I put on the mobile site to make the cookie:

      function set_cookie () {
      document.cookie = ‘mobilesitecookie=mobilesitecookie; domain=.mysite.com;’;
      window.location = ‘http://www.mysite.com/’
      }

      I then added an HTML A tag that triggers the set_cookie function.

      Enjoy!

  21. Hi,
    i use the above code to deviate a cyber attack coming from a Safari 419.3 browser on a linux system. The only thing is that i can’t visit our sites through safari myself.
    RewriteCond %{HTTP_USER_AGENT} “Safari|safari|SAFARI|linux|LINUX|Linux” [NC]RewriteRule ^(.*)$ /http://fakedomain.com/ [L,R=302]
    is the code i’m using.
    my safari is v.5.1, could i somehow refine the above code to only block safari 419.3 linux but allow visits from other safari browsers?

  22. Why did you include “googlebot-mobile”? The redirect that you are using is specifically geared towards smartphone user agents. The googlebot-mobile user agent was meant for WAP content (feature phones). The newly introduced smartphone googlebot-mobile actually masquerades as an iPhone

  23. I think the best way is to use my “Apache Mobile Filter” (http://www.apachemobilefilter.org) and mod_rewrite. For example:

    #Configuration AMF Filter
    #
    PerlSetEnv AMFMobileHome /usr/local/AMF
    PerlSetEnv AMFProductionMode true
    PerlSetEnv ServerMemCached localhost:11211

    PerlTransHandler +Apache2::AMFFilter
    # or
    PerlTransHandler +Apache2::AMFFilterMemcached
    RewriteEngine on
    RewriteCond %{ENV:AMF_ISMOBILE} ^true*
    RewriteRule ^(.*)$ http://m.foo.org [R=301,L]

    Take it from: http://wiki.apachemobilefilter.org/index.php/Mod_rewrite_integration

  24. Hi, very useful topic. Thanks for sharing.
    I’ve a question, how can I prevent a couple of subdomains to get detected by this code?

    On those 2 cases (2 subdomains: some.mydomain.com & somemore.mydomain.com) I dont need to get mobile device detection.

    Thanks for your help trying to solve this case.

Leave a Reply