mod_rewrite Tutorial for Absolute Beginners

Explains what mod_rewrite is and how to use it. Includes 3 practical examples: 301 redirects, creating friendly URLs, and blocking image hotlinking (leeching).

Writing a URLmod_rewrite is a marvellous feature of the Apache Web server. It's very flexible and can do all sorts of useful things.

mod_rewrite can be quite tricky for beginners to pick up due to its somewhat complicated syntax and processing mechanism. However, once you understand a few basic concepts then you can use mod_rewrite to do some pretty clever things with your site.

In this tutorial you'll find out what mod_rewrite is, and the kind of things you can use it for. You'll learn how to create a few basic mod_rewrite rules, and you'll explore some useful real-world examples that you can use on your own website.

What is mod_rewrite?

mod_rewrite is an Apache module for manipulating (rewriting) URLs. Frequently this means taking the URL requested by a visitor and sending them content at a different URL. For example, a visitor might type the following URL into their browser:

http://www.example.com/page.html

Normally, Apache then sends back the contents of the page.html file to the visitor. However, with mod_rewrite you can send back the contents of a different URL, such as:

http://www.example.com/another_page.html

The important thing here is that this rewriting happens inside the Apache server. The browser's address bar still shows http://www.example.com/page.html, but Apache sends back the content at http://www.example.com/another_page.html:

browser showing different content to the URL in the address bar
With mod_rewrite, you can serve up content at a different URL to the one requested by the browser.

Contrast this with HTTP redirects, which tell the browser to visit a different URL from the one requested.

As you'll see shortly, you can also use mod_rewrite to do HTTP redirects, as well as other things such as return HTTP error codes.

Things you can do with mod_rewrite

mod_rewrite lets you create all sorts of rules for manipulating URLs. For example, you can insert values pulled from the requested URL into the new URL, letting you rewrite URLs dynamically. Or you can check server variables such as the user agent (browser), and only rewrite a URL if the browser is, say, Safari running on an iPhone.

Here are some common uses of mod_rewrite:

  • Creating "friendly" URLs that map to "ugly" URLs. For example, you can map the nice-looking URL www.example.com/articles/my-article/ to the real URL at www.example.com/display_article.php?articleId=my-article. Then everyone can use the friendly URL instead of the real one.
  • Stopping image leeching/hotlinking. To stop other sites linking to your images in their pages, you can use mod_rewrite to send back a "Forbidden" error if the referring URL isn't on your own site.
  • Redirecting to canonical URLs. Many webpages can be accessed via several URLs — for example, www.example.com/mypage.html and example.com/mypage.html. You can use mod_rewrite to always redirect browsers to the "correct" URL, such as www.example.com/mypage.html. Amongst other things, this ensures that only the correct URL shows up in search results.
  • Avoiding 404 errors when reorganizing your site. Say you've redone your site and moved the page at www.example.com/myarticle.html to www.example.com/articles/myarticle.html. Using mod_rewrite, you can redirect www.example.com/myarticle.html to www.example.com/articles/myarticle.html so that visitors don't get 404 "not found" errors when visiting the old URL. Thanks to the flexibility of mod_rewrite, you can easily create generic rules that can map all old URLs to your new URL format.

How to use mod_rewrite

To use mod_rewrite, you create Apache directives to tell mod_rewrite what you want to do. Directives are simply configuration settings. Often you'll put these directives in a .htaccess file at the top level (document root) folder of your website. The directives then apply to your whole site.

The 2 most important mod_rewrite directives are:

  • RewriteEngine: This turns the mod_rewrite engine off or on for the current request.
  • RewriteRule: This creates a rule for rewriting one URL to another.

Try this very simple example. Create the following .htaccess file and upload it to the top level folder of your site:


RewriteEngine on
RewriteRule ^dummy\.html$ http://www.google.com/ [R=301]

This file does 2 things:

RewriteEngine on
Turns on the mod_rewrite rewriting engine.
RewriteRule ^dummy\.html$ http://www.google.com/ [R=301]
Redirects requests for the page dummy.html to Google, using a 301 HTTP redirect.

^dummy\.html$ is a regular expression. It means: "Match the start of the URL (excluding the domain name portion), followed by the text dummy.html, followed by the end of the URL". If you're new to regular expressions, here's a good introduction.

Now open your Web browser and visit the dummy.html URL on your site (for example, http://www.example.com/dummy.html). If all goes well you should be redirected to http://www.google.com.

If you get a 404 Not Found error then it's likely that mod_rewrite hasn't been enabled on your Web server or website. Ask your hosting company if they can turn it on for you.

How RewriteRule works

You use the RewriteRule directive to create rewriting rules. The general syntax of the directive is:


RewriteRule Pattern Substitution [Optional Flags]
  • Pattern is a regular expression pattern. If a URL matches this pattern, the rule is processed. Otherwise, the rule is skipped.
  • Substitution is the new URL to use instead of the matched URL.
  • [Optional Flags] are one or more flags that let you alter the behaviour of the rule. More on flags later.

You can add as many RewriteRule lines as you like to your .htaccess file. mod_rewrite works through the rules one at a time, processing any rules that match the requested URL.

If a rule rewrites the requested URL to a new URL, that new URL is then used from that point onward in the .htaccess file, and might be matched by another RewriteRule further down the file. (If you don't want this to happen you can use the L ("last") rule, described in a moment.)

A few mod_rewrite examples

There's a lot more to mod_rewrite than the simple example just shown. The easiest way to explain mod_rewrite is by looking at a few practical examples, which you'll do in the following sections.

Example 1: Avoiding 404 errors

Occasionally you might change the URL of a page on your site. This can happen if you're reorganizing your content. However, what if search engines and other sites have linked to your old URL? Visitors will see a "404 Not Found" error if they follow these links.

To solve this problem, you can use mod_rewrite to issue a 301 redirect. This sends an HTTP header to any browser requesting the old URL, telling them that the page has moved permanently to the new URL. This also tells search engines to update their index with the new URL.

The following .htaccess file will redirect an old URL to a new one:


RewriteEngine on
RewriteRule ^my-old-url\.html$ /my-new-url.html [R=301,L]

The RewriteRule works like this:

^my-old-url\.html$
The regular expression that will match the URL to rewrite. This pattern means: "Match the start of the URL (^), followed by the text 'my-old-url.html', followed by the end of the URL ($)".
/my-new-url.html
The second part of the RewriteRule is the URL that you want to use instead. In this case, this is simply /my-new-url.html.
[R=301,L]
The third, optional part of a RewriteRule is one or more flags, separated by commas and surrounded by square brackets. These flags let you add specific options and actions to the rule. In this case there are 2 flags: R=301 means "issue a 301 redirect to the new URL", and L means "last rule" — in other words, "stop processing if this rule matched the requested URL".

With regular expressions, a dot (.) means "match any character". So, to explicitly match the dot in 'my-old-url.html', you need to place a backslash (\) before the dot to escape it, as shown in the regular expression above.

Example 2: Creating friendly URLs

Say you've written a PHP script, display_article.php, to display articles on your site. You might view an article by using the following URL:

http://www.example.com/display_article.php?articleId=my-article

This URL looks pretty ugly, and the query string within it (?articleId=my-article) can confuse some search engines. A much nicer URL would be:

http://www.example.com/articles/my-article/

You can use mod_rewrite to rewrite the first URL format to the second. To do this, simply add the following .htaccess file to the top-level folder of your site:


RewriteEngine on
RewriteRule ^articles/([^/]+)/?$ display_article.php?articleId=$1 [L]

The RewriteRule line works as follows:

^articles/([^/]+)/?$
This regular expression matches any URL in the format articles/(article ID)/. It reads: "Match the start of the URL (^), followed by the text articles/, followed by 1 or more characters that aren't slashes ([^/]+), followed by an optional slash (/?), followed by the end of the URL ($)."

Note the parentheses around the [^/]+ part of the pattern. These tell Apache to store the text that matches this subpattern — for example, "my-article" — for later use.
display_article.php?
articleId=$1
This tells Apache to run the display_article.php script, passing in the text that matched the [^/]+ subpattern in the regular expression (e.g. "my-article") as the articleId parameter.

$1 is called a backreference — it stores the text that matched the subpattern. If your regular expression contained another subpattern inside parentheses then the text that matched the second subpattern would be stored in $2, and so on.
[L]
As you saw in the previous example, this flag tells mod_rewrite to stop processing if this rule matched the requested URL. Generally this is a good idea, unless you want the URL to be rewritten further by other RewriteRules later in the .htaccess file.

So the above RewriteRule takes a requested URL in the format http://www.example.com/articles/my-article/ and serves up the content at the URL http://www.example.com/display_article.php?articleId=my-article instead.

Example 3: Preventing hotlinking to images

Another common use of mod_rewrite is to stop other websites linking to images on your own site. Say you have a page on your site, http://www.example.com/mypage.html, that contains the following img tag:


<img src="myphoto.jpg" alt="My Photo" />

Another site might then link directly to your photo with the following tag on their page:


<img src="http://www.example.com/myphoto.jpg" alt="My Photo" />

This means that the other site is not only "borrowing" your image for their page, but is also using up your server's bandwidth to display the image on their page. If the other site gets lots of visitors then this can be a big problem!

You can use the following mod_rewrite directives to stop any site except your own from linking to your images. Place these in a .htaccess file in the top-level folder of your site, or in a folder of images that you want to protect from hotlinking. Change example.com to your site's domain name.


RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example\.com/.*$ [NC]
RewriteRule .+\.(gif|jpg|png)$ - [F]

Once you've done this, any browser requests for an image on your site where the referring URL starts with a domain other than www.example.com or example.com will be rejected with a "403 Forbidden" error, resulting in no image being displayed on the linking page (and hardly any of your bandwidth being used).

Here's how this set of rules works:

RewriteEngine on
Turns on the mod_rewrite rewriting engine.
RewriteCond %{HTTP_REFERER} !^$
RewriteCond is another mod_rewrite directive. It allows you to set up a condition that must be true for the following RewriteRule to be processed. This RewriteCond directive reads: "If the HTTP_REFERER server variable is not empty".
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example\.com/.*$ [NC]
This second RewriteCond directive reads: "If HTTP_REFERER doesn't start with http://www.example.com/ or http://example.com/". The [NC] flag makes the match case-insensitive.

If either of these 2 RewriteCond conditions fail, the following RewriteRule is skipped.
RewriteRule .+\.(gif|jpg|png)$ - [F]
The actual rewriting rule uses the [F] flag to send back a "403 Forbidden" error if the URL contains an image filename (that is, a filename ending in .gif, .jpg or .png). The - (hyphen) for the Substitution parameter means "don't rewrite the URL to another URL".

So the whole .htaccess file reads: "If HTTP_REFERER isn't empty, and HTTP_REFERER doesn't start with http://example.com/ or http://www.example.com/, and the requested URL contains an image filename, reject the request with a '403 Forbidden' error".

Summary

This article introduced you to Apache's mod_rewrite module for manipulating URLs. You looked at how mod_rewrite works, and what you can do with it. You saw how to create mod_rewrite rules using the RewriteRule directive, and how to do conditional rewriting with the RewriteCond directive. Along the way, you looked at 3 practical examples of mod_rewrite:

  • 301 redirects
  • Creating friendly URLs, and
  • Stopping image hotlinking.

This tutorial has just scratched the surface of mod_rewrite. If you want to find out more about what mod_rewrite can do, check out the official documentation. Have fun!

Follow Elated

Related articles

Responses to this article

10 responses (oldest first):

05-Feb-11 14:10
Hi Matt,

thank you for writing this introduction. After reading over a dozen tutorials on .htaccess and mod_rewrite, this is the first that's able to explain it in clear, normal language.

rgds, Eric
07-Feb-11 20:02
Thanks for your kind words Eric. I'm glad you found the article easy to follow.

Matt
09-Feb-11 20:01
Hello Matt,
I love this tutorial, so easy to understand. I also have read tutorials on mod_rewrite else where, but you make it perfectly clear.

Thanks again, Joe
09-Feb-11 22:40
Thanks Joe. It's great to know that this article is helping so many people!
01-Mar-11 16:21
thanks joe, nice introduction;
but... i still have no idea how could i do the following:

a rewrite from subdird.domain.ltd internaly to domain.ldt/index.php ?
so lets say the structure looks like this on my hosting:
/root_www/index.php (we want to rewrite from 3th lvl domain to this)
/subdird/

so when i access in browser subdir.domain.ltd/ it rewrites internaly to domain.ltd/index.php

anyone can help plz?
02-Mar-11 02:44
@webperfection: Something like this perhaps?


RewriteEngine on
RewriteRule ^/?$ /root_www/index.php [L]
08-Mar-11 09:05
well... life would be 2 easy and boring with solution like that
the thing is that if i enter my 3th lvl domain
3th.domain.ltd
its "impossible" to get out of there
/ == 3th.domain.ltd
with absolute path i cant access anything
cant use ../ ether
once more the folder structure used:

/www_root/index.php (doc root)
/3th/some.html (so to root i tough i can get like ../www_root/ which is impossible)

so following wont help me
RewriteRule ^/?$ /root_www/index.php [L]
coz / is already /var/www/domain/3th/

as i was despaired with no solution i asked my provider to set vhost serveralias to *.domain
and i had to wrote my own php router for everything :/

so my final question would be: is it apache config related problem or just my lack of experience with mod_rewrite?

thx for replay
10-Mar-11 20:53
@webperfection: Sounds like more of an issue with your virtual server. If your apache can't address the path of the site you want to redirect to then there's not much it can do (apart from a 301/302 redirect).
26-Sep-11 18:29
Hello, Matt

I registered here only to express how grateful I am for you tutorial. I found it very helpful.
The official documentation was too difficult to read for me as an introduction, in other tutorials the processing of the directives wasn't explained clearly enough.
It was a pleasure to read your tutorial. Really well-written. I didn't have to read anything more than once


Really, really grateful and delighted to be finally able to use mod_rewrite,
Michael

[Edited by highlyFlammable on 26-Sep-11 18:30]
28-Sep-11 04:56
@highlyFlammable: Thanks for your feedback! I'm really pleased you found the tutorial useful.

Post a response

Want to add a comment, or ask a question about this article? Post a response.

To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute. Sign up now.

Top of Page