Force Lower-Case URLs with mod_rewrite

You may find yourself in a situation at some point where you need to ensure that all access to your site is done using lower-case only. This may be because of SEO (avoiding duplicate content), or perhaps you want to ensure that you can seamlessly move between case-sensitive/insensitive operating systems. If you are running a standard LAMP stack, you’re in luck. Apache’s mod_rewrite can be used to 301-redirect all incoming requests to their lower-case counterparts with just a few configuration directives.

10. Don’t be Case Sensitive
Since URLs can accept both uppercase and lowercase characters, don’t ever, ever allow any uppercase letters in your structure. If you have them now, 301 them to all-lowercase versions to help avoid confusion. If you have a lot of type-in traffic, you might even consider a 301 rule that sends any incorrect capitalization permutation to its rightful home.
http://www.seomoz.org/blog/11-best-practices-for-urls

It doesn’t require much to rewrite URLs to lower-case, and the necessary configuration directives can be placed in either a virtualhost or .htaccess file. First, the RewriteEngine is enabled, and a custom RewriteMap called ‘lc’ is defined using the internal ‘tolower’ map. Next, a RewriteCond rule is used so that only URLs containing upper-case characters are rewritten. Finally, the actual RewriteRule is defined using the ‘lc’ RewriteMap that we just created to transform the captured URL to lower-case before 301-redirecting the user.

RewriteEngine On
RewriteMap  lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]

The following is the output from the RewriteLog that shows the processing for a request to /INDEX.PHP. Note that only a single upper-case letter needs to be present for the rewrite rule to be triggered. The log output clearly shows the rewrite rule being applied, the RewriteMap being referenced, and the 301 redirect taking place. The subsequent request for /index.php is also shown, where the rewrite condition does not match and the request is passed through.

init rewrite engine with requested uri /INDEX.PHP
applying pattern '(.*)' to uri '/INDEX.PHP'
RewriteCond: input='/INDEX.PHP' pattern='[A-Z]' => matched
map lookup OK: map=lc key=/index.php -> val=/index.php
rewrite '/INDEX.PHP' -> '/index.php'
explicitly forcing redirect with http://test/index.php
escaping http://test/index.php for redirect
redirect to http://test/index.php [REDIRECT/301]
init rewrite engine with requested uri /index.php
applying pattern '(.*)' to uri '/index.php'
RewriteCond: input='/index.php' pattern='[A-Z]' => not-matched
pass through /index.php
Chris Abernethy
PHP Wrangler, MySQL DBA, Linux SysAdmin and all around computer guy, developing LAMP applications since Slackware came on 10 floppy disks.

4 Comments on "Force Lower-Case URLs with mod_rewrite"

  1. Ratnesh says:

    Hi there,
    I am having problem with the above code its not working on local servers.(WAMP)
    The error it gives is internal server error.
    Or
    where should I place this code
    I thinks in the

    RewriteEngine On
    RewriteMap lc int:tolower
    RewriteCond %{REQUEST_URI} [A-Z]
    RewriteRule (.*) ${lc:$1} [R=301,L]

    Please help me out.

  2. Steve says:

    I’m getting the internal server error as well. I suspect that it has to do with the configuration of the servers. Specifically: “Due to the way in which our server environments are setup you may not use php_value arguments in a .htaccess file.”

  3. Hello, its fastidious article on the topic of media print, we all be aware of media is a wonderful source of facts.

  4. Kenan says:

    @Ratnesh for localhost you need to open rewrite extension.

    Also i did it for my web site but nothing changed . It shows again uppercase.

Got something to say? Go for it!