Today we will go over some practical uses of htaccess files that you can use in your web applications.
Requirements
Htaccess files are plain-text configuration files used by the Apache HTTP web server. They allow users to set directory level options without requiring access to the httpd.conf file. As such it is required that your server uses Apache, and a web host that allows htaccess files (the most popular hosts do).
I assume a basic working knowledge of htaccess, but if you need to freshen up check out this article by Joseph Pecoraro
1. Prevent Hotlinking
Hotlinking, or inline linking, is when one web site links directly to an object on another site. This costs the hosting site bandwidth to provide the image on the page of the second site. On popular photo sites this can be a major problem, albeit humorous at times.
There are ways to fix this growing problem using htaccess. First here is the image we are trying to protect.

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
#domains that can link to images
#add as many as you want
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?demo.collegeaintcheap.com [NC]
# RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?noahhendrix.com [NC]
#show no image when hotlinked
RewriteRule \.(jpg|png|gif)$ - [NC,F,L]
We will step through this line-by-line.
- First we need to turn on the rewrite engine in Apache, this allows us to redirect the user’s request.
- Next we start setting our conditions using RewriteCond. This is a function that takes two arguments: TestString and CondPattern. TestString is the string we want to check our CondPattern against (using regular expressions). ${HTTP_REFERER} is a variable provided by Apache that holds the domain the request came from, in this instance we want to allow requests from blank HTTP referrers to protect users who are on a proxy server that sends blank referrers.
- Next we set the domains from which we will allow our images to be linked using the same syntax except now we provide a URL. The [NC] flag at the end of the command simply instructs the engine to ignore casing. You can add as many lines domains as you’d like here, using the same syntax. For the sake of example I added my personal domain, but commented it out.
- Finally, the last line is the RewriteRule we wish to use if any of the conditions above are not met. It takes two arguments as well Pattern and Substitution, where pattern is a regular expression match and substitution is what we want to replace any matches with. In this case we are looking for requests that end in jpg, png, and gif; if found we want to use a blank substitution. However in the flags we tell it furthermore what we want to be done, NC means no case, F sends a 403 forbidden error to user, and L tells the engine to stop rewriting so no other rules are applied.
This is fairly straightforward, but perhaps we are interested in telling the user we don’t want them to hotlink our images, so let’s redirect all hotlinked requests to an image instead of sending a 403 forbidden error. This is done by replacing the last line with this code.
#show an alternate image
RewriteRule \.(jpg|png|gif)$ http://demo.collegeaintcheap.com/envato/htaccess/hotlink/images/hotlink.jpeg [NC,R,L]
You can change url to any image path you’d like on your domain, but remember it needs to not end in jpg, png, or gif as it will reapply the rule and send the server into a never-ending loop. I chose to use the older .jpeg extension to fix this. The R flag that replaced F simply sends a redirect.

2. Block User By IP Address
This is a great little tip if you have a spammer on your website. If you can find their IP in your logs, simply add it to an htaccess file.
Order Deny,Allow Deny from 24.121.202.23 # Deny from 0.0.0.0
Using the Order directive in the mod_access module we can specify IPs to deny and allow. Simply using the syntax Deny from IP ADDRESS we can forbid those users from accessing our directory.

3. Error Documents
All production ready sites should use custom error pages for a professional touch. This is easy using the ErrorDocument directive in Apache’s core. A custom page is far better than the default Apache error pages.

ErrorDocument 404 http://demo.collegeaintcheap.com/envato/htaccess/errors/404.html ErrorDocument 403 http://demo.collegeaintcheap.com/envato/htaccess/errors/403.html ErrorDocument 500 http://demo.collegeaintcheap.com/envato/htaccess/errors/500.html
ErrorDocument takes two arguments error-code and document. In the code above I created error documents for the 3 most common HTTP errors: 404 not found, 403 forbidden, and 500 server error. Then you can provide the full URL or relative path to your error documents. You could also them redirect to a PHP script that logs the errors in a database or emails them to you (might get annoying though). This is a great way to take control of errors in your web application, be sure to check out Smashing Magazine’s 404 error page showcase for inspiration.

4. Redirect While Performing Upgrades
If you are performing a major site upgrade you most likely should redirect users to a page informing them. This prevents users from seeing broken pages or potential security holes while the application is uploading. One caveat to consider is that we want to allow certain IP addresses into the site for testing before it goes live all of this can be achieved in an htaccess file.
RewriteEngine on
RewriteCond %{REQUEST_URI} !/upgrade.html$
RewriteCond %{REMOTE_HOST} !^24\.121\.202\.30
RewriteRule $ http://demo.collegeaintcheap.com/envato/htaccess/upgrade/upgrade.html [R=302,L]
We are using the rewrite engine again to do this, but in a kind of reverse way. First we need to set a condition that excludes the document describing the upgrade otherwise our server start a never ending loop. Next we exclude a single IP address from being redirected for testing purposes. Finally we use the rewrite rule to send users to an upgrade page. The flags we have looked at before, except this time we setting the redirect to a 302 status code, telling the browser that the page has temporarily moved and to handle caching accordingly. Smashing Magazine, again, has a great showcase of Effective Maintenance Pages.

5. Hiding Directory Listing
For numerous security reasons it is a good idea to restrict directory listing, the default behavior in Apache. This can be done with a simple line in our htaccess file we can prevent visitors from seeing our directory listings.

Options -Indexes
Now users who request a directory that doesn’t have an index file it will show them a 403 forbidden error page.

Conclusion
These are several of my favorite uses of htaccess. Leave yours in the comments! I am available for help in the comments or on twitter. If there is a great deal of interest, I will do more htaccess tutorials with solutions to your requests in the comments. Thanks for reading!
- Follow us on Twitter, or subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Thanks! Useful, but could you write another article about mod_rewrite
I and I think many others would really appreciate it!
Flip,
Check out the regular expressions tuts on http://blog.themeforest.net, and then take a look at the O’reilly book Apache Security
mod_rewrite is hell to understand if you don’t have a solid understanding of mod_rewrite.
regular expressions I mean. ; )
I agree, a mod_rewrite tutorial would be good as well.
Another vote for mod_rewrite
awesome!! this is really good!! i didn’t know about the “upgrade” redirect.
thanks you so much!!
Nice list of .htaccess features, but I miss the url rewriting methode. I know it can also be done with .htacces.
There are not many tutsites that cover the basic of a good structured website. Where a domain with .com/about/ will be redirected to the according about.php page and still show /about/ in the title bar.
Very useful.
Thanks for the info. Being more of a sysadmin than developer I always appreciate these kinds of tuts.
Good tutorial, I really should add a few of these to my sites!
I would also like a tutorial on mod_rewrite as well!
Awesome list, this gave me many ideas of what to do with htaccess other than just the cleaning up of dynamic urls.
Expecting a mod_rewrite tutorial .This is also great !
Excellent article.. always nice to see how much you can do with the htaccess file which reminds me..
/me runs off
Guess this tutorial was chosen over mine -_-
I had a 3 part series planned; basic, intermediate, advanced. I was going to cover mod-rewrite extensively as well.
Oh well
None of these are new to me, but the clear and concise explanations have definitely expanded my knowledge.
A mod-rewrite and pretty urls tutorial would get my vote too.
Please tell me that email shown in #1 is fake.
‘I am an honest business man…’ NOT.
People like that should be punched repeatedly in the head.
Heheh.. i thought that was hilarious too. :D
Haha…nice. I agree though. It’s just amazing what people can complain about, try to sue, and actually get money for. Oh well…
Great tut though!
I needed to know some of these solutions, thanks!
Redirect while performing upgrades is very useful. I don’t see that one a lot in other .htaccess tutorials. I actually do it through php so that the upgrade message is styled, but I guess sometimes it wouldn’t be possible.
Is that e-mail from the hot linker real? O_O haha I cant believe that
To all asking the email is one that circulated the internet a few weeks back and does not belong to me, more info from the recipient is found on his blog:
http://www.shapelessmass.com/index.html/?p=578
Oh.
My.
God.
I simply cannot believe this isn’t made up.
He was a better man than me. I would have returned the images back to the site but the new images would be MUCH different…if you know what I mean.
I never quite get comfortable with htaccess….This helped….
Nice article, really useful !
yup how to re-write urls that have php variables would be helpful too!
will the hotlinking code block images in feed readers?
Hmm good question not really sure. If they cache the image then no, but if they are pulling live from the server I guess it probably would. One idea to circumvent that would be if they use an iframe I suppose.
It appears everyone is clamoring to see an htaccess tutorial using mod_rewrite, I have put that on my list of subjects to cover any specifics you’d like to see be sure to put them here, or @noahhendrx on twitter.
mod_rewrite can be hard to grasp without some regex experience. When I was learning mod_rewrite, the best tutorial I found was at phpfreaks.com. Unfortunately, they redesigned their site (after being hacked I believe), and I can’t find it to share with ya’ll.
(!) Ideas! =D
I always run into this issue, someone has a site, they want an update with a CMS, so I install TXP or WordPress (along with their htaccess files, and their setup of mod_rewrite for pretty urls)… but how do I redirect people to a temp page during the updates (as in #4) in this situation, because it ends up conflicting with the mod_rewrite setup for the CMS?
Thank you for your information :) Especially no. 4 is useful for me :)
The fact that the “honest business man” was leaching images to build his business and had the nerve to threaten to call his lawyer. Comedy!
Good info here. Thanks for the post.
Nice article! And that email really made my laugh..
But I also would like to see a indepth article about mod_rewrite..
Some specific ideas:
changing url’s in this way:
normal url: http://www.mysite.com?var1=majorsubject?var2=secondsubject turning into var1.mysite/var2
Is that possible? To also use (fictive) subdomains in mod_rewrite?
Yeah! I would like to see something like this
I laughed so hard when I read those hotlinking emails. Those are hilarious. Thanks for these tips.
Great article…. I have to say I was quite literally laughing out loud reading his email about how he is such an honorable business man… and the mention of a lawyer? priceless!
GReat ! So simple, so excellent ! Woaaa !
Oh excellent post! Thank you very much! haha I especially liked the email from the one on hotlinking :)
For performing upgrades the best solution is to have the holding page return a 503
This is really useful, I wish I had this article about a week ago with the IP bans. Great writeup Noah!
really nice… thank you ;)
Good little collection. I’d definitely add the 301 redirect when you want to say switch a site from an old to a new URL structure nad preserve your search engine rankings as much as possible:
Redirect 301 /old/old.html http://www.domain.com/new.html
Another great use for .htaccess, of that can use it to keep URLs meaningful and consistant, even when you change technologies, like from .aspx to .php.
This is what the inventor of the web has to say about that: http://www.w3.org/Provider/Style/URI
Also, you can use .htaccess to treat .html files and .shtml, so you do not have to include that weird file extension when you want to use Server Side Includes (which are really cool, otherwise).
Another good use for .htaccess is to keep meaningful and consistent URLs, even when you rename files or change technologies (like .asp to .php). This is what the inventor of the web has to say about that:
http://www.w3.org/Provider/Style/URI
.htaccess is also really useful to make .html files treated like .shtml, so you can use Server Side Includes (which are great) without having to use that weird file extension.
thanks ,but in asp how could setting htacess
Really nice tips.
Love that email. It’s gold.. your article too, of course, but not in the same sense ;)
thanks!
hi this tutorial is good
Excellent Hendrix. Very helpful for professionals.
Nice article, especially for beginners.
I also used .htaccess in a funny way. I wanted to experiment with User-Agent filtering… Especially with Web Crawlers, spiders and Bots. So I blocked all “human” visitors on a live website, and allowed only web crawlers to access the site. If you interested in the result look on my blog post:
http://www.dobrotka.sk/blog/use-htaccess-to-filter-visitors-and-crawlers-based-on-user-agent/
Ahm, okay…
Well, did you have turned off your referer variable in your browser? Than you’ll see, that your number 1 isn’t as good as you thought.
There are several Plugins, Firewalls and so on, that kills the referer string of a httprequest. And without it users can see every picture.
Think a php based solution is much better.
Most ways of implementing an anti hotlink system (be it .htaccess, php, asp, whatever) uses the the http referrer header. I don’t think there is any clean way to do it. I think the best solution would be an automated (cron job or something) or manual system that simply checks the logs if there’s a specific domain (checking the referrer field) that has taken a lot of bandwidth, and add those domains to a blacklist as that wont f*ck anything up for normal users.
I know a really secure solution for it, trust me :D the biggest goal: i don’t need the referer. IP, Browser, Timestamp – or just a unique key – that’s all.
Needs:
– mod_rewrite (optional)
– php
– some userdata (IP, browser, timestamp of visit…) or unique key to build md5 string
– a bit coding skill
the idea:
build an unique URL to the file for each user who accesses the file, p.e.: domain.com/img/74mnd36z54mf/folder/filename.png or without mod_rewrite: domain.com/file.php?/img/74mnd36z54mf/folder/filename.png
Important: the real path to the image is _not_ img/folder/filename.png or img/74mnd36z54mf/folder/filename.png, that will be too easy to find out. Use a totally other name for the base image folder. And also impotant: Don’t use indexing on the webserver.
74mnd36z54mf = sample unique key to identifier user.
There are two ways to finally restrict the access to one unique user: store the unique key in a $_SESSION (cookiebased or urlbased) or store it in a database. Bind this unique key with the ip address of the visitor. Optional you can set a time limit for accessing. Bingo: Only this unique user will get now the right image.
Well, okay, true: users can deeplink the images again. But: the unique key is bind to this user, only he can see the right image and he’ll think all is ok. All other users will see a warning, advertising like “Hey guy, this image was deeplinked by the sites administrator, you can get the right image on http://www.domain.com” or whatever. this warning can be set up with an non-expiring header, so that the traffic will be small. Free ads, isn’t that cool? ;)
I have tested this idea with a simple non-dynamic script (one image only, linked within the php file), it works really perfect. It’s only a lot more complicated, when you want to use it dynamic like a databased gallery, newsscript or whatever.
That’s a pretty good solution but theres a small down, for a site with a big userbase the session managing will increase the server load quite a bit. Other than that it’s quite good, but also extremely easy to circumvent.
No, its not as easy to circumvent as you think. If you don’t know the real path to the images, you will never be able to circumvent this solution. Every user has a unique ip (okay, there are proxys, right… but this can be ignored). generate a unique key, use it directly in the url, bind the key to the user – no way to circumvent it.
But in one thing you’ll be right: This solution CAN(!) increase server load. I explicitly said: You need a little bit coding skill – than you’ll know how to work without or only small increasing server load. For example: Think about Expire-Header – you don’t have to read in all images with php on each page impression. And another: its recommended for each larger site to outsource their images on another server to keep connections and server load per user small.
All you need to circumvent this is to generate the set-cookie http header (that’s apache’s default way to store session id’s), this can be done by having an invisible iframe that simply loads the smallest page where the session is set) before loading the images, it would be maximum 10 lines of js to circumvent it… but if someone’s that dedicated to hotlink your images you should feel proud :P
Right, that can be possible :D But the other side of this fact is, that this is a kind of criminal activity, in germany you can demand compensation. Don’t know how this will be in other countries.
Okay in this case youre right – but what if you DON’T use PHP-Session? It’s only _one_ way to prevent hotlinking. The other way is over the IP Address of the user. generate a unique key, store it with the visitors ip in a database. right, then you have to check the userip and unique code on every request, but THAT will be really secure. This solution should be used for downloads. The way over a session is really secure enough for images. :P
Hah, i’ve thought about it.
No, theres NO way to circumvent my solution – even not when sessions are used. The image-stealer uses a unique key in the linked image url on his site, so that every other user can’t view this image. A “bypass-iframe” wouldn’t have any effect of this fact, because each user get his own unique key in the image url.
Hi! Nice little list of useful .htaccess features. I’d just like to point out that the hotlinking protection might be more destructive than useful as a lot of users disables the http referrer header (HTTP_REFERER (heh funny thing the common miss spelling of referrer made it’s way into the http protocol :P)) and a lot of firewalls and other applications that’s meant to keep your privacy also disables the http referrer header.
Off topic:
I’d like to see some SEO tutorials on here :D
Wow, can’t believe that someone really had the audacity to threaten to sue over not being able to use *someone else’s photos*. Amazing.
Anyhoo, thanks for the tut.
Thanks, this is extremely useful, i found that mesage that was received hilarious, very cheeky but very funny, it shows how ignorant some people can be at times, either that or naive possibly.
Thanks for the information regarding 4. especially.
These are some pretty useful tips, especially with Apache being such a popular and free web server platform.
Thanks for the post, I think I’ll be using the Redirect While Performing Upgrades the most.
i like the number 4. but how to do this if the user type http://www.mysite.com it will redirect it to http://mysite.com many thanks.
Hello,
thank you for these explanations :)
I however have one question:
Using a modalbox plugin (jquery for example) to open a page abc.html from a link on page index.html, I would like to know if we can use htaccess to prevent any user to open page abc.html if its not through the modalbox of page index.html ?
like maybe something as allow 127.0.0.1 deny all ?
i don’t even know if that’s possible.
or maybe its in php, like with a define(”,”) but since its not an include…
any advises ?
thank again !
and also, whats the difference between
IndexIgnore *
and
Options -Indexes
?
forget it, I just figured it out…
IndexIgnore * won’t redirect to an error, but won’t display anything
whereas
Options – Indexes will redirect to an error
(which is quite usefull to make it look as an error for scriptkiddies)
There is another difference:
On some shared hostings the use of “Options” Apache directive is forbidden.
But on those restrictive hostings IndexIgnore is allowed.
Great tut. but what I’m missing here is the .htpasswd protection
I recently put together a smorgasbord of delicious password-protection tricks:
http://perishablepress.com/press/2009/07/13/htaccess-password-protection-tricks/
Hopefully it will help :)