more .htaccess tips and tricks..

more clever stuff here

redirecting and rewriting

"The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail."

- Brian Behlendorf, Apache Group

One of the more powerful tricks of the .htaccess hacker is the ability to rewrite URLs. This enables us to do some mighty manipulations on our links; useful stuff like transforming Very Long URL's into Short, Cute URLs, transforming dynamic ?generated=page&URL's into /friendly/flat/links, redirect missing pages, preventing hot-linking, performing automatic language translation, and much, much more.

Make no mistake, mod_rewrite is complex. This isn't the subject for a quick bite-size tech-snack, probably not even a week-end crash-course, I've seen guys pull off some real cute stuff with mod_rewrite, but with kudos-hat tipped firmly towards that bastard operator from hell, Ralf S. Engelschall, author of the magic module itself, I have to admit that a great deal of it still seems so much voodoo to me.

The way that rules can work one minute and then seem not to the next, how browser and other in-between network caches interact with rules and testing rules is often baffling, maddening. When I feel the need to bend my mind completely out of shape, I mess around with mod_rewrite!

After all this, it does work, and while I'm not planning on taking that week-end crash-course any time soon, I have picked up a few wee tricks myself, messing around with web servers and web sites, this place..

The plan here is to just drop some neat stuff, examples, things that have proven useful, and work on a variety of server setups; there are Apache's all over my LAN, I keep coming across old .htaccess files stuffed with past rewriting experiments that either worked; and I add them to my list, or failed dismally; and I'm surprised that more often these days, I can see exactly why!

Very little here is my own invention. Even the bits I figured out myself were already well documented, I just hadn't understood the documents, or couldn't find them. Sometimes, just looking at the same thing from a different angle can make all the difference, so perhaps this humble stab at URL Rewriting might be of some use. I'm writing it for me, of course. but I do get some credit for this..

# time to get dynamic, see..
RewriteRule (.*)\.htm $1.php

beginning rewriting..

Whenever you use mod_rewrite (the part of Apache that does all this magic), you need to do..

..before any ReWrite rules. note: +FollowSymLinks must be enabled for any rules to work, this is a security requirement of the rewrite engine. Normally it's enabled in the root and you shouldn't have to add it, but it doesn't hurt to do so, and I'll insert it into all the examples on this page, just in case*. The next line simply switches on the rewrite engine

for that folder. if this directive is in you main .htaccess file, then the ReWrite engine is theoretically enabled for your entire site, but it's wise to always add that line before you write any redirections, anywhere.

* Although highly unlikely, your host may have +FollowSymLinks enabled at the root level, yet disallow its addition in .htaccess; in which case, adding +FollowSymLinks will break your setup (probably a 500 error), so just remove it, and your rules should work fine.

Important: While some of the directives on this page may appear split onto two lines in your browser, in your .htaccess file they must exist completely on one line. If you drag-select and copy the directives on this page, they should paste just fine into any text editor.

simple rewriting

Simply put, Apache scans all incoming URL requests, checks for matches in our .htaccess file and rewrites those matching URLs to whatever we specify. something like this..

all requests to whatever.htm will be sent to whatever.php:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ $1.php [NC]

Handy for anyone updating a site from static htm (you could use .html, or .htm(.*), .html?, etc.) to dynamic php pages; requests to the old pages are automatically rewritten to our new urls. No one notices a thing, visitors and search engines can access your content either way. Leave the rule in; as an added bonus, this enables us to easily split php code and its included html structures into two separate files, a nice idea; makes editing and updating a breeze. The [NC] part at the end means "No Case", or "case-insensitive"; more on the switches, later.

Folks can link to whatever.htm or whatever.php, but they always get whatever.php in their browser, and this works even if whatever.htm doesn't exist! But I'm straying..

As it stands, it's a bit tricky; folks will still have whatever.htm in their browser address bar, and will still keep bookmarking your old .htm URL's. Search engines, too, will keep on indexing your links as .htm, some have even argued that serving up the same content from two different places could have you penalized by the search engines. This may or not bother you, but if it does, mod_rewrite can do some more magic..

this will do a "real" external redirection:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.+)\.htm$$1.php [R,NC]

This time we instruct mod_rewrite to do a proper external rewrite, aka, "redirection". Now, instead of just background rewriting on-the-fly, the user's browser is physically redirected to a new URI, and whatever.php appears in their browser's address bar - search engines and other spidering entities will automatically update their links to the .php versions; everyone wins. You can take your time with the updating, too.

Note: if you use [R] alone, it defaults to sending an HTTP "MOVED TEMPORARILY" redirection, aka, "302". But you can send other codes, like so..

this performs the exact same as the previous example RewriteRule.
RewriteRule ^(.+)\.htm$$1.php [R=302,NC]

Okay, I sent the exact same code, but I didn't have to. For details of the many 30* response codes you can send, see here. Most people probably want to send 301, aka, "MOVED PERMENENTLY".

Note: if you add an "L" flag to the mix; meaning "Last Rule", e.g. [R=302,NC,L]; Apache will stop processing rules for this request at that point, which may or may not be what you want. Either way, it's useful to know.

not-so-simple rewriting ... flat links and more

You may have noticed, the above examples use regular expression to match variables. What that simply means is.. match the part inside (.+) and use it to construct "$1" in the new URL. In other words, (.+) = $1 you could have multiple (.+) parts and for each, mod_rewrite automatically creates a matching $1, $2, $3, etc, in your target (aka. 'substitution') URL. This facility enables us to do all sorts of tricks, and the most common of those, is the creation of "flat links"..

Even a cute short link like http://mysite/grab? is too ugly for some people, and nothing less than a true old-school solid domain/path/flat/link will do. Fortunately, mod_rewrite makes it easy to convert URLs with query strings and multiple variables into exactly this, something like..

a more complex rewrite rule:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^files/([^/]+)/([^/]+).zip /download.php?section=$1&file=$2 [NC]

would allow you to present this link as..


and in the background have that transparently translated, server-side, to..


which some script could process. You see, many search engines simply don't follow our ?generated=links, so if you create generating pages, this is useful. However, it's only the dumb search engines that can't handle these kinds of links; we have to ask ourselves.. do we really want to be listed by the dumb search engines? Google will handle a good few parameters in your URL without any problems, and the (hungry hungry) msn-bot stops at nothing to get that page, sometimes again and again and again…

I personally feel it's the search engines that should strive to keep up with modern web technologies, in other words; we shouldn't have to dumb-down for them. But that's just my opinion. Many users will prefer /files/games/ to /download.php?section=games&file=hoopy but I don't mind either way. As someone pointed out to me recently, presenting links as standard/flat/paths means you're less likely to get folks doing typos in typed URL's, so something like..

an even more complex rewrite rule:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^blog/([0-9]+)-([a-z]+)$1-$2 [NC]

would be a neat trick, enabling anyone to access my blog archives by doing..

in their browser, and have it automagically transformed server-side into..

which corzblog would understand (note: corzblog can also produce flat links - the crucial "other side" of the flat-links equation that people often forget in their quest for cute URLs). It's easy to see that with a little imagination, and a basic understanding of posix regular expression, you can perform some highly cool URL manipulations.

Here's the basics of regexp (expanded from the Apache mod_rewrite documentation)..


	\char escape that particular char

		For instance to specify special characters.. [].()\ etc.


	.             Any single character  (on its own = the entire URI)
	[chars]       Character class: One of following chars
	[^chars]      Character class: None of following chars
	text1|text2   Alternative: text1 or text2 (i.e. "or")

		e.g. [^/] matches any character except /
			 (foo|bar)\.html matches foo.html and bar.html


	? 0 or 1 of the preceding text
	* 0 or N of the preceding text  (hungry)
	+ 1 or N of the preceding text

		e.g. (.+)\.html? matches foo.htm and foo.html
			 (foo)?bar\.html matches bar.html and foobar.html


	(text)  Grouping of text

		Either to set the borders of an alternative or
		for making backreferences where the nthe group can
		be used on the target of a RewriteRule with $n

		e.g.  ^(.*)\.html foo.php?bar=$1


	^    Start of line anchor
	$    End   of line anchor

		An anchor explicitly states that the character right next to it MUST
		be either the very first character ("^"), or the very last character ("$")
		of the URI string to match against the pattern, e.g..

		^foo(.*) matches foo and foobar but not eggfoo
		(.*)l$ matches fool and cool, but not foo

If you are new to messing around with code or text, you should memorize the above section. The power you gain and the time you will save is well worth the minutes it will take to get your head around it!

I use regex dozens, sometimes hundreds of times a day, mainly to find (and often replace) specific strings in large documents. I have probably saved about a year of LIFE all-in. That's time you can spend doing things you enjoy. Nuff said.

shortening URLs

One common use of mod_rewrite is to shorten URL's. Shorter URL's are easier to remember and, of course, easier to type. An example..

beware the regular expression:
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^grab /public/files/download/download.php

this rule would transform this user's URL..


server-side, into..


which is a wee trick I use for my distro machine, among other things. everyone likes short URL's, and so will you; using this technique, you can move /public/files/download/ to anywhere else in your site, and all the old links still work fine; simply alter your .htaccess file to reflect the new location. edit one line, done - nice - means even when stuff is way deep in your site you can have cool links like this..


and this; links which are not only short, but flat..

capturing variables

Slapping (.*) onto the end of the request part of a ReWriteRule is just fine when using a simple $_GET variable, but sometimes you want to do trickier things, like capturing particular variables and converting them into other variables in the target URL. Or something else..

When capturing variables, the first thing you need to know about, is the [QSA] flag, which simply tags all the original variables back onto the end of the target url. This may be all you need, and will happen automatically for simple rewrites. The second thing, is %{QUERY_STRING}, an Apache server string we can capture variables from, using simple RewriteCond (aka. conditional) statements.

RewriteCond is similar to doing in many programming languages. If a certain condition is true, then do the rewrite that follows..

In the following example, the RewriteCond statement checks that the query string has the foo variable set, and captures its value while it's there. In other words, only requests for /grab that have the variable foo set, will be rewritten, and while we're at it, we'll also switch foo, for bar, just because we can..

capturing a $_GET variable:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.*)
RewriteRule ^grab(.*) /page.php?bar=%1

would translate a link/user's request for..

server-side, into..

Which is to say, the user's browser would be fed page.php (without an [R] flag in the RewriteRule, their address bar would still read /grab?foo=bar). The variable bar would be available to your script, with its value set to bar.

This variable has been magically created, by simply using a regular ? in the target of the RewriteRule, and tagging on the first captured backreference, %1.. ?bar=%1

Note how we use the % character, to specify variables captured in RewriteCond statements, aka "Backreferences". This is exactly like using $1 to specify numbered backreferences captured in RewriteRule patterns, except for strings captured inside a RewriteCond statement, we use % instead of $. Simple.

You can use the [QSA] flag in addition to these query string manipulations, merge them. In the next example, the value of foo becomes the directory in the target URL, and the variable file is magically created. The original query string is then tagged back onto the end of the whole thing..

QSA Overkill!
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.+)
RewriteRule ^grab/(.*) /%1/index.php?file=$1 [QSA]

So a request for..

is translated, server-side, into..

Depending on your needs, you could even use flat links and dynamic variables together, something like this could be useful..

By the way, you can easily do the opposite, strip a query string from a URL, by simply putting a ? right at the end of the target part. This example does exactly that, whilst leaving the actual URI intact..

just a demo!
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} .
RewriteRule foo.php(.*) /foo.php? [L]

The RewriteCond statement only allows requests that have something in their query string, to be processed by the RewriteRule, or else we'd end up in that hellish place, dread to all mod_rewriters.. the endless loop. RewriteCond is often used like this; as a safety-net.

If all you are after is a /simple/flat/link/ to server-side.php?query=variable translation, use something like this..

cooler access denied

In part one I demonstrated a drop-dead simple mechanism for denying access to particular files and folders. The trouble with this is the way our user gets a 403 "Access Denied" error, which is a bit like having a door slammed in your face. Fortunately, mod_rewrite comes to the rescue again and enables us to do less painful things. One method I often employ is to redirect the user to the parent folder..

they go "huh?.. ahhh!"
# send them up!
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)$ ../ [NC]

It works great, though it can be a wee bit tricky with the URLs, and you may prefer to use a harder location, which avoids potential issues in indexed directories, where folks can get in a loop..

they go damn! Oh!
# send them exactly there!
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)$ /network/routers/Voyager/ [NC]

Sometimes you'll only want to deny access to most of the files in the directory, but allow access to maybe one or two files, or file types, easy..

deny with style!
# users can load only "", and the css and js files.
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_FILENAME} !$
RewriteRule ^(.+)$ /chat/ [NC]

Here we take the whole thing a stage further. Users can access .css (stylesheet) and Javascript files without problem, and also the file called "", but requests for any other file types are immediately redirected back up to the main "/chat/" directory. You can add as many types as you need. You could also bundle the filetypes into one line using | (or) syntax, though individual lines are perhaps clearer.

For those that don't code, the "!" sign simply means not something. In most programming languages one writes "not equal to" as "!=" or "!==" or similar.

Here's the sort of thing you might find inside my /inc/ directory..

all-in-one control..
RewriteEngine on
Options +FollowSymlinks
# allow access with no restrictions to local machine at
RewriteCond %{REMOTE_ADDR} !
# allow access to all .css and .js in sub-directories..
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.js$
# allow access to the files inside img/, but not a directory listing..
RewriteCond %{REQUEST_URI} !img/(.*)\.
# allow access to these particular files...
RewriteCond %{REQUEST_URI} !comments.php$
RewriteCond %{REQUEST_URI} !gd-verify.php$
RewriteCond %{REQUEST_URI} !post-dumper.php$
RewriteCond %{REQUEST_URI} !source-dump.php$
RewriteCond %{REQUEST_URI} !textview.php$
RewriteRule . http://%{HTTP_HOST}/ [R,NC,L]

Ban User Agents, referrers, script-kiddies and more..

There are many valid reasons to ban a particular request from sucking up your site's resources; resources that could be better served to valid, interested users. It might be some cross-site attack script, or inward link from a place you don't want to be associated with, or perhaps a web sucker or download manager, whatever; .htaccess + mod_rewrite provides ways to protect your content from unwanted "guests".

The basic formula is standard if-then logic: if the request meets a particular CONDITION, then REWRITE the request. The "conditions" can be many things; perhaps the referrer header sent by their browser (the site they came from), or the page they asked for, or a particular query parameter, or the type of client (browser, etc.) they are using, or any other piece of information Apache has attached to the request. Here's an example which will deny access to "Teleport Pro", a download manager which is known to suck, hard..

Who need's a local copy, when I'm right here?..
RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [NC]
RewriteRule . abuse.txt [L]

It's your site, and just like your home, you have every right to exert some control over who gets in. You may have a huge list of user agents you'd rather not have eating your bandwidth; so use the [OR] flag, and line 'em up..

A little garlic for the net vampires..
RewriteCond %{HTTP_USER_AGENT} ^BackWeb [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^Bandit [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BatchFTP [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BecomeBot [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [NC]
RewriteRule . abuse.txt [L]

This forms the basis of what often becomes a HUGE list of ban-lines. Remember, we aren't limited to user agent strings..

Suckers, h4x0rz, kiddies, cross-site scripters and more.. Bye now!
# why not come visit me directly?
RewriteCond %{HTTP_REFERER} \.opendirviewer\. [NC,OR]
# this prevents stoopid cross-site discovery attacks..
RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
# please stop pretending to be the Googlebot..
RewriteCond %{HTTP_REFERER} users\.skynet\.be.* [NC,OR]
# really, we need a special page for these twats..
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
RewriteCond %{REQUEST_URI} owssvr\.dll [NC,OR]
# you can probably work these out..
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} Sucker [NC]
RewriteRule . abuse.txt [L]

Fortunately, mod_rewrite can parse enormous lists of ban-lines in milliseconds, so feel free to be as specific and comprehensive as required.

As ever, thorough testing is strongly recommended. Simply send requests matching your conditions and see what happens. And importantly; normal requests, too. Firefox, Opera, Konqueror, and most other decent browsers, allow you to alter the user agent string; though you would quickly find the process tedious in a testing situation. Far better to use some tool better designed to send fake HTTP requests..

It's not too difficult to mock up a web request on the command-line with any-old user agent using a scripting language like php or Perl, if you have these things available (read: most Linux/UNIX/BSD/etc. as well as many other OS). Many examples exist online. In fact, you could quickly create a suite of tests, designed to interrogate all your rewrite rules, with results logging and much more, if required. cURL is always useful for jobs like this, so long as you don't add a cURL ban-line!

On a Windows desktop, Sam Spade can send a single spoofed request with a couple of clicks, along with a stack of similarly handy tricks, and regularly proves itself invaluable.

Don't let just anyone hammer your site!

While I'm on the subject of abusive web clients, you will probably have noticed that many clients (bots, spiders, automated suckers and such) like to disguise their user agent information, in fact any information, in an attempt to bring your site to its knees, hammering your pages umpteen times per second in the process. Not good.

If you are interested in a way to defeat hammering web clients regardless of who they pretend to be or whether or not they accept cookies or any such malarkey, protecting your valuable server resources for genuine clients, check out: Anti-Hammer.

prevent hot-linking

Believe it or not, there are some webmasters who, rather than coming up with their own content will steal yours. Really! Even worse, they won't even bother to copy to their own server to serve it up, they'll just link to your content!  no, it's true, in fact, it used to be incredibly common. These days most people like to prevent this sort of thing, and .htaccess is one of the best ways to do it.

This is one of those directives where the mileage variables are at their limits, but something like this works fine for me..

how DARE they!
Options +FollowSymlinks
# no hot-linking
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?corz\.org/ [NC]
RewriteCond %{REQUEST_URI} !hotlink\.(gif|png) [NC]
RewriteRule .*\.(gif|jpg|png)$

You may see the last line broken into two, but it's all one line (all the directives on this page are). Let's have a wee look at what it does..

We begin by enabling the rewrite engine, as always.

The first RewriteCond line allows direct requests (not from other pages - an "empty referrer") to pass unmolested. The next line means; if the browser did send a referrer header, and the word "" is not in the domain part of it, then DO rewrite this request.

The all-important final RewriteRule line instructs mod_rewrite to rewrite all matched requests (anything without "" in its referrer) asking for gifs, jpegs, or pngs, to an alternative image.

There are loads of ways you can write this rule; Google for "hot-link protection" and get a whole heap. Simple is best. You could send a wee message instead, or direct them to some evil script, or something. Mine is a simple logo, which I think is rather clever. Actually, these days, I do something even cleverer-er..

lose the "www"

I'm often asked how I prevent the "www" part showing up at my site, so I guess I should add something about that. Briefly, if someone types into their browser (or uses the www part for any link at it is redirected to the plain, rather neat, version. This is easy to achieve, like so..

beware the regular expression:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{http_host} ^www\.corz\.org [NC]
RewriteRule ^(.*)$$1 [R=301,NC]

You don't need to be touched by genius to see what's going on here. There are other ways you could write this rule, but again, simple is best. Like most of the examples here, the above is pasted directly from my own main .htaccess file, so you can be sure it works perfectly. In fact, I recently updated it so that I could share rules between my dev mirror and live site without any .htaccess editing..

here's what I'm currently using:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]

multiple domains in one root

If you are in the unfortunate position of having your sites living on a host that doesn't support multiple domains, you may be forced to roll your own with .htaccess and mod_rewrite. So long as your physical directory structure is well thought-out, this is fairly simple to achieve.

For example, let's say we have two domains, pointing at a single hosted root; and In our web server root, we simply create a folder for each domain, perhaps one/, and two/ then in our main (root) .htaccess, rewrite all incoming requests, like this..

All requests NOT already rewritten into these folders, transparently rewrite..
#two domains served from one root..
RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^/one

RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^two
RewriteRule ^(.*)$ two/$1 [L]

All requests for the host are rewritten (not R=redirected) to the one/ directory, so long as they haven't already been rewritten there (the second RewriteCond). Same story for Note the inconsistency in the RewriteCond statement; !^/dir-name and !^dir-name should both work fine. But needless to say, if you get a 500 error on your server, that would be a good place to start looking!

Also note, with such a simple domain & folder naming scheme, you could easily merge these two rule sets together. This would be unlikely in the real world though, which is why I left them separate; but still, worth noting.

Other general settings and php directives can also go in this root .htaccess file, though if you have any further rewrite you'd like to perform; short URL's, htm to php conversion and what-not; it's probably easier and clearer to do those inside the sub-directory's .htaccess files.

automatic translation

If you don't read English, or some of your guests don't, here's a neat way to have the wonderful Google translator provide automatic on-the-fly translation for your site's pages. Something like this..

they simply add their country code to the end of the link, or you do..
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)-fr$$1 [R,NC]
RewriteRule ^(.*)-de$$1 [R,NC]
RewriteRule ^(.*)-es$$1 [R,NC]
RewriteRule ^(.*)-it$$1 [R,NC]
RewriteRule ^(.*)-pt$$1 [R,NC]

You can create your menu with its flags or whatever you like, and add the country code to end of the links.. <a href="page.html-fr" id="... Want to see this page in French?

Although it is handy, and I've been using it here for a couple of years here at the org for my international blog readers, all two of them, heh. Almost no one knows about it, mainly because I don't have any links. One day I'll probably do a wee toolbar with flags and what-not. Perhaps not. Trouble is, the Google translator stops translating after a certain amount of characters (which seems to be increasing, good), though these same rules could easily be applied to other translators, and if you find a good one, one that will translate a really huge  document on-the-fly, do let me know!

If you wanted to be really clever, you could even perform some some kind of IP block check and present the correct version automatically, but that is outside the scope of this document. note: this may be undesirable for pages where technical commands are given (like this page) because the commands will also be translated. "RewriteEngine dessus" will almost certainly get you a 500 error page!

Another thing you might like to try; rather than individual country flags; fr, de, etc., use the "u" flag, for "Universal". In theory, Google will check the client's location, and automatically translate to that language. One line in your .htaccess would cover all languages, and automatically cover new ones as Google adds them.

While I'm here, slightly related; you can do a similar thing browser-side, create a "bookmarklet" (a regular bookmark, except that it "does something"), using this code for the location..

the same sort of thing, except browser-side..

..which you will instinctively learn to click at the merest whiff of unrecognizable text, I reckon. Put it in your toolbar somewhere visible, is my sincere recommendation.


Remember, if you put these rules in the main server conf file (usually httpd.conf) rather than an .htaccess file, you'll need to use ^/... ... instead of ^... ... at the beginning of the RewriteRule line, in other words, add a slash.


If you are creating rules in sub-folders of your site, you need to read this.

You'll remember how rules in top folders apply to all the folders inside those folders too. we call this "inheritance". normally this just works. but if you start creating other rules inside subfolders you will, in effect, obliterate the rules already applying to that folder due to inheritance, or "decendancy", if you prefer. not all the rules, just the ones applying to that subfolder. a wee demonstration..

Let's say I have a rule in my main /.htaccess which redirected requests for files ending .htm to their .php equivalent, just like the example at the top of this very page. now, if for any reason I need to add some rewrite rules to my /osx/.htaccess file, the .htm >> .php redirection will no longer work for the /osx/ subfolder, I'll need to reinsert it, but with a crucial difference..

this works fine, site-wide, in my main .htaccess file
# main (top-level) .htaccess file..
# requests to file.htm goto file.php
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$$1.php [R=301,NC]

Here's my updated /osx/.htaccess file, with the .htm >> .php redirection rule reinserted..

but I'll need to reinsert the rules for it to work in this sub-folder
# /osx/.htaccess file..
Options +FollowSymlinks
RewriteEngine on
RewriteRule some rule that I need here
RewriteRule some other rule I need here
RewriteRule ^(.*)\.htm$$1.php [R=301,NC]

Spot the difference highlighted in the subfolder rule?. You must add the current path to the new rule. now it works again, and all the osx/ subfolders will be covered by the new rule. if you remember this, you can go replicating rewrite rules all over the place.

If it's possible to put your entire site's rewrite rules into the main .htaccess file, and it probably is; do that, instead, like this..

it's a good idea to put all your rules in your main .htaccess file..
# root /.htaccess file..
Options +FollowSymlinks
RewriteEngine on
# .htm >> .php is now be covered by our main rule, there's no need to repeat it.
# But if we do need some /osx/-specific rule, we can do something like this..
RewriteRule ^osx/(.*)\.foo$ /osx/$ [R=301,NC]

Note, no full URL (with domain) in the second example. Don't let this throw you; with or without is functionally identical, on most servers. Essentially, try it without the full URL first, and if that doesn't work, sigh, and add it - maybe on your next host!

The latter, simpler form is preferable, if only for its tremendous portability it offers - my live site, and my development mirror share the exact same .htaccess files - a highly desirable thing.

By the way, it perhaps doesn't go without saying that if you want to disable rewriting inside a particular subfolder, where it is enabled further up the tree, simply do:

handy for avatar folders, to allow hot-linking, etc..
RewriteEngine off


Lastly, a quick word about cookies. While it's easy enough to set cookies in .htaccess without any mod_rewrite..

create a cookie called "example-cookie", and set its value to "true"..
Header set Set-Cookie "example-cookie=true" will need it to read the cookie information back again, and "do stuff" with it. It's easy. For example, to check if the above cookie exists and has the correct value set, we could simply do..

check for that same cookie + value..
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_COOKIE} !example-cookie=true
RewriteRule .* /err/401.php

..which could easily form the basis of a simple authentication system. As with any RewriteCond, you can get pretty complex, checking multiple cookies, utilizing regexp and more, but that's enough to get you started. You will probably want to add another RewriteCond to prevent looping on the 401. I'll leave that as an exercise.

While I'm at it, note, you can also set cookies with a RewriteRule. Check this..

Set a cookie with this visitor's "Original Referer", using RewriteRule..
SetEnvIf Referer "^https?://(.*)/" myref=$1
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} ! [NC]
RewriteRule . - [cookie=original-referer:%{ENV:myref}:.%{HTTP_HOST}:1440:/]

The first line checks the value of the "Referer" header (usually sent by the browser - by the way, the misspelling of "referrer" annoys a lot of people, but its hard-coded into the web now)

Let's say the referring URI is "", which matches (of course it matches, all Referers will match!) so the part between "https?://" and the next occurring slash ("/") of the referring URI is captured inside the braces () and then backreferenced (by the use of "$1", 1 = the first captured string, in this case ""), that value being stored in an Environment Variable (Apache has loads of them created on every request, your IP address, browser type, time of the request, remote port, loads...) named "myref".

In other words:

Then we do a couple of RewriteCond conditions, the first to prevent "empty" referers (where no referer information is sent) and the second to prevent resetting the cookie with the name of our own domain*. Then it's down to business..

The RewriteRule, its simple dot "." expression, again matching every single request, passing the request straight through (to any remaining .htaccess code, by use of the "-") without altering the URI in any way, and while it's at it sets the browser's cookie variable "original-referer" to the value of the Apache variable "myref", which is currently "", accessing this variable by use of the "%{ENV:<Name-of-Environment-Variable>}" construct.

The domain of the cookie is set to "". Note, it's best practice to use a preceding dot in "www"-less, or other sub-less domains).

The cookie will expire in approximately 1440 minutes (24 hours). The cookie "path" is set to "/", covering the entire site. Job done.

Finally, having said ALL that, I'd still much rather use PHP sessions wherever possible, and if taking a chance on something more permanent, with a persistent cookie, php (or similar) is still a better place to be coding this sort of stuff.


In short, mod_rewrite enables you to send browsers from anywhere to anywhere. You can create rules based not simply on the requested URL, but also on such things as IP address, browser agent (send old browsers to different pages, for instance), and even the time of day; the possibilities are practically limitless.

The ins-and outs of mod_rewrite syntax are topic for a much longer document than this, and if you fancy experimenting with more advanced rewriting rules, I urge you to check out the Apache documentation.

If you have Apache installed on your system.. there will likely be a copy of the Apache manual, right here, and the excellent mod_rewriting guide, lives right here. do check out the URL Rewriting Engine notes for the juicy syntax bits. That's where I got the cute quote for the top of the page, too.

Have fun!


troubleshooting tips..

Fatal Redirection

If you start messing around with 301 redirects [R=301], aka. "Permanently Redirected", and your rule isn't working, you could give yourself some serious headaches..

Once the browser has been redirected permanently to the wrong address, if you then go on to alter the wonky rule, your browser will still be redirected to the old address (because it's a browser thing), and you may even go on to fix, and then break the rule all over again without ever knowing it. Changes to 301 redirects can take a long time to show up in your browser.

Solution: restart your browser, or use a different one.

Better Solution: Use [R] instead of [R=301] while you are testing. When you are 100% certain the rule does exactly as it's expected to, then switch it to [R=301] for your live site.

rewrite logging..

When things aren't working, you may want to enable rewrite logging. I'll assume you are testing these mod_rewrite directives on your development mirror, or similar setup, and can access the main httpd.conf file. If not, why not? Testing mod_rewrite rules on your live domain isn't exactly ideal, is it? Anyway, put this somewhere at the foot of your http.conf..

Expect large log files..
RewriteLog "/tmp/rewrite.log"
#RewriteLogLevel 9
RewriteLogLevel 5

Set the file location and logging level to suit your own requirements. Unless you are using Apache >= v2.4. Now your old RewriteLog directives will bring the server down..

Recent versions of Apache need this, instead..
LogLevel alert rewrite:trace3

This sets the main LogLevel to alert, and turns it up the volume of rewrite logging trace3. A full explanation of the various LogLevel and trace options can be found here.

If the offending rewrite rule is causing your Apache to loop, load the page, immediately hit your browser's "STOP" button, and then restart Apache. All within a couple of seconds. Your rewrite log will be full of all your diagnostic information, and your server will carry on as before.

Setting a value of 1 gets you almost no information, setting the log level to 9 gets you GIGABYTES! So you must remember to comment out these rules and restart Apache when you are finished because, not only will rewrite logging create space-eating files, it will seriously impact your web server's performance.

RewriteLogLevel 5  is very useful, but 2 is probably enough information for most issues. In the new scheme, trace:3 is probably about as high as you want to go, unless you have lots of space and time.

Suddenly "Forbidden"..

On the subject of new and improved Apache versions, if you are rolling your own server you may have noticed that your sites dramatically fail to load after an Apache upgrade. Everything is "Forbidden", and you don't have permission to access, well anything.

It's possible that your site's DocumentRoot points to a symlink. If that's the case, add this to your site's host (probably vhost) section:

Oh yes, it's a "permissions problem"..
Require all granted

And you're in!

A php script to make your mod_rewrite life easier.

When things aren't working as you would expect, rewrite logging is a good option, but on a hosted server, you probably won't have that option, without access to httpd.conf. Fortunately, what's usually required is no more than a quick readout of all the current server variables, $_GET array, and so on; so you can see exactly what happened to the request.

For another purpose, I long ago created debug.php, and later, finding all this information useful in chasing down wonky rewrites, created a "report" version, which rather than output to a file, spits the information straight back into your browser, as well as $_POST, $_SESSION, and $_SERVER arrays, special variables, like __FILE__, and much more.

Usage is simple; you make it your target page, so in a rule like this..

Send EVERYTHING to the debug unit..
RewriteRule ^(.*)\.html$ /catch-all.php?var=$1

You would have a copy of debug-report.php temporarily renamed to catch-all.php in the root of your server, and type into your address bar and, with yer mojo working, debug-report.php leaps into your browser with a huge wodge of exactly the sort of information you need to figure out all this stuff. When I'm messing with mod_rewrite, debug-report.php saves me time, a lot. It's way faster than enabling rewrite logging, too. Also, it's free..


debug report

Before you ask a question..

Firstly, read this at least once in your life. I insist!

NOTE: THIS IS NOT A COMMUNITY. And I am not your free tech dude. Sure, folk sometimes drop back in, but realistically, the chances of someone else coming along and answering your tech question are about as close to zero as it gets; almost no one sticks around but me, the guy who wrote all that text (above).

If you can't be bothered to read the article, I can't be bothered responding. Capiche? I do read all comments, though, and answer questions about the article. I'm also keen to discuss anything you think I've missed, or interesting related concepts in general.

If you are still sure that you want to post your own, personal, tech question, then please ensure that you first, either..

a) Have read the article (above) and have tried "everything" yourself; in which case; post the exact code that isn't working (preferably inside [pre][/pre] tags), replacing any personal domain names with "" (advertising gets deleted) or else..

b) Pay me. The PayPal button is at the top right of the page. I offer many related services, if you need priority assistance, get in touch.

Other posts will be ignored and/or deleted.

return to paged comments
cor - 06.11.04 10:26 pm

I decided to add comments here too,
we're most definitely in different territory with this page.

;o) Cor

Al Raq - 09.11.04 4:17 am

Thank you.
You helped me solve a problem with hotlinkg.
Kind regards.

cor - 09.11.04 9:15 pm

Thanks Al, that's what makes it all worthwhile.

;o) Cor

ZiZe - 28.11.04 1:06 pm

Nice article.
One of the best about .htaccess i've read so far, and it helped me solve a problem i had with hot-linking.

tnx :)

Tony Elliott - 06.12.04 5:52 am

You have a good teaching gift :) I understood what you wrote.
Great work, I have bookmarked this site for future reference.

maxcreation - 10.03.05 3:34 pm

RewriteRule ^files/(.*)/(.*).zip /download.php?section=$1&file=$2

I was looking for a solution to redirect partially to what rule matched and $1 etc was solution. It was hard to find.

I kinda googled Google trough and then later I accidentally find this article. Its great! Thank you. :)

cor - 10.03.05 9:51 pm

Yup, it's a cute and powerful command, like much of the rewrite stuff, Ralf did a great job.

More than once I've started to code some cute redirection in php with the idea that I'd "like to move away from htaccess", but usually realise fairly quickly that it's just simpler and more elegant this way. My ubercool 404 page being the exception.

You know I've even had emails from folk saying they don't believe half this stuff will work because it's too simple. smiley for :lol:

Well, I reply, I try!

;o) Cor

guido - 22.03.05 12:02 am

here's my current redirect:

RewriteRule ^block/(.*)/(.*) /mydir/block.php?divid=$1&xtra=$2

So the url http://../block/fire/wood would go correctly to:

but what about if there is no second part.
This works:
http://../block/fire/ (goes to /mydir/block.php?divid=fire&xtra=)
But This doesn't
http://../block/fire (goes 404)

is there a way to send this even if there is no trailing / ?

And something else i just noticed, if I go:
http://../block/fire/ it will resolve to:

cor - 23.03.05 12:14 pm

well, firstly, it's you that's supplying the links, so we wouldn't expect to get "unfinished" URL's!

In answer to your question, yes! You simply make the slash an "optional" character, something like this..

RewriteRule ^block/(.*)/?(.*) /mydir/block.php?divid=$1&xtra=$2

So it shouldn't matter whether you have a slash or not, both will work. This trick is commonly used to combat "the trailing-slash problem".

As to your second issue, it's a matter of approach. Using mod_rewrite to split up multiple variables, particularly when the are free (not supplied specifically by your pages) is not ideal.

You (and the server) could handle the whole thing more efficiently by passing everything after "block" and using php to split up the string into its respective variables. I'm not saying it's impossible, just that it would be a whole lot of messing around when a simpler approach exists. Also you benefit from better error handling, etc.

As with all rewrite fun, some experimentation is involved!
have fun!

;o) Cor

Secret Chamber - 08.04.05 6:57 pm

I was wondering if you use htaccess to password a directory, is every file in that directory protected from search engine and other bots?

mikolaj - 09.04.05 7:07 pm

Excellent write up -- this was exactly what I was looking for.
Great work.

cor - 09.04.05 9:24 pm

Secret Chamber, if you password protect a directory, nothing and no one can access any file inside it, unless authorised. If you need to limit access to only certain files, check out the hide files stuff on the first htaccess article. You could even password protect cetain files and allow regular access to others.

thanks mikolaj, I kinda hoped it would be.

;o) Cor

cor - 10.04.05 10:59 pm

rewriting multiple GET variables

This is from an email (by the way, you get a MUCH faster response if you post your questions on this page!), but I thought I'd drop it here, because I imagine others will find this useful, and I didn't cover this trick in the main article. The email..

Here is the rule I am trying to get work

RewriteRule ^(.*).html$ /?view=$1 [nc]
RewriteRule ^(.*).html\?(.*)$ /?view=$1&$2 [nc]

Basically what I want to make work is this. If I go to

corz.html => /?view=corz

but what I also want to work is this

corz.html?status=1&job=jedi => /?view=corz&status=1&job=jedi

only the first works... and the name/value pairs in the second example can not be retreived via $_REQUEST, it only returns /?view=corz.

It's a good question, and can't be solved with the "normal" rewrite methods.

The problem is that mod_rewrite doesn't consider the GET variables as part of the regular request string, but that doesn't mean it doesn't see them. The solution goes like this..

RewriteRule ^(.*).html(.*) /?view=$1&%{QUERY_STRING} [nc]

That's it, a nasty hack, but simple and effective!

for now..

;o) Cor

cor - 10.04.05 11:02 pm

forgot to mention, you can usually get off with simply using the "qsa" flag (query string append)..

RewriteRule ^(.*).html(.*) /?view=$1 [nc,qsa]

;o) Cor

Jan! - 12.04.05 9:27 pm

I am rather puzzled by your anti-hotlinking rules:

RewriteCond %{HTTP_REFERER} !^http://?corz?.*$

The question marks don't make sense to me. First of all, the second slash in http:// is not optional, as far as I know. What browser would send a referer like http:/ instead of

The second question mark makes the "z" entirely optional. That means that anything starting with http://cor is valid.

The .*$ is also unnecessary. It does not give any extra information to the regular expression engine. "Hey, I want something that starts with this and ends in anything whatsoever" is the same as just saying "Hey, I want something that starts with this".

My suggestion is to change the rule to these rules:

RewriteCond %{HTTP_REFERER} !^http://(www\.)?corz\.org/
RewriteCond %{HTTP_REFERER} !^http://(www\.)?corzoogle\.com/

I know the "www" part is not used on your site, but seeing how this is an example to many, it could prove useful.

PS: I didn't include the "[nc]" flags because your parser kept barfing errors about the tags being unbalanced. Bloody helluva trial-and-error finding that out! You might want to give some better feedback, such as text in the neighbourhood of the error. (I finally found the answer after meticulously examining your sample bbcode.)

cor - 13.04.05 5:16 am

Hah! well, the simple answer is that I did the hot-link protection before I fully understood the optional characters. It was one of those messy times when it fixed something that wouldn't work, and got left in, maybe; slipped through. This often happens to .htaccess code that works, almost superstitiously, in fact.

I discovered the "Hey, I want something that starts with this and ends in anything whatsoever" is the same as just saying "Hey, I want something that starts with this" a while back, quite by accident, but again, the old hot-link code got overlooked, probably other .htaccess code, too, it just works!

I don't get off with this kind of slackness with the php stuff, it has users. You're right, though, this page has users too, a lot of folk travelling through, so I really should pay more attention! Thankfully I've got visitors willing to take the time to keep me right. Thanks for that. Or rather, this..

RewriteCond %{HTTP_REFERER} !^http://(www\.)?corz\.org/ [nc]

Much more elegant than my messy example! I'll put it up where it belongs. Thanks again Jan!

;o) Cor

ps.. for a bbcode square bracket, you do it doubled.. [[!]] <- I had to do four there! smiley for :D

pps.. the bbcode tag balance checking is new for the current cbparser beta, and although fairly rudimentary, is deadly effective! More user feedback on which tag is barfing would be smart. noted. ta.

Jan! you can come back any time!

Steve - 19.04.05 10:06 pm

Jan, great work on the page. However, I am despeately trying to find a solution to do the following:

(1) Redirect

(2) Maintain in address bar of browser.

RewriteRule seems to only work with local pages within the same domain. If I want to rewrite and hide the real physical link that I am redirecting to, being an external domain, it does not seem to work.

Any thoughts?

cor - 20.04.05 2:18 pm

for deception of this kind, and breaking the internet in general, use frames.

;o) Cor

speeke - 23.04.05 2:22 am

Hi all

I would like to have my urls

(eg )

show up as: OR simply

Sometimes these links are generated using the GET command, other times they are direct links.

Any suggestions gratefully received.

PS I am not a php whiz by any means, so please be kind. :)

speeke - 23.04.05 2:23 am

Hmmm - the 'preview my comment' and 'add my comment' buttons appear to do the same thing, so sorry about the double post!

cor - 23.04.05 12:53 pm

The buttons do the same thing dude, it's the refresh button that reposts your comment (doesn't your browser warn you that you are about to do this?) no worries, I just delete 'em!

To the question, I'm not sure if I understand it correctly.

The links are generated by your php, the form of the links is the crucial point. Either they are "flat", like or "dynamic", like⊂=socks&type=wool

First decide which you'd like to use. You would be best to stick to one or the other, at least for the particular section/site/page we are theoretically discussing.

The .htaccess side of things (la raison d'etre pour cette page!) will catch ALL links and transform them to your requirements. I will presume you want nice user-friendly "flat" links to appear on your page, so really it's simply a question of working out what they will be, and putting together some regex to catch them.

I suspect that you are really looking for php advice, but I'm still not ready to go public with that part of the site! smiley for :geek:

;o) Cor

mikolaj - 23.04.05 10:12 pm

since I'm using MySQL on my site, i have one main template -- the index.php -- and all pages are created with ?page=aboutus for example. since i would like to convert to a friendlier /aboutus/, which is easy, i've run into a problem.

I set the .htacccess as
RewriteRule ^(.*) /index.php?page=$1

which works for what i'm going after; but now all images and scripts stored under the root directory is considered a ?page=$1 (!)
(like, /images/ and /css/)

I want the site to be "" and not "" (which can be done and fix the root-directory-problem.)

what do you suggest?

armadillo - 27.04.05 4:38 pm

I have scoured the internet for days, and nothing I've found or tried has worked. What I want to do is restrict access to the music files in a directory to only those who link the files directly from my site. In other words, I want to make it impossible to get these files if you simply enter the url in the location bar, so the only way you can get them is to use the link on a page I've set up. Is there a way?

cor - 27.04.05 7:01 pm

armadillo, see HotLink Protection (above). If you also want to prevent direct (typed-in) access, remove this line..
RewriteCond %{HTTP_REFERER} !^$

although be warned, some browsers don't send correct referer information, and they won't be able to download your files, even if they do use your special links.

There will be more complex ways to do this. For instance, you might want to set a cookie with your page, and read it again with the .htaccess file in the same folder as the music files, at least then they would have to have visited your page. An example (nicked from, when it was still around)..
Cookie Password Protection

Make a folder to be protected.
Then upload a .htaccess file with the following lines.

RewriteEngine on
RewriteCond %{HTTP_COOKIE} !^.*access=granted.*$
RewriteRule .*$

Its a good idea to change access=granted to your own "password" to stop
people from being able to guess it. Create a file and call it whatever
you like (some hard to guess), put it in a public folder.
function setCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
function fixDate(date) {
  var base = new Date(0);
  var skew = base.getTime();
  if (skew > 0)
    date.setTime(date.getTime() - skew);
var now = new Date();
now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
setCookie("access", "granted", now);


The code above will create the cookie to be read by the htaccess file.
If the visitor hasn't been to this page, they won't get access. 

If you felt kinky, you could even rotate the values with php.
You might also want to take a look at this.

oops! mikolaj missed another comment! smiley for :roll: your command looks like it would send the server into a spin-cycle! But assuming that it does work for you (tell me how!) you could try a couple of rewritecond lines to match the affected directories..

rewritecond %{REQUEST_FILENAME} !^\/images\/(.*)$

or else, perhaps only do the rewrite when the requested file doesn't actually exist..

RewriteCond %{REQUEST_FILENAME} !-f

There are a few ways to do this, but that should work okay.

for now..

;o) Cor

cor - 27.04.05 7:32 pm

I was thinking about this dynamic site thing and I thought I might put it all together for other interested (yet clueless) souls out there! if you want to try this sort of thing out for yourselves, here is a miminimum ruleset, as I see it..
# for "dynamic" data-driven sites..
options +followsymlinks
rewriteengine on
rewritecond %{REQUEST_FILENAME} !-f
rewriterule ^(.*)$ http://mytest/index.php?page=$1 [nc]
"mytest" is a fictional testing domain, running on your own machine!
Your index.php file might start by containing the following..
echo 'Yo! Page = '.@$_GET['page'];
to check on the variable being passed. If you requested "http://mytest/img/toolbar/foo.jpg" and that file doesn't actually exist, you will get..

Yo! Page = img/toolbar/foo.jpg

in the resultant page. Then it's just a question of splitting the path variable ($_GET['page']) into its elements.

;o) Cor

mikolaj - 28.04.05 3:50 am

Actually, I got it:
RewriteRule ^({^/}+)/$ /index.php?page=$1 {L}

(for whatever reason I can't add a bracket in the code -- so i used a "{" in it's place.)

See it in action:

cor - 28.04.05 3:16 pm

Bandwidth Limit Exceeded!

That's recursive rewrite rules for ya! smiley for :lol:

The [L] simply prevents mod_rewrite from processing further rules, but it won't always prevent a recursive loop. (to do a square bracket with bbcode, double it; [] <- I did four there!)

Experimentation, trial-and-error is usually the way with mod_rewrite. The main thing is, it works for you, and while it may not work in every situation, most of us are only trying to deal with one situation, so hat's off, sir!

for now..

;o) Cor

ps.. While experimenting with rewrite rules (on your test server), in particular, with rules that aren't working, it's often useful to add the following lines to your server config (httpd.conf)..
RewriteLog "/home/test/rewrite.log"
RewriteLogLevel 9

The log location is up to you, the log levels probably go from 1 (almost no information) to 9 (a lot of information). Remember to disable (comment out) once you get the rule working!

mikolaj - 29.04.05 4:54 am

ah, the log-- that's a good idea. thanks.
as for the bandwith, we have mp3 samples that's probably eating it up.

cor - 29.04.05 10:56 am

And impressive MP3's at that! If I ever have a Maui Wedding, I'll be in touch! I was just kidding about the bandwidth, I don't think recursive rewrite loops count towards bandwidth usage, mind you, some web hosts smiley for :eek: ... not mine! they rock! smiley for :D

And yes, the rewrite log is very often overlooked, even by folk who know it exists. It is extremely useful, but watch out! it fills up very quickly, especially during recursive loops!

;o) Cor

euio - 30.04.05 7:42 am

hello, just a question. In shortening urls, u said


this rule would transform this user's URL..


server-side, into..



should public, files, download folders be existent to use the shortening of files?

cor - 30.04.05 2:50 pm

yes and no.

For this rule, yes, it points to an actual file, "download.php", which must exist, and so all the folders it lives inside. There are no rules following this one, so it has to point to somewhere real.

But rewrite rules themselves are not limited to "real" files, you can redirect to anything at all. Scroll up the comments a bit to see how we were creating nice "real" looking paths that are in fact nothing more that variables. You can redirect to "in-between" strings that will later be redirected again to "real" files, etc, etc.

I used "/public/files/download/" simply to demostrate how a very deep place (with its long URL) could be presented with a very short URL, but the possibilities are practically limitless.

It all depends on what are you trying to do...

;o) Cor

Made up name ! :D - 01.05.05 5:40 pm

Quick question ... I've been trying to figure out a way to do this:

when people type it points to

How can I do that ?

Thanks very much !

cor - 02.05.05 12:17 am

dude! that's the default action!

It should just happen. So long as ensure "script" is the file Apache would use as its index, ie "index.php".


;o) Cor

Made - 02.05.05 2:17 am

Hey cor ! Thanks for the answer ! smiley for :D

Quick question though ... if script.php is not the index for apache .. is there a way I can make it point to that script ?

Thanks again !

cor - 04.05.05 4:45 pm

why would you want to do that?

I don't even think it's possible, by the time apache gets to .htaccess level (the last place it looks), it has already trandlated the path to /index.php (or whatever your index file is) so the only way around that would be to rewrite the index requests..
rewriterule ^index.php$ [qsa,nc]

which just seems silly!

;o) Cor

euio - 06.05.05 6:49 am

well, I actually think the whole article write up is rather a very useful reference. ^_^ I also think that you can better expand your article in the future by referring to more specific examples like explaining the .htaccess the wordpress publishes or any other blog softwares. ^_^

I've been visiting this page lately as I'm figuring out/experimenting on some of the topics you have tackled and honestly you've done a great job!

btw, I have a question regarding wordpress' .htaccess.
can you explain this?


euio - 06.05.05 6:55 am

how come I can't post the code??? it says 'preview, tags don't balance'?

here it is again..

cor - 06.05.05 3:27 pm

looks like you were trying to use square brackets, this is a bbcode comment facility, and square brackets is tags! if you need to do square brackets, simply double them -> [[ ! ]] It's all in the instructions page, but I know, life is hectic! Alternatively, put code examples inside pre tags.

I guess you're referring to switches, "qsa" we just did, and means "Query string append", in other words, mod_rewrite will append your GET variables back onto whatever it outputs, and "L", means "last rule", in other words, no further rules will be processed.

I'm not familiar with wordpress, I have my own blogging software! But yeah, this is the page where I should mention that if you install corzblog, and you get a 500 error from your server, try removing the .htaccess files!


;o) Cor

Made up name ! :D - 07.05.05 1:43 pm

Hey cor, I figured out a way to do and I wanted to do .. I just wanted to say thanx for you help and patience ! smiley for :D

See ya !

P.S. Great job on this article !

cor - 07.05.05 7:31 pm

let's see it then!

;o) Cor

euio - 09.05.05 12:07 am

hey cor!
just a quick question...
what if I put all the images under directory, and when I call any image via 'img src' or 'url()', no matter where the html/php file is (say under, I want the the browser to automatically read 'img src=/i/image.jpg' or 'url(/i/image.jpg)' NOT as '' BUT '' when '' is loaded? ^_^


Made - 09.05.05 2:51 am


RewriteRule /?$ script.php?%QUERY_STRING


cor - 09.05.05 5:54 am

yeah, Made, I like it, elegant! Believe it or not, it's what I tried first! But like I said earlier, that command just throws the server into a loop! at least all the servers I have stuff on, but as ever, ymmv, so nice one!

euio, surely I don't understand the question!

Web browsers translate partial paths automatically! If you look at the source of my front page, you'll see the blog image link, for instance, looks like src="/img/bloggerlogo_tn.png" but the browser knows that really means, and grabs the correct image, no problem! HTML 101, dude!

Any link presented to the browser without a leading slash is interpreted as a relative, and any link with a leading slash is interpreted as being "from root", so the browser will add the "" part itself. I'm guessing you've been oscillating between relative "./img/img.png & ../img/img.png" and absolute "http://mydomain/img/img.png" linking. But there is a middle path!

If you are looking to simplify things at the coding stage, why not put the paths into variables and just use them wherever you need to place content. I always start any page by declaring lots of variables like $root, and $domain, and stuff, so I don't have to keep typing them.

$img_path = 'path/to/images/';

Though if you're simply using /i/, that does seem kinda retrograde!

;o) Cor

euio - 09.05.05 7:40 am

^_^you pretty much answered my question actually when you said

"Any link presented to the browser without a leading slash is interpreted as a relative, and any link with a leading slash is interpreted as being 'from root'"

The instant I picked up what you mean, I realized my question really was confusing...


example scenario... given 'http://site/' as the root...

I load index.php

http://site/folder1/index.php (note folder1)

and in it I call for the image.jpg with leading slash

img src="/imagefolder/image.jpg"

With that I mistakenly assumed that "/imagefolder/image.jpg" = "http://site/folder1/imagefolder/index.php"

which is completely in contrast to your explanation... which suggests that...

since the root is http://site/, hence, "/imagefolder/image.jpg" is equivalent to "http://site/imagefolder/image.jpg"

well i think it's clearer to me now ^_^

euio - 12.05.05 4:41 pm

Does anyone know a way to have .htaccess alter a URL so that if someone clicks a URL with an extra part appended to it, our .htaccess will remove the appended portion and send them to the correct URL?

This post I sent to google may explain what I mean in better terms:

cor - 12.05.05 10:28 pm

I'll tell you how if you remove that obscene scrolling javascript from your website! smiley for :lol:

;o) Cor

ps.. look at the status bar when you're browsing around! That's how you do the status thing! static!

sol - 13.05.05 7:31 pm

Cor, You helped me with the [QSA] option, which works beautifully. Do you know of a way to pass along POSTED values to the redirect? Thanks.

cor - 14.05.05 8:47 am

hmm, I can't think of a way off-hand. But it probably makes a lot more sense to grab them from inside your script, like this..
$array = $_POST;
echo'<b>POST variables</b><br>
and use them as normal. So long as it's not a permanent redirect (301, etc), they should still be available (along with $_GET variables, ENV variables, etc) in your target script.

;o) Cor

ps.. of course I could have just done "print_r($_POST)", but I wanted to take the extra step to quickly show how to get these babies into a regular array, easy-peezee.

cor - 14.05.05 1:02 pm

It just crossed my mind that not everyone uses php! (why? I don't know!) but these are server variables, so you can get them out with any old api, just look for HTTP_POST_VARS or similar in whatever language you're using!

;o) Cor

arc - 14.05.05 8:00 pm

cor, nice article. My problem is an URL with a variable number of &keys=variables attached. How do I handle this with RegExps? Say:

script.php?key1=value1&key2=value2&(... up to 10)

gives me:

foo/key1/value1/key2/value2/script.html .

How to convert this (back)?

Do you have an idea?

-- arc

cor - 15.05.05 8:44 am

well, arc, it all depends what language you are using server-side. If it's php, there are many ways, check out the pathinfo function. Something I often use myself is this..
$path_pieces = explode("/", $_SERVER['PHP_SELF']);
"explode()" being in my top three most useful functions!

other than php? erm ...

;o) Cor

arc - 16.05.05 12:41 pm

Thanks for your speedy answer.

Sorry, I did not stress that my problem is to re-convert the data. I know how to generate
it; I will use some kind of post-processor in my application for that.

But I don't understand how to decode/transform with regexps lists with an arbitrary number o encoded key-value pairs. You know, in web-applications there is sometimes only one key-value pair transmitted, sometimes more. It would be pretty inelegant to write, say, 10 times a RewriteRule, if the number of key-value pairs is between zero to 8.

In rules like below, the number of backreferences is restricted, because regexps are not recursive (I think):
RewriteRule ^files/(.*)/(.*).zip /download.php?section=$1&file=$2 [nc]

Or is there some magic way around -- some kind of "dynamic backreferencing"?



balkrishna - 16.05.05 3:46 pm

Hi need help

I had written this code on my .htaccess file and uploaded on root, but this code is not working. Why?

Guide me.

cor - 16.05.05 10:57 pm

arc, I don't understand. I suspect what you are attempting to do is something very difficult, when a much more simple solution exists; ie, pass the whole lot to the script and let the script work it out.

balkrishna, what code?

;o) Cor

Sboa23 - 17.05.05 12:14 am

I want to do a mod-rewrite to convert:

to show as

and how would I get:

to show as:

With a mod-rewrite? Can it be done with one line of code? Or a line for each event?


Rob James

cor - 17.05.05 8:31 am

Rob, you're not trying! The first example looks complicated until you turn it around and say, how do I get mod_rewrite to transform this..

into this..

which is a real simple find-and-replace type rule..
rewriterule ^(.*)\.html$$1 [nc]
Try looking at the second one the same way; it's just as easy!

;o) Cor

Sboa23 - 19.05.05 3:20 am

I see what you are saying; however, I am trying to make dynamic urls static using a mod rewrite.

I am trying to make the drop the subfolder and rewrite everything after the "=" into a static html page.

Then one to make
drop out the subfolder and just show the page after the domain.

and possibly convert the shtml pages to html pages using mod rewrite.

I understand the above postings have been about making static pages look like dynamic; however, I am trying to do just the opposite.

I am actually trying to drop information and only rewrite some of it. I am trying to get a understanding of the drop part.

Is there documentation some where on the web?

BTW: I installed Tiger on my G3 800 laptop and a old G3 300. It is amazing that the Mac OS keeps making the boxes faster. Then again more ram helps too.

Rob James

cor - 19.05.05 9:11 am

Firstly, no, most everything above is about making dynamic pages look static, that's pretty much the main reason many folk start using mod_rewrite.

I am trying to make the drop the subfolder and rewrite everything after the "=" into a static html page."

The rule I put in my last post will do exactly this!

Then one to make
drop out the subfolder and just show the page after the domain

Again, real simple regex..

rewriteRule ^(.*)/page\.html$ /page.html [nc]

Easy! Quite possibly I simply misunderstand you, I've read your post maybe six times and I'm still no closer to figuring out exactly what you're trying to do.

Let's break it down. These are questions I'd like you to answer..

1. user clicks a link on your page. Is that link written as a static link or a dynamic link? (static: or, dynamic: ) I mean the actual text appearing on the actual page the user gets in their browser. (static/dynamic)

2. What is the URL of the page, the actual real physical page that you want the user to be sent to? (Full URL)

What it looks like you are trying to do is real easy regexp, but like I say, I may simply not understand your exact needs.

As to OS X, that's simply because it started out as a hugely inneficient mess of code, and slowly (actually, not so slowly) the apple engineers are making it cleaner, faster, much more efficient. It'll level out pretty soon methinks.

;o) Cor

Eric - 21.05.05 2:08 am

Made wrote:
Quick question though ... if script.php is not the index for apache .. is there a way I can make it point to that script ?

Yes, that can be done in .htaccess like so:
DirectoryIndex script.php index.html index.php index.phtml index.htm default.htm default.html

That's all one line ... order from first to last determines default precedence.

You can even take it a step further tell PHP to process a file with no extension like so:

<Files script>
ForceType application/x-httpd-php

cor - 21.05.05 6:40 am

I'd taken it as read that anyone messing with rewrite rules would be aware that you could change the default index filename! As you quoted, Made said "...if script.php is not the index for apache .. is there a way I can make it point to that script ?", so surely HE already knows! He wasn't asking to change the default index file, was he? Maybe I misunderstood.

And aye, it's true that you can get php to parse any file, with or without an extension, but forcing php to parse files with no extension is a risky business.

The biggest trouble is that webmasters often put in wee hacks like this, and then forget they are there. A month or two later, some other function is added, lets say, an upload facility, and before you know it you have one enormous security event just waiting to happen. I've seen it happen!

Also it's sloppy, file extensions are there for many good reasons. If someone wants to present dynamic links as http://mysite/foo/bar, then they can achieve this with mod_rewrite, that's why we're here, there's no need to have an actual script called "foo"! In a UNIX environment, extensionless files are generally executable binaries.

It's not evil, as such, to do this in a webserving environment, but there are a few caveats..
  • DO specify an exact filename, in this case "script"
  • ONLY apply this in directories where it is strictly necessary
  • DON'T use extensionless scripts when a rewrite rule will do the job

Remember, If you put something like that in your main .htaccess file, it will apply to your whole site.

At the end of the day, there are better ways to do these things, and I've still not heard one valid reason to use "extensionless" files in a server environment (though they are super-useful on your windows desktop, mapped to regular text files, for "notes".)

As a sidenote, if MultiViews is enabled for a directory, and you have a file in it called file.php, simply requesting "file" will return "file.php", thanks to Apache's "content negotiation". check it out

I'm not having a go, I just feel strongly about this!

;o) Cor

wowbagger - 26.05.05 7:47 pm

this page, alone, has helped me understand this so much! thanks a lot!

Odilon - 01.06.05 5:47 pm

Thanks for the run down on rewriting.

Whilst I can get some of rules working for my site I can't get all.

I'm building a new site. The old site has A LOT of pages with no file extension. For example, I'm trying to get /page_name redirected to /new_page/file.php

Would I need to create a rule for each page? At the moment it seems to choke on the fact that no file extension is specified.

Any clues on how to overcome this?

Slava - 08.06.05 2:42 am

Hi, I have this:
But some time it can be just

It varies. so how can I make it look loke like:
Thank you for your help.

cor - 08.06.05 2:54 pm

Odilon, my first thought, perhaps a lateral one, is "why not ADD extensions?". You say you are building a new site, so don't continue this bad habit, eradicate it!

If this is not possible for some reason (why, oh why?), what you ask is simple, one blanket rule redirecting to /new_page/file.php, though you don't say how you would like the old location to be incorporated into the new location, for instance, /new_page/file.php?page=page_name, and the blanket exaples (above) would do that.

If you give us more idea about exactly how you need the final request to look, I could cook a better rule maybe, but I still recommend you ADD EXTENSIONS! smiley for :ken:

Slava, pfff, no idea! If I get a minute I might look into it. You might want to ask one of the guys at (see useful links section above these comments) To be honest, I'm not sure I understand exactly what you're trying to do.

;o) Cor

sol - 09.06.05 5:47 pm


I am rearchtitecting my company's site, images were all over the place, I have consolidated them to one image folder, but want to make sure any all references to the files are redirected to this location.

is it possible to say write a condition or rewrite that when any call to any .gif, .jpg, .swf, .png file it redirects to this folder and same file name?


cor - 10.06.05 5:47 am

Well sol, something like this..
rewritecond %{REQUEST_URI} ^.*\.(gif|jpg|png|swf)$ [NC]
RewriteCond %{REQUEST_URI} !^/?img/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*)\.(.*)$$2.$3 [L]
would do the job. Any requests for images that don't exist will be redirected to an image of the same name inside a folder named "img" in the root of the site. TADA!

There's some superfluous digits their, I'm sure, and it won't catch old links to images in the root of your site (who keeps images in the root of their site?) but will otherwise work fine, and won't send your server into a spin-cycle, either. Test locally first, of course.

Note, the file existence check is the last of the the rewritecond lines, so only files which have been matched by the first two rewritecond rules will have this check performed. This will aid server performance if you're dealing with lots of queries.

If you were feeling kinky, you could write it like this..
rewritecond %{REQUEST_URI} !^/?img/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*\.(jpg|gif|png|swf))$ /img/$2 [L]
which is niftier (those nested brackets are soo sexy!), but still doesn't deal with old bad links to images in your root folder. Surely no one has those! smiley for :blank:

If you must  have links to images in your root, you could add this..
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*\.(jpg|gif|png|swf))$ /img/$1 [L]
to catch any requests that the previous section didn't match, and the only requests it didn't match were requests for images in the root directory, but really, who on earth keeps images in their root? smiley for :lol:

;o) Cor

ps.. if you are adding this to the main server conf file rather than an .htaccess (you mention "my company's site") remember to use ^/(.*)/ ... instead of ^(.*)/ ... in the RewriteRule line.

George - 12.06.05 1:15 pm

I have a very simple problem which I can't seem to find an answer to. I am trying to redirect from a static directory to non-static content The problem is with Redirect command is that the redirected address always tails with a / making it Is there anyway I can merely remove the trailing / from the redirected address? Thanks.

cor - 12.06.05 2:01 pm

Show us your rules George, use pre tags for best formatting.

;o) Cor

kirk - 19.06.05 3:04 am

About all I can manage to do is hang my site and give myself a big headache. What I'm trying to do is allow links and bookmarks to my site go to a category renamed 'Japanese-Tea-Cups' from 'JTC'.

The old link was:

The new link will be:

So what I need to do is only change from 'JTC' to 'Japanese-Tea-Cups'. It needs to allow links such as where "PROD&Product_Code=TM-171" varies but never has to be rewritten.

Eventually I'll do this for other categories than 'JTC' but I can just redo the conditions and rules for each new set of substitutions, right?

Any help would be appreciated.


natasha - 20.06.05 3:28 am

hi fellows
i m newbie to this,so pls dont mind my following stupid request for help :)
i installed php and apache using PHPtriad, i have a folder for dynamic website that picks all the data from DB, and its location is c:\apache\htdocs\mysite,,,,,,,now i want to use this mod rewrite, for only this site not for others. so how can i implement this only for this site and also where to place my .htaccess file, by the way i searched my all pc i dont have any .htaccess file but i do have httpd.conf..........please help me in this ........
target: to chage (localhost\mysite\index.php?maincat=games&table=gm) like urls to localhost\mysite\whatever.html
please help me guys i will love to hear from you soon

p.s. also tell me when i will upload it what i have to do further smiley for :D thanks

cor - 20.06.05 4:49 am

kirk, I really think you aught to be dealing with this inside merchant.mvc

You don't need a redirection, it's still the same script getting the variables! save yourself a headache and just catch the "Category_Code" variable inside merchant.mvc and convert "JTC" to "Japanese-Tea-Cups".

It's a one line string-replace.

natasha, you can put rewrite rules inside an .htaccess file, inside httpd.conf, or inside <vhosts> directives, and other places.

I don't know enough about how your URL's are generated, though, to advise on particular rules (dynamic domains? how?). Have a read through the comments here, it looks like you just need a simple redirect, but I can't really say.

PHPTriad has been dead for years, it's now Sokkit, no? a "simple" installer for apache/php/mysql. I never liked it, you're usually better off installing the three individually. The apache foundation, in particular, have done an excellent job with their installers.

;o) Cor

kirk - 20.06.05 5:57 am

So, you're saying you can't just replace one part of a URL with a different term using mod_rewrite? Miva is now compiled and I can't modify any of the modules so that's not an option.


Peter - 20.06.05 10:18 pm


Your trips and tricks helped me a lot. I've got one strange thing.
I'm hosting also some multimedia clips and hotlinking prevention works well when someone left click on the hot link. If someone right click and do the save target as option it will start the download without a problem. If they use a downloadmanager they will receive the redirected html. Is there a way to rule that right click and save target thing out?



PS. I could not paste the .htaccess code due to some bbcode mismatch

cor - 22.06.05 5:00 am

kirk, I don't know what Miva is, but any server-side program that doesn't allow you to get inside and change it is Bad News. web programming is best done with an open-source language (like php), so before you get wired into finding a solution to this problem, you might want to consider finding a solution to the real problem! or recompile!

In the meantime, I guess something like this..
RewriteCond %{QUERY_STRING} JTC [nc] 
RewriteCond %{QUERY_STRING} !Japanese-Tea-Cups [nc]
RewriteRule ^(.*)$ $1?%{QUERY_STRING}&Category_Code=Japanese-Tea-Cups [l,nc] 
would do the job, our added variable will over-write the earlier value, but you definitely want to think hard about this closed-source server-side stuff!

Peter, the right-click doesn't pass referer information by the sounds of things. you can either a) disallow requests without referrers (remove that line, though be warned, older browsers might not be able to download your file), or b) tackle this inside the browser with one of the many right-click protection scripts (I DO NOT condone their use, by the way, but you asked)

But if the file exists, and is publicly accessible, there will always be a way round these tactics. If you want real protection, you might want to consider a secure download facility.

;o) Cor

ps.. put code inside pre tags!

Peter - 22.06.05 3:01 pm


The right click protection scripts are not applicable (I hate them also) because the URL(s) hotlinked to my file(s) is on their own server.

I tried to remove the:

RewriteCond %{HTTP_REFERER} !^$

But that redirected all downloads (even my own)


exupery - 22.06.05 4:29 pm


maybe you can help me, I'm pretty newbie...

I've juste set up a htpasswd protected directory on a distant server. But I'd like to have it working on a local server as well (different address for #AuthUserFile in the .htaccess).
What would be the conditional statement to put in the .htaccess ?


alexlop - 23.06.05 9:14 am

i've got a problem

i follow everything you said
everything is fine

but my apache (macos X.3.9) doesn't find the file

<Directory "/Users/alexlop/Sites/">
Options Indexes MultiViews
AllowOverride All
Order allow,deny
Allow from all

then my htaccess

RewriteRule ^folder/(.*) sp_index.php?dir=./$1
RewriteRule ^file/(.*) sp_index.php?file=./$1
RewriteRule ^thumb/(.*) sp_getthumb.php?source=$1

and the error message in the browser

Not Found
The requested URL /Users/alexlop/Sites/gallery/sp_index.php was not found on this server.

(when i put$1 in the whatever.php it works but not transparent whatever.php is in the browser url bar: i want it transparent)

so i hope iit's clear and that someone can help me

alexlop - 23.06.05 9:36 am

to late
i found alone

the answer

RewriteBase /~alexlop/gallery/

cor - 24.06.05 1:51 am

glad we could help alexlop!

exupery, for what? you don't actually say what you want the rule to do! If you want more help, please explain some more.

;o) Cor

Listo - 29.06.05 11:23 pm


I asked this on the previous page and thought I would ask on this section as well. I would like to take the search term from the "referrer" at the time of request or from the web logs then redirect to a particular page relevant to that search term. Is this something you can do??

As before...Thanks in advance!!

cor - 30.06.05 4:52 am

hi Listo! Yeah, this is the page. scroll up to the Hot-Linking section. Those rewritecond lines should set you off in the right direction.

It all depends how complex a redirection you want to perform, you don't say, so it may be possible, maybe not! If you want to just, say, send a word to a search engine, a-la corzooogle.php?q=foobar, then it's easy enough. more details = better replies!

Don't forget to check out the useful links, the apache rewriting guide is an essential read for anyone messing with this stuff.

;o) Cor

sol - 01.07.05 12:16 pm


Your trick up above worked beautifully for me. Thanks! One problem... every now and again we get a rogue process where the redirect redirect indefinitely... (I cant seem to find the file that is triggering it). Is there a way to write one more condition on the rewrite to check if the redirected file exists before redirecting?
rewritecond %{REQUEST_URI} !^/?img/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*\.(jpg|gif|png|swf))$ /img/$2 [L]

Steve - 02.07.05 7:23 pm

I'm switching from Isapi_ReWrite to Mod_ReWrite.
Do you know the Mod_ReWrite equivalent of:
RewriteRule /article-(\d+)\.htm /displayarticle.php\?id=$1 [I,L]

RewriteRule /list-([^.]+)\.htm /listarticles.php\?category=$1 [I,L]

I like your explanations...How about adding a section on rewriting dynamic url's to static ones?

cor - 04.07.05 2:28 am

Sol, I recommend you enable rewrite logging for a day and find out what's really happening before we fix it!* that rule won't loop, even if you have a missing file somewhere.

Steve, those rules look fine, only the explanations are back-to-front, they turn /list-Example.htm into /listarticles.php?category=Example, not the other way around!

As for the sections, I have thought about it, I have loads of wee snippets lying around that some would doubtless find useful, but they'd need double-checked and explained and well, I might do that, but it won't be this month!

;o) Cor


a good trick is to enable the rewrite logging, and then set a search spider on your site. switch the rewrite logging off immediately after the test, or your server will suffer and die

flashGuy - 04.07.05 10:35 am

Hi guys, I would appreciate any help you might have regarding the following question. I have a flash website with two files “index.html” and “index.swf”. The search engine is indexing my index.swf file on its own with out html formatting and messes the look of my site. Is there a way to make .htaccess file that, when someone finds my index.swf file in search engines it will be redirecting people to html page that holds the swf file inside ? Thank you all ahead of time.

cor - 04.07.05 2:00 pm

flashGuy, the htm > php rule above is what you need, with a small modification. simple is best..
RewriteRule ^foo\.swf$ /index.htm [r=301,nc]
The "r=301" part will ensure the search engines permanently update all their links to point to the new location. You'll need to add the usual rewrite-enabling commands before it, of course.

I don't use flash, so I'm presuming the user doesn't need to access the flash file directly (like a php include). But if they do (and the more I think about it, the more this seems likely), you'll probably need to create a RewriteCond line like the hot-linking rules (also above), so it might become..
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?mydomain\.com/ [nc]
RewriteRule ^foo\.swf$ /index.htm [r=301,nc] [nc]
Then it will only be loaded if called from your containing page, but that still wouldn't prevent direct access.

There's a more elaborate solution here.

Personally I'd completely deny access (see deny rules in the main article) to the flash file, keep it outside the webroot (completely), and stream it through php..

= fopen('my.swf', 'rb') {

If a php solution interests you, download a copy of my distro machine for example code. You'll likely need to add some HTTP headers before that to let the browser know what it's getting.

have fun!

;o) Cor

flashGuy - 05.07.05 6:42 pm

Thank you for taking time to help me. I'll try it and let you know how it worked out. However regarding denying an access to .swf file is not an option for me since I do want search engine bots to spider my .swf files.

cor - 06.07.05 12:22 am

The idea is, to the browser, it's just the same as before, php's "streaming" is transparent. (check out the pajamas demo page, all these images are "passed through" php, but arrive in the browser exactly as they exist on the server, as regular images. They could just as easily be movies, or whatever).

Because the only way to see the swf is via the php file (which it could easily remain as "index.htm", or whatever"), you can check stuff before you stream the swf. You could check *anything*, in fact, and you could easily have one group of clients (search engines, whatever) allowed direct access to the swf, and another group that MUST load the containg page first (which could, for instance, initiate a php session, which is like a server-side cookie, a way to "recognise" users, temporarily, I use these a lot).

The swf itelf would have a url something like index.htm?file=my.swf which poses no problem to any search engines, but big problems to anyone who attempts to access the file without proper authority!

You could even go an extra step and have users enter some keyword to "unlock" the swf, though that's probably going to far!

If you decide to stick with .htaccess, remember, you can allow referrers, too (you allow your own domain, don't you!) so a line for google underneath the one for your own domain might be an good idea.

;o) Cor

Xtreme984 - 08.07.05 11:07 pm

well, I got a phpBB board, and got a sweet dynamic signature mod.
however phpBB doesn't allow php extensions to be used as images or whatever.

I need the url to look like: http://domain/phpBB2/signature-$id.png
(where $id is the user identification number specified in the database)
while it's really http://domain/phpBB2/signature.php?id=$id

and I don't understand any of this. (main language being Dutch)

cor - 09.07.05 9:38 am

Your English seems fine to me.

Show me what you've got so far, and I'll see if I can spot where it's going wrong.

;o) Cor

Xtreme984 - 09.07.05 10:25 am

that's the problem, I don't have anything since I don't know where to start. I've been able to make a normal redirect using the .htaccess
but maybe it's because of the fact that I use phpTriad.

I'd think along the lines of

RewriteEngine On
RewriteRule ^signature-(.*).png http://domain/signature.php?id=$1

cor - 09.07.05 12:02 pm

Well, Xtreme984, that's pretty close, try this..
RewriteEngine On
rewriterule ^phpBB2\/signature\-(.+).png$1 [nc]
or something very like it.

Has phpTriad been revamped or something? That's the second time I've heard someone mention it recently and I thought it was long since dead! I usually recommend folk install apache, php, MySQL, etc from their source distributions, or binary distributions if you have no compiler available.

If you're a windows user, you have it real easy these days; all the big web server packages are available in easy-to-use binary installers. There's really no need for phpTraid, easyphp, Sokkit and the like any more. In my (and others) experience these "simple installers" usually end up being more complex and harder to maintain than the "raw" software packages.

;o) Cor

ps.. this is also a valid image link..

Xtreme984 - 09.07.05 12:12 pm

well, I have had the phpTriad package for years now...

and on phpBB2 the php extension is excluded to be used as images for security reasons. if you can set me up with some instructions to set the environment up from the seperate binary distro's I'll do that.
I'll try your rewriterule, thanks.

cor - 09.07.05 12:34 pm

that's what I meant by my "ps". It's an old trick for using generated images on bulletin board (which, of course, do not allow .php extensions) usually we just do something like this..


the "/foo.jpg" is generally disregarded, the image generates just fine, and because it has a ".jpg" extension, phpbb doesn't mind at all. For more details, you might want to check this out.

If phpTriad works well for you, and is up-to-date, then it would probably be counter-productive to go uproot all that for the sake of a "pure" install. But if you're thinking about upgrading anyway, it's definitely worth considering doing exactly that.

Perhaps it's a cop-out, but the documentation that comes with these packages is quite excellent, not that you'll need it much; the apache team in particular have worked hard on their windows distribution, and you probably wouldn't have any troubles installing it.

There's some interesting webserver install fun at the secret comments page (not a secret any more now, is it?) that you might enjoy. In fact, feel free to drop webserver-related questions right there!

Whatever you do, make a complete backup of all your sites and apache installation and especially the configuration files and databases before you begin!

for now..

;o) Cor

Xtreme984 - 09.07.05 12:39 pm

I don't need any backups or whatever, I'm just still using the webserver set-up as a thing to do my web development testing, however I'm considering to host my own website on my machine at some time (for my game development etc.)

cor - 10.07.05 10:03 am

it doesn't matter how trivial your current usage is, your setup works, and any working setup should be backed up! You may need to revert to it, especially if you go experimenting. Everyone needs a back-up, preferably scripted and nightly!

Sadly, most folk only learn of the importance of back-up after they've lost their valuable data. typing even one config line twice is Bad. Losing creative work is like DEATH. nuff said.

As for installing the "raw" server packages, really the best way to do it is just do it! Head along to the respective sites,,,, etc, and grab their latest Windows binary installers (I'm presuming you are a windows user). The installers are very good, and they will guide you through the process.

After that it's just tweak, test, tweak, test, and so on, like the rest of us!

Good luck!

;o) Cor

Xtreme984 - 10.07.05 3:07 pm

ok, thanks for all the comments back, I'm now in the progress of setting up the new apache server. but one question, should I set up php as an apache module or as CGI-module?

Shaun - 10.07.05 5:37 pm

Does anybody know how to turn this ...

... into this ...

I can manage to get it down to something like:


But I haven't yet figured out a way to pass a variable without specifying a document, as you can with normal URL "GET request" format:

cor - 11.07.05 7:02 am

Well Xtreme984, I prefer Apache module.

Shaun, this is another one of those backward things isn't it? surely you mean convert  into

I'll assume you want the ultimate target to be (the biggest challenge!) as in your last example. You could do it like this..
rewriteengine on
rewritecond %{QUERY_STRING} !^.*username.*$ [nc]
RewriteRule ^(.*)$$1 [nc,l]
it's tricky, sure, but it does the job, converting a user-friendly..

server-side, into..

There are probably safer ways, but not if you want the variables bang against the domain like that (which I like, by the way)

have fun!

;o) Cor

Xtreme984 - 14.07.05 6:28 pm

I kinda got problems with setting up the apache...
I can't connect to localhost anymore, if I can connect to localhost neither PHP or MySQL seems to be working.

michael - 18.07.05 6:49 am


Thanks for the excellent page.

I have gone over many, and as good as your is I'm *still* confounded by what seems like it should be an easy task. I'm trying to rewrite the following, which will allow me to do a redirect to an admin tool without having the nasty cgi- url...

/cinesphere/admin /cgi-bin/WebObjects/ActiveMedia

Up to this point I've just put a folder named "admin" in the "cinesphere" folder, and had a simple index.html page which redirects to the ugly url. (I'm not normally called upon to be a web admin, as you can tell...) But since developers consistently fail to update their source with this shortcut folder/page, and I'm sick of recreating it, I'm trying to achieve a simple, elegant (permanent!) solution :)

Interestingly using only /admin (which does not exist) or /cinesphere (which does) as the start point for the rewrite works fine, but /cinsphere/admin...forget it...I have tried every permutation I can think of.

It's probably something stupid that I've missed, but it's driving me bonkers regardless.



cor - 18.07.05 12:12 pm

hmm, on some servers, the path "/admin" is a reserved path, internally linking elsewhere, often an "alias" in the main httpd.conf.

none of the .htaccess rules begin with "/", though they would if they were out in the main httpd.conf file. You probably just omitted to "escape" the slash in the path you are trying to match. Something simple should do the trick, try..
RewriteEngine on
RewriteRule ^cinesphere\/admin\/?$ /cgi-bin/WebObjects/ActiveMedia [r,nc]
remember to put the slash back at the start of the line if you are adding this to your main httpd.conf file.

If that doesn't work, you must have some other thing interfering, in that case come back and we'll try something else.

;o) Cor

michael sanchez - 19.07.05 9:43 am

Hi Cor,

I had actually tried what you suggested, as I think I've tried (as I said) every permutation I can think of, and it didn't work now or then.

Interestingly though, in poking around further, I discovered the following thing: if the folder /cinesphere *does not* exist, then the same redirect syntax works (even without the escapes, actually). As soon as I rename the folder to /cinesphere, it fails.

I am at a total loss...



cor - 19.07.05 12:25 pm

Well, michael, that rule should work whether the folder exists or not, perhaps it has an .htaccess inside it, and this is interfering? Well, something is. If you have access to the httpd.conf (you must, if you are putting forward slashes at the start of the Rewrite rules) then check for aliases/script aliases that could be getting in the way.

Or perhaps you have other rewrite rules being processed before this one?

Or why not just use some made-up link name, like "", and be done with it? I use these sorts of links to point to places all over the site, stuff like /bbtags, /engine, /source, and many others. If something works, use it! using "/admin" sounds like a great idea to me!

;o) Cor

michael sanchez - 20.07.05 7:34 am

cor -

Alas, no. Position makes no difference. No .htaccess anywhere. 2 default Aliases (for /apache/icons/ and apache/htdocs/manual/) and one (default?) ScriptAlias for the cgi-bin.

Using the rewrite that works - /admin - has the drawback of breaking the shortcut for all who have previously bookmarked it as /cinesphere/admin. But it's what I will do for now since I have a whole life to tend to outside of the 6 hours I've poured onto this! :)

I'm pretty sure this is due to some interaction between tomcat and apache. Following this hunch, I created a temporary link to my home folder, and put another folder in there and attempted the same rewrite - and not to my surprise it worked just fine:

^/msanchez/admin/?$ /cgi-bin/WebObjects/ActiveMedia4

Although what that interaction IS?? - I haven't the slightest clue at the moment.

Thanks again for your help.


cor - 20.07.05 5:59 pm

Ahhh well, of Tomcat I have exactly zero experience, so maybe there is some interaction here, yes, seems possible, certainly that rule would work on any regular Apache setup.

I know what you mean about the whole life apart from these things, sometimes the working solution, though inelegant and clunky, is perfectly acceptible because the devoting the time involved in developing a stylish, cute, perfectly-formed alternative is not acceptable.

Some of my old rules are are crazy stuff, but they work! One day, perhaps I come back to them, wiser, and go FIXED! But it's way down the list!

All the best!

;o) Cor

sim - 22.07.05 8:03 pm

Would you please suggest me
How to redirect/rewrite Apache to Tomcat server so that I can capture user name, who has logged in using Apache's .htaccess way of validating users.

tom - 28.07.05 1:32 am

I'm testing a site, where the temp URL loads the site from a sub-folder instead of root-level (eg., "" instead of "")

Problem is, all the absolute links in this (someone else's code) are breaking (where a link to the stylesheet or some forum topic are looking for the files from the root, instead of "root/~user/"

I can't seem to get the syntax right in the .htaccess file, so I can test this sub-foldered site before switching over to the final domain.

Please help!

cor - 28.07.05 3:28 am

Well tom, there's two ways to approach it. The first would be with a rewrite rule, something like the image rules in previous comments, essentially checking if the request contains "~user/", and if not, add it!

Personally, I'd rather create a temporary "virtual domain", and test the site exactly as it will be when it goes live, ie. "in the root". nose about this area of the site for more information on virtual domains.

sim, if this is a Tomcat question, see previous comment! If not, what?

;o) Cor

michael sanchez - 28.07.05 4:35 am

cor -

I seem to have found the problematic "interaction."

First off I googled this excellent page which had the tip-off in it. It has a lot of great information on xml/tomcat/apache/linux:

(comment was under the linked section "achieving complete transparency")

So the problem according to a comment on the above web page is that loading the tomcat module (there are several flavors, in this case mod_jk.c) after loading mod_rewrite will prevent mod_rewrite from rewriting tomcat directories. (exactly my symptom). It seems letting mod_jk load last means it executes first, and since the path I want to rewrite lives under the (apache configured) /tomcat/webapps directory, apache hands the URL off to tomcat before mod_rewrite gets the chance to parse/rewrite the URL.

The tomcat configuration file (which loads mod_jk) in my environments is brought in as an Include in apache/conf/httpd.conf. To fix I took the LoadModule and AddModule directives for mod_rewrite out of the usual LoadModule and AddModule list (in /apache/conf/httpd.conf), and moved them below the tomcat Include:
# Tomcat support
Include /opt/WebWare/Products/tomcat/conf/httpd-jk.conf

# ms - 050722 - mod_rewrite must be loaded after mod_jk (which is loaded in the above tomcat conf file)

# for url rewrites to work on tomcat/webapps/app_name paths
LoadModule rewrite_module     libexec/
AddModule mod_rewrite.c
And la voila my like a charm.

Ahhh...the bliss of winning the battle :)

Thanks again.


cor - 29.07.05 5:56 pm

Great news michael! Reminds me of early messings with WebDAV, how the module load order could completely mess things up, a real "gotcha", and well caught!

Now there's two places on the net folk can find a solution to their tomcat mod_rewrite troubles!

;o) Cor

Tom - 30.07.05 2:59 pm


I'm currently making a redirection script. I have tried lots of different RewriteRule's and read at least 10 tutorials on it, but still can't understand how to do it.

The RewriteRule which has got me the closest to success (500 Internal Server Error) is:

options +followsymlinks
RewriteEngine On
RewriteRule ^(.+)$ /redirect.php?id=$1

What I basically want to happen is when a user types "http://mysite/2gh56" it takes them to "http://mysite/redirect.php?id=2gh56".


cor - 31.07.05 2:01 am

Well Tom, that's a fairly basic rule. Try this variation..
options +followsymlinks
RewriteEngine On
RewriteRule ^(.+)$ redirect.php?id=$1 [l,nc]
If that doesn't work, something else is amiss.

Do you have mod_rewrite enabled on your webserver? And if so, are you allowed to set rules? That rule should work without problem, so if it doesn't work, you'll need to fix elsewhere before you start messing with the rules themselves.

have fun!

;o) Cor

Freaky - 14.08.05 1:03 pm

hi , i need some help with a .htaccess , .htgroup & .htpasswd files i removed , eversince , now when i type in my adress bar it comes up scrambled , but when i type it appears correct , i am fairly new to this , trying to find out what i did and to learn my self.....any help will be appreciated.....

I think it is probably with redirecting......

cor - 14.08.05 4:02 pm

Freaky, trying both of those addresses gets me your hosting admin login. not good. If it's scrambled for you, maybe your browser is old and can't handle the https (secure pages).

Basically you've totally screwed up your hosting settings and you'll need to ask the admin to replace the files you removed, or better yet, replace them yourself from the backup you made before you deleted them.

You backed them up before you deleted them, right?

By the way, I need to know, exactly why did you remove these files?

;o) Cor

Chris - 15.08.05 11:27 am


my website at uses cgi script. I have read through this excellent article and while I understand the ethics of how it all works I can't work out how to solve my problem.

I want to be able to goto page:

but I want the URL to be displayed as something like:

(i am not too bothered about loosing the cart ID as I no longer use it for anything)

I also want to be able to goto web page:

and for the URL to read:-

Hope I have given you enough info to understand what I want, basically it's to make the pages on my site appear to be static rather than dynamic and allow them to be indexed correctly.

Thanks for any help


cor - 17.08.05 4:32 pm

Hi Chris,

Firstly, it's a myth that your pages won't be indexed properly unless they have "real" links. It was maybe true five years ago, but not now, not with any spider that matters.

Another thing, there's no need to put "cgi-bin/" in the user's URL, you can add that in your rewrite rule. Show us your code so far, and I can see where you're going wrong.

;o) Cor

ps.. I don't understand what ethics has to do with mod_rewrite! well, apart from hot-linking rules! smiley for :D

Ant - 18.08.05 10:44 am

Managed to create a .htaccess file as follows:

RewriteEngine On
RewriteRule ^royalinn(.*) http://localhost/Places/subscribers/royalinn/

so that a shortened URL (http://localhost/Places/royalinn) displayed instead (losing the subscribers bit), but now the link to CSS and images is broken and its not displaying properly.

Any advice as to how I can do this without breaking any links.


cor - 19.08.05 11:31 am

Well, Ant, something simple like..
rewriteengine on
RewriteRule ^subscribers/royalinn(/)? /Places/subscribers/royalinn/ [nc]
would do the trick, but I suspect it's probably not the best way forward.

The above rule improves on your example by firstly being portable - it won't just work on localhost, but any host - and secondly, the [nc] part catches "places" as well as "Places" for human-typed links, but it still doesn't fix your images, or does it? I'm guessing you have your images in a local (to the page) subfolder and are using "relative" linking. bummer.

It all depends how your images are linked. I use absolute linking (beginning with a "/", donating the root of the site) pretty much 100% of the time these days because it eliminates a whole bag of potential problems like this. relative linking relies on the browser being given the correct address to play with, and if you are using mod_rewrite to present "pretty" links, the user gets whatever they entered into the browser instead of the "real" address. Looks great, but kills those pesky relatively linked images. broken.

a good image link..
<img src="/Places/subscribers/royalinn/img/image.jpg" alt="seeme" />
which will work regardless of what rewrite rules are in place.

Some folk argue against absolute linking because they say "it makes your pages less portable", but in my reality I have found exactly the opposite to be the case. on any page of mine, the "/Places/subscribers/royalinn/" part of the absolute link would be generated by php, and derived from the precise relative location of the actual page delivering the link.

It's your call. If you stick with relative image linking, you'll have to use a proper redirect, that is, put make the [nc] into [r,nc] and have the "real" location appear in the user's browser, or else get funky with the mod_rewrite rules..
RewriteEngine on 

# requests to /Places/royalinn >> /Places/subscribers/royalinn/ 
RewriteCond %{REQUEST_URI} !(jpe?g|png|css)$ 
RewriteRule ^Places/royalinn(/)?$ /Places/subscribers/royalinn/ [nc]

# broken (relative) image links fixed..
RewriteCond %{REQUEST_URI} (png|jpe?g)$ [nc]
RewriteRule ^Places/royalinn/img/(.*)$  /Places/subscribers/royalinn/img/$1 [nc]
The first part catches requests that aren't images or css files and rewrites them invisibly to the real address. The second part catches only image requests and sorts them out, you do do the same for relatively linked css files too, if you like.

Lastly, if you have more "places", you might want to consider replacing "royalinn" with a regex condition, and using it in the target URL, would save you writing multiple rules when one would do.

for now..

;o) Cor

ps.. the brackets () on the conditional rules are optional, as far as I know, you could probably use square brackets too [], experimentation is usually necessary on any particular setup, just because something works at home doesn't mean it won't bring down the entire server the instant you upload it to your website!

And if that's a shared server, other webmasters might not be too chuffed! smiley for :lol:

West - 22.08.05 7:38 am


First of all great article!! But sadly getting to grips with regular expressions is a major task. At least for me.

My prob is that i want to call my index.php page something else, like other.php. But my host won't change this for me.

So, i need something in my htaccess file so that when a user visits my site with the url it will actually grab my index.php file.

This is so that search engines will have my index page down as other.php but it is actually index.php. Can this be done??

Thanks for any help!!!

cor - 22.08.05 8:57 pm

I 'm not quite sure I understand the question (I often misunderstand htaccess questions, but often that's because, so does the one asking the question, and in my usualy merry way I will try and answer it anyway..)

It's very easy to use a different filename as your index, a simple .htaccess tweak (which really belongs in part one of these articles)..
DirectoryIndex other.php
That's it!

From now on, if someone accesses your site by "". Apache will automatically serve up "" as your index file. No rewrite required!

However, the next two paragraphs of your question seem to contradict this desire, so I'm not sure quite what you want. Feel free to jump back here with more information if I didn't cover your answer already.

Quite why you want to do this, I haven't the foggiest idea. Is this some SEO secret that I don't know about?

;o) Cor

West - 24.08.05 10:27 am

Hi Cor,

Excellent that works great. I have now read all the articles so that should prevent any more obvious questions.

Yes, the reason i wanted to change my index page is to do with SEO but it's no great secret. Certain search engines award a page better page ranking if a search word appears in the actual url of the page as well as in it's content. So if i was selling oranges a url like would work well.

So now i'm giving away trade secrets hopefully you can help me with the final piece in my htaccess puzzle?

Members at my site have their own folder on my server. At present these are created in the root folder. Not good security wise. So i want to ceate my member folders in a directory called "users" off the root. For example "/users/exampleuser".In this directory they would have their own index page.

However i want them to enter a url like "" and be directed to "".

This all seems easy enough looking at your examples, so i used this
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.+)/(.*) users/$2 [nc]

But this raised an error.

Your example of
RewriteRule ^files/(.+)/(.+).zip download.php?section=$1&file=$2 [nc]

worked fine on my server. However i do not know the name of the start directory (in your example files) and my server raises an error 500 if i use

Any ideas would be much appreciated. Many thanks,


cor - 25.08.05 3:41 pm

heh, yeah I know that one, and use it a lot, too. I was thinking too literally, trying to figure out how "other.php" would be of any use to you, SEO-wise. I guess "other" will in fact be some other word. smiley for :ken: with ya. By the way, page title is way more important.

It would be good to know what the .htaccess errors were, more useful, no matter.

In my example ( there *is* no starting directory. "files" is completely fictional, and only appears in the user's URL, nowhere on site. The tricky part to your request is that you don't want users to type anything to signify that they require the /users/ subdirectory, so you'll need to do addditional checks if you want it to work.

I'd probably start with something like this..
rewriteengine on
rewritecond %{REQUEST_FILENAME} !-f [nc]
rewritecond %{REQUEST_FILENAME} !-d [nc]
RewriteRule ^([^/]+)(.*) users/$1$2 [nc]
at least, without knowing what your errors were, I'd start like that. try it.

The first bracketed condition ([^/]+) grabs everything up to the first "/", and uses that as your user folder. Additionally, any requests for files inside the user folder (the super-loose (.*)) will also be redirected, so long as the previous conditions are met, i.e. it's not a real file or directory existing at the location specified in the request. In other words, it won't rewrite requests for your existsing stuff.

It may need some tweaking for your setup, extra conditions, whatever, but that should get you started.

have fun!

;o) Cor

ps. note. you may want to test the performance penalty of using "-d" and -f" in your setup.

West - 26.08.05 1:44 pm

Right well that works great. At least it certainly does the redirection. The only problem is that i want the redirection to take place without the users browser title bar showing the new path. That is, i want

to look in

But for the address bar to still display

I was going to use Alias, but a far as i can tell that is for folders outside of the document root, which does not apply in this case.

What do yo think?

cor - 26.08.05 7:18 pm

I agree, that's why I omitted the "r" from the switches. What I mean is, as it stands, the browser address bar will not change to the real path. Well, it shouldn't.

Did you change the rules, or add other rules after those, or something?

;o) Cor

Leo - 28.08.05 6:48 pm


I was wondering if someone could help or point me in the right direction.

I have a website which shows for profiles. The id=5218 being the specific user profile.

All the id's i.e. 5218 correspond to a username(i.e happyboy) in the database.

What i want to be able to do is that when users go to , the url will automatically forward to without this change showing in the user's address bar.

Any ideas how i go about doing this? Some help will be greatly appreciated.



cor - 29.08.05 4:13 am

Leo, I wouldn't even begin to consider using .htaccess for this, though it would be a fairly trivial matter with php.

Accessing a mySQL database with .htaccess? pfff.. pass!

Use .htaccess only to redirect to a php handler, then the handler can access the db, provide the correct page, etc.

have fun!

;o) Cor

Leo - 30.08.05 6:07 pm

Thanks, i will look into changing stuff with the PHP instead then and see if i have much luck that way. And then use .htaccess to redirect.

Mufasa - 30.08.05 8:50 pm

Thanks for putting up this web page! I had never used mod_rewrite before and your examples made it very easy to understand.

cor - 31.08.05 7:30 am

Leo, there is no such thing as luck. Don't forget the [qsa] !

You're welcome Mufasa, I tend to keep lots of notes, and I have to try and make things simple so I can understand them myself a month later, so to go from that, to sharing some of what I've learned in the form of a web page often isn't such a big step.

The real work comes when you add a comment facility!

;o) Cor

Buddy - 02.09.05 1:03 pm

I am slow catching on and will probably figure this one out, but the symbols have me confused. I am trying to write webpages and everytime I put in a url like and I try to test it in (I want all pages passed) it comes back with an error code of the & symbol.
How do I put the url in the page to pass the validator and what would the .htaccess rule be?

cor - 02.09.05 2:00 pm

Hey Buddy, I don't think this is an .htaccess issue, you probably just forgot to html-encode the "&" symbol.

If you want to validate, use "&amp;" (no quotes!) insead.

;o) Cor

arjun - 06.09.05 11:46 am

The best info i have read about .htaccess. Kudos!

Ben - 12.09.05 2:56 am


here is my problem : I have pictures and scripts in subfolders of my website. I don't want people to go and see directly them, so I tried to use htaccess with deny all... but then my website was not able to show my pictures and to use the scripts any longer...
is there any way to protect files in a subfolder without preventing my own website to use them?


cor - 12.09.05 7:58 am

Yes Ben, there are at least two ways..

The first is called "Hotlink Protection". See above.

The second, you carry on with the "deny all", and feed the images through a php pass_thru() function, or similar.

The first is easier, the second is more foolproof (but more work for the server) and really, for images, totally over the top, unless your images are very special.

;o) Cor

cor_fan - 13.09.05 4:08 pm

Hi Cor,

I am new to this rewrite hope you can help.

I have an alias url eg. The actual url is eg.

When I type it goes to successfully. But it does not display on the address bar, it changes to the actual url. I do not want the user to see the address. Is this possible and how?

Many thanks

cor - 14.09.05 7:27 am

Hi cor_fan (interesting nick!), it sounds like you are performing a proper "redirection", with something like [r=301] after the rule (or even just the r), which tells the browser to reload the new location.

Drop the "r" (or "r=number") part and you will get what you want. Supposing your pages are well written (ie. php pages refer to "self" and not spcific URL's, etc), the should stay in the address bar, too.

If you pages aren't written so well, you may have to make other changes. Check your HTML for hard links pointing to, remove them, and it should all work as expected. I use this techniques all over the place, even rely on it..

No "r", see!

;o) Cor

ps.. The old way of doing this sort of thing was to put your whole page inside one big frame, but frames are evil and best avoided for web pages.

cor_fan - 14.09.05 12:15 pm

Thanks for the help above.

I thought I could set it up on the actual site. I'll contact the guy who set it up for me and ask him to do that.

All my php pages include a constant file. This file has a BASE_URI. This const can be set to either '' (relative) or '' (absolute).


Another happy customer.

12_Centuries - 17.09.05 12:02 am

I love this! I'm using it to great effect. EXCEPT... something that seems very basic isn't working well... check this out:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^article/(.+) article.php?id=$1 [nc]
RewriteRule ^bio/(.+) bio.php?id=$1 [nc]
RewriteRule ^query/(.+) query.php?q=$1 [nc]
RewriteRule ^key/(.+) key.php?c=$1 [nc]

It all works great, except for the last line. Apache just stops responding to all requests for a minute or two whenever I try it.

A sample url:

should be turned into

Any ideas why that one won't work, yet the others do?


cor - 17.09.05 7:24 am

there's nothing in the rules that would cause the problem, chances are it's conflicting with some other rewrite rule (perhaps in the main server's httpd.conf or virtual hosts setup) or something else..

The word "key" could be conflicting with any one of a whole host of things, and is generally not a good choice for redirections and similar unless you have complete control of the server, do you?

If so, enable error logging, and rewite logging and find out exactly what the problem is. If there are other rules interfering, making the [nc] into [nc,l] will likely fix it, but only the logs can tell you for sure, I'm just shooting in the dark.

;o) Cor

12_Centuries - 18.09.05 5:33 pm

Cor, thanks so much for the advice. I find this very fascinating. I don't have control over the server, only .htaccess, so I tried changing "key" to "area" and the same thing happened. So I then changed it to "pjb" (my initials) and it still happens. I also tried using [nc,l], but that didn't work either.

Can I enable rewrite logging from .htaccess?

This is a tremendous mystery!

cor - 19.09.05 4:17 pm

There's a keyboard shortcut or something in Firefox I really must track down. Twice now I've hit it (after hitting ctrl-b instead of ctrl-v - paste) and it jumps to a link, and when I go back, POOF! no form data.

That's three really solid posts I've lost this week.


12_Centuries - 20.09.05 4:11 pm

Shoot, I hope that data you lost wasn't a great response to my problem! :-)

cor - 21.09.05 11:38 am

hehhe no worries! I had to shoot out in a hurry, and my post here was the last thing I did (made me late, in fact! hahah), then lost it. lemme think now..

no, you cannot enable rerwrite logging from .htaccess, probably a good idea considering most folk are hosted on shared servers and rewrite logging is a serious drain on resources, but super-useful in situations like this.

It seems to me the sort of thing that someone with a particular experience would look at your post and go "Oh! yeah! that's such-and-such", but I don't have that experience.

I even tried recreating the conditions here to see if I could duplicate the error. no. Very strange indeed.

Have you tried creating a bogus rule after the last rule here? Nothing is too weird when it comes to mod_rewrite, it's possibly a "last rule thing".

I'd definitely try this on a home mirror (where you CAN enable rewite logging) to see if there's some other factor in your site that influences this. If it works fine at home, chances are it's your web hosts' issue, and you can mail them about it!

for now..

;o) Cor

randomarrival - 21.09.05 9:56 pm

Can anyone tell me why this line is not working? Or have any ideas why it wouldnt work?

RewriteRule ^Merchant2/merchant\.mvc\?Screen\=CTGY\&Category_Code\=(.*)$$1.html [nc]

Im trying to get this -

To Go to This -

cor - 22.09.05 1:07 am

Oooh randomarrival! I had to stop and think about this one! smiley for :D

Personally I'd (again) handle this sort of thing with php. But I like a challenge, and this one looks like it requires some real mod_rewrite voodoo, but turns out to be simple enough when you get down to it..
rewritecond %{REQUEST_URI} !-f
rewritecond %{QUERY_STRING} Screen\=CTGY&Category_Code\=(.*)$
rewriterule ^Merchant2/merchant\.mvc$ /%1.html [nc]
The first line prevents looping, always handy, the rewritecond checks the query string (the ?something=something&somethingelse=somethingelse parts of a request) and matches the Category_Code variable in parenthasis so it becomes available to the rewriterule line via "%1". (a second (.*) match would be %2, etc)

It would be easy enough to add your "Screen" variable onto the new url, simple converting the [nc] flag into [nc,qsa] would append the entire original query string onto the new URL and it would therefore be available in the target page via the usual methods.

"/%1.html" could be "", if you prefer, though that's not usually necessary.

By the way, you can't check for query string variables with a rewriterule line - like you can with the regular "path" parts of the query - you need to access those bits via ${QUERY_STRING}.

have fun!

;o) Cor

randomarrival - 22.09.05 3:32 pm

That all seems to make sense - but I appear to be having problems with it still.

Now I get a 404 Error and the address in the browser address does not change.

My main goal is to get the address just to display as the shortened one. Am I completely missing something?

n0ah - 27.09.05 8:51 pm

12_centuries (and of course you cor)

IIRC .htaccess ignores the last line in the file

so do this:

RewriteRule ^key/(.+) key.php?c=$1 [nc,l] <enter> (will create the line that will be ignored)

cor - 27.09.05 9:00 pm

randomarrival, the link that the user clicks, its HTML code, what would you like THAT to be?

;o) Cor

randomarrival - 27.09.05 10:57 pm

The link address would be

I would like the browser to display it as

I do also want to be able to enter the address to display the when it is called. There would actually be no TEST.html file.

cor - 28.09.05 10:40 am

Thanks n0ah, I missed that when I passed through yesterday. Interesting, though I haven't a clue what IIRC is, my "last line thing" was right enough, then? Weird!

I always add an extra linebreak to scripts, etc, (except php scripts) so perhaps I've unwittingly circumvented this myself! Cheers for the heads-up! Now I gotta go find out what IIRC is, (apart from AOLbonics!)

Ahhh! randomarrival, I suspected as much! What you are asking is exactly the opposite of what you were actually attempting to implement in the first place. I did wonder why you wanted the long URL's! But mine is not to reason why..

okay, what you want is dead simple, something like..
rewriterule ^(.+)\.html /Merchant2/merchant.mvc?Screen=CTGY&Category_Code=$1 [nc]
would do the job. The short address will appear in the address bar. make [nc] into [r,nc] if you want the long address displayed instead.

have fun!

;o) Cor

randomarrival - 28.09.05 3:10 pm

That works! Thanks - I guess I was just trying it backwards to start off with and that had me all screwed up.

cor - 29.09.05 12:06 pm

yup, it's quite common for folk to drop comments here along the lines of "I need to convert so-and-so into so-and-so", when in fact, they mean exactly the opposite, whereas you took it to the next level by actually providing an example! Good work! smiley for :lol:

It works now, that's always the main thing.

;o) Cor

Ketlan - 29.09.05 10:08 pm

Excellent (and interesting) stuff. I've never even looked at htaccess possibilities before.

Here's a possibly tricky problem for you. I run several pages, blogs and so on from my own machine, access to them being http://IP/whatever...
I used to run a 3000 member forum but gave that up last year - but I notice that my access log file gets enormous over just a week or so, full of attempts to access the non-existent forum. I've tried using a simple redirect page and I've tried to simply block access so everyone who attempts it just gets a 404. Both of these work but my access log still gets massive because it's recording every attempt to get the damned forum. Apart from anything else, it's making it very difficult to keep tabs on when my other pages are being accessed.
Have you any idea how (or if) I could use htaccess to either stop recording these attempts to access a dead page or to deny the access without any record at all going into the log?

Any help would be appreciated. I've lost a few billion brain cells since I started trying to work this one out. smiley for :eek:

cor - 29.09.05 11:07 pm

Try this in your httpd.conf (or vhost block, perhaps you keep those in a separate file - wise) ..
SetEnvIf Request_URI "^/oldfolder(.*)$" dontlog
CustomLog logs/access_log common env=!dontlog

RewriteEngine on
RewriteRule /oldfolder(.*)    -    [F]
It's fairly self-explanatory, all requests to the old forum set an environment variable which we check against when deciding whether or not to log the request. If it's *not* set, we log, as usual.

Then we kick in with the mod_rewrite to stop all those requests dead in their tracks. (the "F" flag means "F* OFF!") The user gets the plain server generated 403 message. Forbidden. Without this, they'd get redirected to your regular error page which would - you guessed it - leave a log entry.

Simply replace "oldfolder" with the name of the old folder where the forum was. Restart apache and Bob's yer Uncle!

Hopefully that should save a few braincells.

;o) Cor

Ketlan - 30.09.05 9:58 am

Hi again, and thak you for the speedy and helpful reply.

I placed your section in that part of the httpd.conf file immediately after the access.log set up. I left it all night so I could get a sensible idea of whether it worked or not. Sadly, it didn't seem to - though that may just be a problem with where it appeared in the conf file. I'll read the notes in the file (that'll make a change) and see if I can find a more logical location.

One question about the code snippet you provided. In the first line, there is
Given that the forum was accessed by http://IP/forum/index.php, then all other pages followed the form http://IP/forum/section/threadID... and so on, should that line be something like
I find the logic of all this stuff fascinating but I'm starting to think I'm too old for all this thinking.

Oh, one tiny little trick that might save some stress for any stray readers who have been irritated by having to close Apache down just to delete enormous access and error logs then restart it (when the log files are recreated fresh), is just to Open the files in situ, Select All/Delete, then Save, overwriting the file in the process. Instant empty log file without a restart.
I did say it was a tiny trick. smiley for :D

Ketlan - 30.09.05 12:18 pm

Whoops. That SO didn't work. smiley for :lol: That'll teach me to try to be clever. smiley for :roll:

cor - 30.09.05 4:18 pm

Heh, yeah, deleting the contents of a live log file can have *mixed* results, on some setups, with certain processes it does work. But often it will prevent any logging until you restart the process.

If you run windows (and don't have access to tail, etc) I recommend BearTail.

As for your rules, that certainly *should* work. Yes, replace both occurences of "oldfolder" with "forum". And then restart Apache. You must restart apache to get httpd.conf changes to take effect. (a "graceful" restart is fine)

It's preferable to put this in a vhost block, in fact using virtual hosts if almost always preferable in the first place. If you are placing directly into the httpd.conf (*ouch*) it's a little trickier. First ensure you are placing the rewrite rules inside a valid <Location> or <Directory> block, perhaps something like this in the main block..
<Directory />
    Options FollowSymLinks
    # etc, etc, the usual stuff
    rewriteEngine on
    rewriterule ^(.*)forum(.*)$    -    [F]
and ensure a) any existsing customlog directive is commented out, the one that probably reads something like..

CustomLog /usr/local/apache/logs/access_log common

(put your two new custom log lines after that section) and, b) that you don't have a real 403 page for that part of your site (perhaps specified in .htaccess) or else they will get redirected to it, and of course that gets logged!

Virtual hosts makes this (along with lots of other stuff) a great deal easier. Generally, I don't touch my httpd.conf after the initial setup-and-tweak, keeping my virtual hosts in a separate file. Load all the comments for more information about this, and browse around the /serv/ part of the site for details.

There's enough information there to get things working and if you persevere you'll get things exactly the way you want. But don't let that stop you getting back here if you get stuck!

have fun!

;o) Cor

ps.. if you find the logic fascinating, you should check out the mod_rewrite guide (first link in useful links section) - mind-bending stuff!

Ketlan - 30.09.05 5:09 pm

That's great, thanks. I shall have a play around with that later this evening. I can see there's a LOT to learn about this stuff (and I thought I knew everything). smiley for :roll:
Thanks for your help thus far. It's very much appreciated. I'll be back soon - either screaming for help or (preferably) cheering. smiley for :D

DAV - 05.10.05 7:16 am

Thank you cor for helping me out
I have 1more query:
suppose my link shows
I want to convert it to dynamically.
I've tried alot but no success. some of your code works but i want to convert it dynamically.

Plz help

cor - 07.10.05 4:11 pm

DAV, check my reply to randomarrival, a few comments back, same story.

;o) Cor

ps.. all my code works. often it's clunky, inelegant, dumb, fat and plain old stupid, but it always works! smiley for :ken:

Manuel - 07.10.05 10:12 pm

thanx for all expleining

desperewrite - 08.10.05 6:06 pm

hi, good page and lots of hints! However, got a tricky htaccess issue and can't get my head round it - I read all the above but still no luck. Is it ok to post it here?

cor - 08.10.05 7:04 pm

sure, so long as we didn't just do exactly the same thing!

;o) Cor

desperewrite - 08.10.05 7:25 pm

Ok, thanks for that. What I am trying to do is point my domain to a subfolder off my root in my webspace. I have set up subfolders with the name of the domain (but I don't think thank matters), e.g. has a subfolder in my web space called I then set up a subfolder In there, I placed a default document so that it can be accessed without a long url. Now, when I try to access through a browser, it all works great. However, when trying through a browser, I get in the URL. While the script works, it will cause issues later on with my project. I tried which works fine, so I think it's something with the default document, but I am at a loss what to do.

My htaccess file is as follows

RewriteEngine On
Options +FollowSymlinks
RewriteBase /
RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !
RewriteRule ^(.*)$$1 [L]

Any ideas what's wrong? Very much appreciate your help as it drives me round the bend...

Makc - 09.10.05 12:42 pm

Hello Cor,

Thank you for the article.

I've found an explanation and a solution for my trouble from your hint:
rewritecond %{REQUEST_URI} !-f
rewritecond %{QUERY_STRING} Screen\=CTGY&Category_Code\=(.*)$
rewriterule ^Merchant2/merchant\.mvc$ /%1.html [nc]

and i has adopted this code to my needs:
RewriteEngine on
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{QUERY_STRING} id\=reboo(.*)
RewriteRule ^index\.html err.html [nc]

Now all requests which contains string 'id=reboo' redirects to err.html
Spamadvertising is really s%cks :(

Thanks again and keep up the good work! :)

desperewrite - 09.10.05 10:58 pm


Futher to my earlier posting, I also tried which is the default document which also works without funny URL. So, it's something that's happening when accessing a folder that has got the default document but the default document is not in the URL, if this makes sense?

cor - 10.10.05 9:14 am

desperewrite, I suspect you are going about this the long way. The double was just to throw me, right? Really it could be for simplicity, yeah?

My first thought was "yup, that would work", and it should, does. I even tested it to be sure (though without the rewritebase rule). But still, isn't this complete insanity???

If I understand correctly, you are trying to host multiple domains on one server. There are better ways to achieve this, virtual hosts for starters. Do you have access to the main httpd.conf file?

If you don't, doesn't your web hosting appliance (CPanel or whatever) allow you to setup domains on the system without resorting to .htaccess tweaks? If not, are you seriously considering setting up multiple domains on a host with such lousy software?

Feel free to send more enlightenment this way if I'm missing something, but I just get the feeling that something else is wrong, something apart from htaccess.

;o) Cor

ps.. Makc, check out my bbcode parser - the new beta will be packaged and available real soon - dedicated to giving the buggers a hard time! smiley for :D

desperewrite - 10.10.05 9:33 am

Cor, sorry if I threw you - the double in the domain is a bit confusing, the rewriting that could happen could be in the format of where domain is the domain I want to access and subfolder the folder in which the code for this domain resides, so another domain would be in mysubfolder2 etc, for example. I don't have access to the main config file, yes, that would be easier. Nope, control panel does not give me anything either. I do want to host multiple domains on one shared space, yes. Yes, I realise there are other hosts that offer different options but this one is free, and there are other reasons why I would like to use them. So, if at all possible, I'd like to get the rule to work. Any suggestions?


boris - 15.10.05 3:47 pm

can you help with?


to rewrite to


cor - 17.10.05 7:46 pm

Nah boris, you don't need help, it's too easy! And there are at least three examples of exactly what you want on this very page.

Ahh, desperewrite, another comment from the upgrade day, I had a feeling there's was another I missed. The first question is, if you don't have access to the main config, and you don't have a domain facility in your hosting panel, how will you get the requests to resove to the box in the first place?

Technically, your rules work. You could even go further and plant .htaccess file into the folders themselves, redirecting everything to the alternative domain; but unless you have a valid DNS setup, no amount of rewriting will get those domains served up.

;o) Cor

ps.. I know a host that can do it all, sub-domains, parked-domains, offers shell access, stats, FTP, pop, smtp, cPanel, the works, $25/year. Interested?

Eelke - 20.10.05 2:32 pm

Cor, still wondering about IIRC? It means, "if I recall correctly" and is pretty commonly used. Thanks for an excellent write-up, I plan to put it to some use one of these days.

cor - 20.10.05 5:19 pm

hahah! yes, of course! I guess my aolbionics is slipping these days, it's generally frowned upon in the chatrooms I visit (apart from my own), which is a bit sad (and snooty) really, because it's a gr8 time saver!

Thanks Eelke, worry not, although the average lifespan of an internet page may be 100 days, this will still be here when you get around to the tweaking!

for now..

;o) Cor

desperewrite - 28.10.05 6:47 pm


I have got a DNS panel all right, so domains work for the host. Yes, would be interested in hearing about the host you are mentioning...


shanX - 28.10.05 7:27 pm

Hi Corr!
Please help me with this problem.
I want to change the path of a file,
-from: http://domain/dir1/dir2/dirX/#1.file
-to: http://domain/dir1_dir2_#1.file.

I tried directive below, But it didn't work.
RewriteRule ^(.+)/(.+)/dirX/(.+).file $1_$2_$3.file

I think there's a little bug in it. Can u help me.

cor - 29.10.05 6:52 am

shanX, although theoretically, your not escaping the slashes and dots would appear to break this, in reality mod_rewrite wouldn't care much (a dot is  a character) and it would still work. Your problem is more likely the "#" character; don't use that in filenames, it's a page id reference, and belongs after the URL.

for now..

;o) Cor

ps.. Didn't Firefox used to remember your form text areas? I just went to a page, hit "back", and lost this post (I had to do it TWICE!). Weird.

shanX - 29.10.05 2:24 pm

Thanks for earlier reply!
Actually I've used the '#' character as a reference to a part of the filename, for an example I'm gonna use this mod_rewrite on a directory containing a file list such as given below.

So that it'd result to be

I tried using rewrites below as you suggested, but they didn't work.
RewriteRule ^(.+)/(.+)/thumbs/(.+)\.file $1_$2_$3\.file[nc]
RewriteRule ^(.+)\/(.+)\/thumbs\/(.+)\.jpg $1_$2_$3\.jpg [nc]
RewriteRule ^\/(.+)\/(.+)\/thumbs\/(.+)\.jpg $1_$2_$3\.jpg [nc]

Similar directives such as Hotlink preventions used in other directories are working.
Thanks Again!

cor - 29.10.05 5:29 pm

They are all pretty close, probably workable, too. This will definitley work..
RewriteRule ^(.+)\/(.+)\/thumbs\/(.+)\.jpg $1_$2_$3.jpg [nc]
and if it doesn't, something else must be wrong with your setup. (by the way, you don't need to escape the targets, only the regexp conditions)

The "-pics", I guess, is another one of your "references to something", but if by some chance you are actually referring to a real folder called "-pics", and these commands are going in an .htaccess file inside that folder, clearly the rule would instead need to be..
RewriteRule ^(.+)\/(.+)\/thumbs\/(.+)\.jpg /-pics/$1_$2_$3.jpg [nc]

If you still have troubles, please post the exact full paths of the URL's and targets you are using, saves me guessing.

;o) Cor

shanX - 29.10.05 7:05 pm

Thanks for response, It's true without exact paths It leads us to confusions.

* Actual path : http://domain/pics/Jaguar/XK/thumbs/1.jpg
* Path expected: http://domain/pics/Jaguar_XK_1.jpg
* Variables to be tracked here are 'Jaguar','XK','1'
* .htaccess file resides in the 'pics' folder

I tried
RewriteRule ^(.+)\/(.+)\/thumbs\/(.+)\.jpg $1_$2_$3.jpg [nc]
but It throws up 404's, for either requests, actual and expected.

cor - 30.10.05 12:13 pm

I need to think about this. Not your rewrite rule, that's dead easy. But about why everyone, I mean, almost to a man, asks rewrite rule questions back-to-front! Like others, you even provide examples of your back-to-front rules, which I look at, and go, "yup, nothing wrong with that". smiley for :lol:

I've gotten so much feedback about how good this article is that I started to believe it all! smiley for :roll: I'll need to work on making this all real clear on the page. I'll sketch some updated copy for the main article methinks, right now, while I'm here. If you don't skip this, you'll understand things and be better able to cook up whatever rules you need in the future..

A Rewrite Rule is composed of two distinct parts. The "match" (the first part) and the "target" (second part). Optionally you can add a third section, rewrite flags, inside [square brackets].

rewriterule     Public URL     Private URL      [options]
rewriterule     something      somethingelse    [[whatever]]

The transformation happens left-to-right, which is exactly how the rewrite rule is itself written.

The first part is what mod_rewrite will try to match against. This is the real URL the browser is sending to the server. That's the URL that travels over the wires of the internet. That's the URL that appears in pages, links, perhaps generated by php, whatever, that's the URL the world sees. That's what mod_rewrite will be looking at when it tries to make a match.

IF and only IF it matches, mod_rewrite proceeds with the rewriting, transforming the original matched URL to the new "target" path, usually an internal URL, the real location from which the web server (Apache) will grab the file to serve to the client.

Now, shanX, armed with this information, and looking front-to-back this time around, can you see how easy your rewrite rule is? The browser will be asking for http://domain/pics/Jaguar_XK_1.jpg, so that is the first part..
rewriterule http://domain/pics/Jaguar_XK_1.jpg *something* [yup]
The real path, the target, where the file actually lives (the second part) is http://domain/pics/Jaguar/XK/thumbs/1.jpg
so our rule becomes..
rewriterule http://domain/pics/Jaguar_XK_1.jpg    http://domain/pics/Jaguar/XK/thumbs/1.jpg [better]
Now we simply replace the variable parts with some regexp conditions, mindful that we are already inside the "pics" folder..
rewriterule ^(.+)_(.+)_(.+)\.jpg    /pics/$1/$2/thumbs/$3.jpg [nc]
and we're done! No really, it's as simple as that.

Like they say, it's easy when you know how.

;o) Cor

p - 08.11.05 3:30 am
Hey cor!
I'm having 2 problems...
1) I have a mod rewrite rule as follows...
 RewriteRule ^Download-Polyphonic-(.+)-(.+)\.html$ downloads.php?id=$1&name=$2 
this works perfectly fine...except when $2 (which is song name) involves a colon eg.. downloads.php?id=2&name=12:09 doesnt work instead I get download-polyphonic-2-12:09.html the root folder is not included >.<

2) How can I get rid of those annoying %20 that replace spaces in the song name, can i create a rule to write them into underscores?


Fluxid - 08.11.05 3:30 am

I'm new to .htaccess files, so i can't find any solution to my problem.

I want to rewrite this:
to this:

I wrote this in .htaccess:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^u/([A-Za-z0-9_\-]+)$ _index.php?s=user&user=$1 [NC]

and i've put it to root

but it's not working. when i try to get to /u/AbcUser server returns 404
here's line from log:
[Mon Nov 07 19:33:04 2005] [error] [client] File does not exist: D:/Server/Apache Group/Apache2/htdocs/u/AbcUser

as you can see i'm using Apache on my local computer to tests. Everything is working fine, but not rewrite.

httpd.conf is okay...

can you help me?

PS: also i like to add SessionID links when it's needed, so i also like to rewrite
when sid exists...

PS2: Sorry for my language mistakes

PS3: I've edited this post 4 times, it's too late for me... in my country it's 03:40 am...

shanX - 08.11.05 5:37 pm

Thanks for the explanation!

Judith Archer - 13.11.05 4:22 am

Good work, nice webpaqe.

cor - 24.11.05 1:52 pm

This page is Jinxed! Fortunately, I've taken to copying my posts into my scraps file as I work. I had to scroll for this..

Firstly, you can't have colons in filenames. period. But that won't stop the rule from working. The colon is part of the "name" variable, and will pass straight through to downloads.php, no problem at all. That rule is perfectly fine.

If you haven't sussed it yet, please show me exactly what URL (that is visible, external, yadda yadda) URL, the one that is seen and clicked. And exactly what you expect at the other end, along with actual error text you receive. Are you sure it's not your downloads.php that's giving the error, perhaps you are trying to pass this colon to the filesystem, which of course, won't work; you can't have colons in filenames.

And the spaces, well, %20 doesn't replace the space, that *IS* the space! You can't send a raw space in a URL, it needs to be encoded, which is what the %20 is. If the %20 is causing troubles for your downloads.php script, then that's a php issue, and a trivial one.

At the end of the day, it sounds like the back-end php needs some work, perhaps redesign. All this text processing should be done with php, not mod_rewrite, also a place to check for nefarious requests. And what's "polyphonic"? it seems erroneous, makes the URL so big the unmod_redirected version is neater!

By the way, it was your < and > that prevented you from posting. They need to be like [<][>].

have fun!

;o) Cor

That was for "Person X", who's name got sucked into the htaccess vortex that swirls under this page.

Fluxid, your rules are fine, technically. It looks like the trouble is deeper. Do simple rewrite rules work? By the way, the sid= part can be easily handled with a RewriteCond line.

for now..

;o) Cor

Wytze - 27.11.05 1:46 pm

Thanx for the article Cor,

I've been trying to get a .htaccess file to do a very simple redirect. But when the redirect occurs the url in the addressbar changes to the new (redirected) url.

I've been using this code

RewriteEngine On
RewriteRule ^$

Adding a [P] makes the url fail, adding [R] doesn't make any difference. I can't figure out what I am doing wrong. Can anybody help me ?

cor - 29.11.05 2:36 am

Wytze, I suspect the rule itself is the problem. It's wacked!

You'll need to a) specify *something* to rewite, "^$" isn't valid, afaik, and b) do some rewrite condition to prevent the thing going into a spin-cycle (loop). Then your [r] will work, though better with [r=301], if it's a permanent redirection..
RewriteCond %{REQUEST_URI} !report.php
RewriteRule ^.*$ http://itest/report.php [r=301]
or something like that.

;o) Cor

HJ - 29.11.05 3:11 pm

Hi everybody,

I've got a little problem with the encoding of the QUERY_STRING. This line causes the error:

RewriteRule ^prod\.html(.*)$ "{QUERY_STRING}"

There are a lot of variables I've already encoded, such like this:


Now, when I enter prod.html?N%3DFz%26U3%3D3128%26U4%3D335%26U7 get back a site like this:

So ModRewrite has encoded it a second time.

How can I prevent this?

cor - 30.11.05 2:41 am

Have you tried [qsa] ?

;o) Cor

ps.. see also [ne]

Christopher - 30.11.05 3:45 am

My website is down, i can not login to my control panel. The problem is i can not buy it again because it stil appear like a domain name regitred. Can i make a redirection of first site to another site? For example i want to redirect to ? So if i will try to open the first link, the internet browser to redirect me to my new link?



cor - 30.11.05 3:53 am

Christopher, to setup a redirection from the old domain, you need to access your registrar's admin page and redirect it from there (for instance, your GoDaddy admin page, if you use GoDaddy).

Normally you can setup simple web redirects, DNS redirects, whatever you need. But you need to have access to the domain setup. You don't need access to your old server, unless the domain name was somehow tied into your old hosting package with that server and they own the domain that you used to use, in which case you are probably screwed.

If the latter is the case, a polite email to their sysadmins might be a nice idea.

for now..

;o) Cor

Henry ! - 02.12.05 6:43 pm

Christopher !! S.O.S. !! Help !

I must do a url rewrite for this:

It is for an affiliate script... the url MUST have those 2 vars. or it won't work.

I've done this so far:

Rewriterule ^(.*)\.htm$ /aff/t.php?a_aid=$1&a_bid=f78ebc0e

But this will work for user michael only !!

And the url should be

(not with .htm, but i took from your examples...)

Any workaround ?

Thanks !!

cor - 03.12.05 2:49 pm

no comment.

;o) Cor

cor - 04.12.05 5:01 am

I had to come back and have another look, really, this isn't a joke, is it? smiley for :eek: I thought you guys were just teaming up for a wee spoof, but the more I read your posts, the more I think you could be two genuine, unconnected peeps with real   issues. It was the "Christopher !! S.O.S. !! Help !" that threw me! smiley for :lol:

HJ, if you're serious, fuxake! why did you html encoded the & symbol? That's nuts! Just asking for trouble. But anyway, you should still get N=Fz&U3=3128&U4=335&U7 out the other end, but instead of being separate variables, it will all be one big empty variable, and you'd have to sort that out in your target script. Something like..
$_GET: Array
  [N=Fz&U3=3128&U4=335&U7] =>
instead of the usual..
$_GET:  Array
  [N]  => Fz
  [U3] => 3128
  [U4] => 335

And what's the quotes around the address? Does that work? Hmm. [qsa] would have a similar effect, because it is also working with these pre-encoded variables (why oh why?!?). If you must encode these variables, you might want to consider converting them to base64 or something, you could send it as ?SomeVar=TiUzREZ6JTI2VTMlM0QzMTI4JTI2VTQlM0QzMzU=, and then decode it at the other end. But, again, what's wrong with using regular variables?

Henry ! Oh Henry ! ...

After reading your post about ten times I think I might have an inkling of what you are trying to do - ten minutes I'll never get back! as they say on the imdb smiley for :lol: - simply, you need to have the affiliate id in the link for this to work. So the user clicks

or something like that. If you can't or won't put the affiliate id in the URL (and really, it's crazy that there are two id's for each account, name and id, why not just one of the two, like just the name? - by the way, I really don't know what an affiliate program is - just that it sounds like something I want to avoid at all costs - so perhaps this is a normal practice for those, whatever they are, but it's still crazy)

The alternative is to store a database of mappings, which would be accessible to a php handler script, it would have something like..

michael = f78ebc0e
spunky = f78eb13b
whipit = etc..

in it. The /micheal request would be intercepted - with mod_rewrite..

Rewriterule ^(.*)$ /handler.php?user=$1

and redirected to the php handler, which redirects the browser on to the full, crazy URL.

Download the source for my 404 page (hit any bogus link at to get to it, or go directly to the /engine) which does some cute redirecting, and will provide you with a fairly clear example of how to redirect your own mapped links.

404 keeps its own mappings (simply old link > new link type affair) inside itself, because there aren't that many, but if you are dealing with dozens or even hundreds of links, you'll definitely want a separate database (just a plain text file) for these. That, or put the ugly ID in the URL!

/me googles affiliate program.

Yup, just as I thought, totally the Wrong Thing for, but, well, each to their own, eh!

;o) Cor

sam - 05.12.05 8:32 pm


Is there a way in Apache to parse the text in the files, and find all urls, or perhaps once a url is clicked, be able to access it.

We need to find and replace all the external urls on our server.

Thank you.

daveberk - 08.12.05 9:29 am

I have several subdomains but sometimes people add a "www." to the start like:


I am trying to write a htaccess redirect to eliminate the "www"

I am trying this:
RewriteCond %{REQUEST_FILENAME} ^www\.(.+)\.whyagel\.com$
RewriteRule ^(.*) http://$ [NC,L]
I also tried:
RewriteRule ^www\.(.+)\.whyagel\.com$ http://$ [NC,L]
but it doesn't seem to be working.

Any ideas?


cor - 08.12.05 9:31 am

daveberk, I moved you comment from the other page.

In answer, I use this..
rewriteengine on
rewritecond %{http_host} !^$
rewritecond %{http_host} !^
rewritecond %{http_host} ^www\.corz\.org [nc]
rewriterule ^(.*)$$1 [r=301]
and it works great.

sam, you'd be better off with a grep in the shell. If you want help with that, mail me.

;o) Cor

Steve - 08.12.05 5:38 pm

how do i support multiple domains and multiple sites on 1 shared hosting account using htaccess? can this be done?

cor - 09.12.05 9:07 am

It can be done, Steve, but not easily. You'd definitley be better off with a host that supports this sort of functionality out of the box.

If you still want to press ahead, do a wee search at webmasterworld forums, I remember reading a thread there where they explored different methods of achieving this, with varying success.

But really, you need to get a better host!

;o) Cor

gratzo - 09.12.05 7:52 pm

I'm running an Apache server (WAMP) on a windows box, and have some virtual hosts set up on it - trying to figure out why you allways have to type in the "www" before the URL. If you don't, you hit the "root" folder of the server.

The DNS is handled via, and both the "www" and "non-www" domains are pointed to the server.

I'm thinking that there is a command that can either rewrite or redirect (or both) and have it hit the same "virtual" site with or without the "www". I've searched the Apache docs, and all over your site, and google, and can't seem to find this specific topic. smiley for :blank:

Here's what I've tried and it's not working:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mydomain\.com$ [NC]
RewriteRule ^(.*)$$1 [R=301,L]

Wondering if I have it backwards - this is all new to me!

roger - 12.12.05 3:41 am

In reply to Steve's question, I found this code snippet somewhere:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(ww+\.)?parked-domain\.com
RewriteCond %{REQUEST_URI} !/parked-domain/
RewriteRule ^(.*)$ /redirect-folder/$1 [L]
RewriteCond %{HTTP_HOST} ^(ww+\.)?second-parked-domain\.com
RewriteCond %{REQUEST_URI} !/second-parked-domain/
RewriteRule ^(.*)$ /redirect-folder-2/$1 [L] 

But I am trying to do the same thing, but I cannot figure what must be inserted where in the code above. Can anyone out there help me?

I have a primary domain with hosting. But now I have another domain name which I want to host in a sub-folder within the primary domain. But in the code above I am not sure where I have to insert the parked domain name, the sub-folder name and the primary domain name.

cor - 12.12.05 11:48 am

It's almost spelled out..
RewriteCond %{HTTP_HOST} ^(www\.)?parked-domain-NAME\.com
RewriteCond %{REQUEST_URI} !/parked-domain-FOLDER/
RewriteRule ^(.*)$ /redirect-folder-FOLDER/$1 [L]
The first line catches the requests (with or without the "www" part), the second line checks that the request (which may itself be a rewrite) isn't for something in the redirected folder, and lastly, all requests to the parked domain are redirected to the folder.

The confusion lies in the code presuming that the folder name and parked domain name will be identical. It's functionally the same as
RewriteCond %{HTTP_HOST} ^(www\.)?thefoodomain\.org
RewriteCond %{REQUEST_URI} !/foofolder/
RewriteRule ^(.*)$ /foofolder/$1 [L]
But that's not all you need to do. Unless the domain records actually point to that box (at your registrar), and the web host is setup to host this parked domain (at your hosting admin page, or else manually, by the system admins), none of this redirection will work as you expect. Your webserver is the last link in the chain.

I definitely advise seeking a host which can handle this stuff, not just because it's a lot easier to setup, but also because if you rely on this parked host, and anything goes wrong, they will be much more likely to be willing and able to help out.

I'm always amazed by the number of folk who are out there, messing with mod_rewrite and the dns records without having first setup a webserver at home, a place to test-test-test all this stuff out.

If you take webmastering seriously, get a development mirror, and a few domains to play with.

;o) Cor

roger - 13.12.05 1:24 am

Hey, Thanks a lot for your quick reply and advice.

Yes, it seems like now I have to turn to my web host for help. Because although the redirection itself now works fine(i.e. typing my parked-domain gets my hosted-domain page), somehow, the htaccess rules don't seem to kick in and so the redirect to the folder does not happen. wierd... smiley for :eek:

cor - 13.12.05 2:32 am

Possibly your host doesn't even support .htaccess, some don't. A good way to tell is to drop a gibberish .htaccess file in your root folder, if your site still works, you probably don't have .htaccess capabilities.

If .htaccess works normally, putting gibberish in a live .htaccess file will bring up a nice 500 error page. But in your case, it simply sounds like the dns records need to be altered at your host, if they will do that for you.

Remember, grovelling is always a bad idea, except when dealing with sysadmins.

;o) Cor

unDead - 09.01.06 12:42 pm
Need to rewrite incoming requests for .html to generic URI. In the progress of upgrading my website using php templates, but plan to keep index.html files. Thought I hit the jackpot when I came across your mod_rewrite rule for all requests to whatever .htm will be sent to whatever.php. It worked great until I realized that my home page with URL .html had disappeared!smiley for :eek: So that particular code doesn't work for me.

I am now employing generic URIs as far as possible in my website, and right now the server returns the new php file in response to a request for the generic URI, but there is error (page not found) when a request comes for the specific .html URL. This wouldn't be any big deal to fix if there were only a few files affected, but there are hundreds of files on this website with who-knows-how-many bookmarks set to the previous .html URL.

I want a fix that will return the file of that name no matter the content type specified, at least with respect to requests for html, htm, php content types; let the image files be specific URLs for the moment. What I want is this: suppose someone requests name.html, the server will look for name and if there is only name.php, then it will return that file; if there is no name.php but name.html, then it will return name.html. This is because I plan to use index.html in my directories.

I did come across another mod_rewrite rule that looked like it might work, but when I tried to implement it (typed it into my .htaccess file in the root), nothing happened.smiley for :blank: Here's the rule I tried (I substituted .php for the .phtml):

#   backward compatibility ruleset for
#   rewriting document.html to document.phtml
#   when and only when document.phtml exists
#   but no longer document.html
RewriteEngine on
RewriteBase   /~quux/
#   parse out basename, but remember the fact
RewriteRule   ^(.*)\.html$              $1      [C,E=WasHTML:yes]
#   rewrite to document.phtml if exists
RewriteCond   %{REQUEST_FILENAME}.phtml -f
RewriteRule   ^(.*)$ $1.phtml                   [S=1]
#   else reverse the previous basename cutout
RewriteCond   %{ENV:WasHTML}            ^yes$
RewriteRule   ^(.*)$ $1.html

Can you tell me whether this rule will work? Perhaps I did not type it correctly. I removed the comments and typed only:

RewriteEngine on RewriteBase /~quux/ 
RewriteRule ^(.*)\.html if exists 
RewriteCond %{REQUEST_FILENAME}.php -f 
Rewrite Rule ^(.*)$ $1.php 
RewriteCond  %{ENV:WasHTML} ^yes$ 
RewriteRule ^(.*)$ $1.html
(reformatted - ed)

Of course I did also use enable: Options +Multiviews +FollowSymlinks.

Maybe I typed it wrong? (I'm new at this stuff.)

Anyway, I hope you can help me solve this problem. Seems to me it must be a common problem with a commonly known solution, but I just haven't been able to find it out. Thanks in advance.

cor - 10.01.06 12:20 pm

I think you need to get back to basics here, unDead, and delete that mess of code! You struck gold with my original rule, you just need to *tweak* it slightly. The original rule..
Options +FollowSymlinks
 RewriteEngine on
 RewriteRule ^(.*)\.htm $1.php [nc]
is illustration. If you scroll down, you'll see a real example..
Options +FollowSymlinks
 rewriteengine on
 rewriterule ^(.*)\.htm$$1.php [r=301,nc]
can you spot the subtle difference?

In the second example, there's an "$" after the \.htm, which means, rewrite this line ONLY if the filename ends in .htm, whereas in the first example, so long as the extension begins .htm, the rule will work. myfile.htmyipee would trigger the rule, for instance, as of course, would .html files. Add the $ and it will work exactly as it does at, allowing html files to display just fine.

As for the order in which they are served, there's no need to get complicated, Apache has a built-in mechanism for this, which I touched on in part one. I'm assuming by "Generic URI" you mean links without filenames, like, as opposed to What you need is the DirectoryIndex directive, and it looks like this..
DirectoryIndex index.php index.html index.htm
which tells apache to serve up first an index.php if it exists, and if it doesn't, serve up index.html, and if that doesn't exists, index.htm, and so on. you can add more types and re-arrange the order to suit your needs. With these two simple directives you should be able to achieve what you desire.

Easy when you know how. smiley for :geek:

;o) Cor

unDead - 10.01.06 4:24 pm

Thanks, Cor.

I really don't know what I'm doing.smiley for :erm:

Actually I got the "mess of code" to work so that requests for .html files return .php files except when the .html file exists. But this only solves half the problem, because I need to generate a 301 page to alert the search engines and also to allow people to update their bookmarks. As it is with the mess of code, even if the server returns the .php file, the .html URL shows up in the browser address, and also when the page is bookmarked.

My goal: when visitor requests, the server returns the filename.php but the user-agent displays the generic URI, and also alerts my visitor to update his bookmarks. Exception when there is an existing filename.html, then server returns that, but still want to display the generic URI and give alert to update bookmark.

Anyway, I wanted to give your code a shot. But I modified it somewhat, thinking to try to rewrite the .html to non-specified type. So I deleted the mess of code and typed in this:

rewriteengine on
 rewriterule ^(.*)\.html$ $1 [r=301,nc]

I know, I know, it was a dumb thing to do.smiley for :roll: But I had supposed that if I left in the then I would run into problems with my files in so many different directories. Anyway, this is what happened. I keyed this address into my browser:, and I ended up here:

At least there was no .html or .php appended to the file name. But I found myself in the core of the earth when I wanted to be somewhere above sea level.

So then I did something stupid again. I added RewriteBase / to the mix. That was even worse. Couldn't access my web pages at all, got a message something like "redirect unable to execute" and the mention of "cookies" in it (sorry, I didn't copy the error message; just got the hell back into the .htaccess file).

So then I tried this:

RewriteRule ^(.*)\.html$$1 [r=301,nc]

That works just fine for my test filename.html in test directory. I direct the browser to, and the browser displays


when I tried to go to, the browser address showed but there was nothing. Nothing at all. Where did my index.html page go?smiley for :eek:

I do after all want to still keep some .html pages, in particular my index.html files at home and directories and subdirectories.

So why didn't I keep to your rule and just use .htm$ instead of .html$? Because I don't have (and never have had) any links using .htm. What would be the point? I don't follow why this should apply to what I want to accomplish. And why did I drop the .php from your rule? Because I want to upgrade to "cool URIs" and avoid specific content type URLs.

I am bewildered why your modified rule worked nicely for my test directory, but then my home page disappeared. smiley for :blank: I sent the browser to, and when that didn't work, to, but I ended up in a blank page, with the URL displayed in the browser address bar:
Why the page doesn't display even so, I don't know. Then too, I didn't see any 301 notice, no alert of any kind.

So for the time being, I have pasted back the mess of code, hoping to find a better solution.

I'm sure I've missed out something obvious... like Mr. McGoo. Can you point me in the right direction?

cor - 11.01.06 11:33 am


Well, firstly, I think this whole "generic link" thing is a Very Bad Idea. (note Winnie-The-Pooh capitalisation). File extensions are there for many good reasons, and if you rely on content encoding and mime-types to get the page correctly displayed in the user's browser, there are times when this will simply fail. And portable, it is not.

Also, you must have one or the other. Either you send a proper redirect, and have the proper URL appear in the browser, or you don't.

You can't send a 301 and have your "cool" links in the browser address bar. It's either, or. And I don't think is cool at all, it just looks like something's broken, which it clearly is!

By the way, the "point" of redirecting .htm files is so you can include them inside php files. php is code. html is content. A modern web page is a mix of both of these things (and style - css - as well), so while the content (the text of the page) exists in the .htm file, you wouldn't want the user to load that directly, or else they'd miss the headers and whatever else your containing php code usually sends along with it.

There's one thing I always strive for in any work, and that is simplicity. I'd definitely think again about all this. However, if you do decide to continue on down this path, why not try a nasty hack like this..
RewriteEngine On
# only rewrite is file doesn't exist..
RewriteCond %{REQUEST_FILENAME} !-f [nc]
# if it hasn't got a .php extension, add it..
RewriteCond	%{REQUEST_FILENAME} !(.+)\.php$
RewriteRule ^(.+)\.?(.+)?$		$1.php [nc]
# finally, if there is no actual php file there, present its .html equivilent..
RewriteCond %{REQUEST_FILENAME} !-f [nc]
RewriteRule ^(.+)\.(.+)$	$1.html [l]
That's roughly what you're after isn't it?

If someone requests http://mysite/test.html , or http://mysite/test.php and it exists, that's what the user will get in their browser. Now to your "cool" links..

If someone requests http://mysite/test, it is firstly rewritten to "test.php", and if that exists, test.php is presented to the browser. Their address bar still just shows http://mysite/test

If it doesn't exist, the request is rewritten to "test.html", and that is presented to the browser. Again, their address bar remains http://mysite/test. Cool?

This is just off the top of my head, and would need tested and tweaked. I guess you could go further and take extra steps to remove the extensions altogether, but that seems OTT. Your cool links will work, basically checking for file.php, and then file.html in that order and presenting whichever it finds, without altering the address bar in any way. (no [r])

As soon as you send a 301, of course, the address bar will change to the redirected location, I don't think it's possible to send a 301 to your cool link and then work internally from there, as it's something that's physically sent to the browser, ie. last.

At least this will get you started, though really, if I were you (which, as ever means, "if you were me") I wouldn't even go there.

I used Macs for years, and the lack of decent file extension support was a cross-platform nightmare. My opinion: file extensions are cool.

;o) Cor

ps.. note, every "-f" file existence check causes you a performance hit.

pps.. also note, if you start messing with 301 redirects, broken ones can take a long time to change in your browser (so you might go on to fix it, but not realize, because the browser is still pointing itself at the first (broken) 301. Solution: restart your browser, or use another one.

ppps.. (the legal limit for pee-esses) if you have access to the httpd.conf (main apache config) add this to the bottom of it..
RewriteLog "/tmp/rewrite.log"
RewriteLogLevel 5
which will spurt out loads of information for you. 9 is the most info 1, the least. 5 is useful, I find. IMPORTANT: remember to comment out these lines when you finish testing or you will seriously impact your server's performance.

unDead - 13.01.06 12:31 pm

Thanks a lot, Cor. Wish me luck.smiley for :roll:

Mike - 14.01.06 11:40 pm

Quick question... I would like to redirect any requests to* to* .
I tried using this in the /test/.htaccess file:

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^mysite\.com [nc]
rewriterule ^(.*)$$1 [r=301,nc]

This works fine for most urls, e.g.,,, which all redirect to the correct etc url.
However if I request without a trailing slash, i am instead redirected to

Would appreciate any help.
As you can see I am running WAMP.

cor - 15.01.06 12:01 pm

Ahh.. trailing slash problem. Please be aware, I'm still under the influence of last night's poisonous substances, but something like this in your root .htaccess would probably do the trick.
RewriteEngine On
RewriteCond %{http_host} [nc]
RewriteRule ^test$ /test/ [r=301,nc]
RewriteRule ^test/(.+)$$1 [r]
worth a try, anyway! smiley for :ken:

;o) Cor

cor - 15.01.06 12:05 pm

I can already see an easier way to write it. smiley for :roll:

;o) Cor

Mike - 16.01.06 3:00 pm

Thanks for the help, I managed to get it to work using this in the root .htaccess:

Options +FollowSymlinks
RewriteEngine On
RewriteCond %{http_host} ^$ [nc]
RewriteRule ^test(.*)$$1 [r=301,nc]

cor - 16.01.06 3:44 pm

Yup, Mike, once you get up to the root, there are a few ways to achieve the effect.

Good work!

;o) Cor

Joe - 17.01.06 2:47 am

ok, so what do the [L] [R] [NC] and all those statements mean at the end of the line? is there somewhere with a list of them all? i cant find one :(

cor - 17.01.06 10:14 am

See the Useful Links section (above), first link.

;o) Cor

paul - 19.01.06 12:47 am

I have the following situation that I couldn't find an example for in this great page.

We have many subdomains like,,, etc... If a subdomain is hit, I'd like to acheve to pull out a file with the subdomain name as a parameter for a PHP file sitting in the root of the web.

Something like this:

user types in: or
(other filenames except index.html in the subdomains should show 404)
page served:
the browser URL still shows:

Is something like that possible to do?

Thanks a lot for your help,

cor - 19.01.06 9:06 am

Well, Paul, almost anything is possible, but before I dive in with possible real solutions, I'll need to know how things are setup at your server. Good question, by the way, well framed.

Okay, these "subdomains", are they real? I mean, do they exist properly on the DNS, and there's a folder in the root of your main site that is accessed when someone uses one of them?

If they are real subdomains (like those created with CPanel or whatever) then firstly, you'll need to put the rewriting rules IN that subdomain. The main .htaccess file isn't read unless someone accesses the main site.

And if you redirect from a subdomain to the main domain, it's going to be very difficult to keep the address bar from changing, becasue you will be performing an "external" redirect, out of one domain and into another.

If these are subdomains that are created on-the-fly with mod_rewrite, it might make things easier to implement, but also easier to mess up those redirections; if this is the case, show us the code that creates the subdomains. If it's not, consider it; you could take care of the whole thing with mod_rewrite.

If you have access to the DNS and web server setup, perhaps set up a wildcard subdomain system; basically a wildcard A class record for your domain, and tell Apache to send all requests to the main root. Then you could add any old names you need later on by simply using them.

Regardless, the principle goes something like this..
rewritecond %{HTTP_HOST} !^www\. [NC]
rewritecond %{HTTP_HOST} ^([^.]+)\.domain\.org [NC]
rewriterule ^(.*)$ [R,NC,L]
An example only, from a subdomain's .htaccess file, and an "external" rewite, so the user gets the real location in their browser. Just food for thought.

And if you are stuck with fixed subdomains, you might want to consider some php solution. If your index.php inside the subdirectory were some intelligent handler (maybe start by copying sub.php to /sub/index.php) - because it can access all your files the same way the php scripts in your main site can - it could possibly handle the whole thing from the subdomain, which would ensure the user stays inside your chosen subdomain, too.

It all depends on how your site is designed, and how your web server is setup.
More details please!

;o) Cor

Joe - 20.01.06 11:50 am

thanks, i found that link the second i posted this question :(

i have a new question... i used the funky rewrite to change to, however i am having some problems in PHP.

one of the PHP appli's just stops working when i use the www eliminator...
for some reason it doesnt like the redirecting process, and just stops working. To get it to work again, i have to remove the rewritecond from my .htaccess.

Are there many situations where this may occur?
im wondering if its fixable, and if its worth the risk of causing problems for my users just for the sake of a 'prettier url'...

help smiley for :D

UPDATE: i fixed the problem in question, seems i had to remove the www from the admin area's too, so it stopped re-directing... but anyway, i am still wondering about any other Risks involved?

cor - 20.01.06 5:26 pm

Yup, Joe, that was the obvious answer; remove 'www.' from php scripts.

It is usually best to use $_SERVER['HTTP_HOST'] in your php scripts, saves errors, increases portability, etc.

risks: none.

I've *never* used the www part at, but then, I write all my own back-end code, so if you are using some off-the-shelf package, it's certainly worth testing it thoroughly (preferably at your development mirror) before deploying.

But that's true in any case.

;o) Cor

Merlin - 23.01.06 5:33 pm


I've fairly new to the joys of mod_rewrite and have a rewriterule in a htaccess
file that fails for some reason thats not clear to me.

This rewrites a PHP file into a different PHP file.

Options +FollowSymlinks
RewriteEngine on

rewriterule ^(.+)\.php http://localhost/httest/page.php?p=$1 [r=301,nc,qsa,ne,l]

I would expect the translation to be done once and finished with, but it seems the rule is repeatedly reapplied, so the server gets into a loop. I bypassed the problem by doing this.

Options +FollowSymlinks
RewriteEngine on

RewriteCond $1 !^page$ [nc]
rewriterule ^(.+)\.php http://localhost/httest/page.php?p=$1 [r=301,nc,qsa,ne,l]

Taking out the r=301 generates a different symptom "The server encountered an internal error or misconfiguration and was unable to complete your request."

What nugget of info am I missing about this case? Why is the rewriterule being repeatedly reapplied ?

Thanks in advance

BTW: Great site.... :)

Paul - 23.01.06 10:46 pm

I have a parked URL, say
that I want to get redirected to 
so that when a user types
they get taken in the php code to the landing page at where I collect the tracking source and link information. Can you help? I image it is something like the following that I use to redirect my other parked domains, but not exactly.

Options +FollowSymlinks
RewriteEngine on

RewriteCond %{HTTP_HOST} ^$ [OR]
RewriteCond %{HTTP_HOST} ^$
RewriteRule ^(.*)$ [R=301,L]

As of last week I had never even heard of htaccess - this is all very new to me.

cor - 24.01.06 1:31 pm

Merlin, your first rule redirects *every* php file. for instance..

http://localhost/some/deep/page.php would redirect to http://localhost/httest/page.php?p=some/deep/page

Understand, at the end of the first run, when the browser is phyisically redirected to "page.php", the rule has to run again; it's a whole new request. A browser like Firefox will tell you "Redirection limit for this URL exceeded. Unable to load the requested page".

So, adding RewriteCond $1 !^page$ before the rule prevents Apache getting in a loop. Removing the "r=301" shouldn't cause an error. The rule looks fine, and it should work exactly as expected, the only difference being that the user sees the old URL in their browser address bar instead of the new redirected URL. You removed the comma, too, right?

If it's still not working, enable rewrite logging (see the new troubleshooting section up in the main page for more details) and try again! Feel free to drop more information and questions here.

Paul, again, see the troubleshooting tips (above), the section about "Fatal Redirection". There's nothing inherently wrong with your rule, though you might prefer the shorter..
RewriteCond %{HTTP_HOST} ^(www\.)?$ [nc]
RewriteRule ^(.*)$ [R=301,L,NC]
But it's all the same, really.

What puzzles me is where the extra data comes from; the "tracking source and link information", there's nothing in the original request, so I assume this is some arbitrary data you are adding yourself.

Thing is, unless the data is based on something like their IP, or other unique characteristic, won't all requests have the exact same data? And if so, what's the point in tracking it?

Just thinking out loud! You'll have something up your sleeve, no doubt. smiley for :ken:

for now..

;o) Cor

Paul - 24.01.06 4:33 pm

Thanks. The problem was indeed a fatal redirection. The reason I want the tracking information in the redirect is that the domain name will only be used for a single snail mail sales letter and I want to track who uses the domain and thus who responded because of the letter.


Dan - 27.01.06 1:43 pm

I have a problem with a "ErrorDocument 404". Can I get the requested not-found url to the 404-page, so I can save the name of the not-found file?

Will redirect to:


cor - 29.01.06 6:05 am

Sure, Dan, hit any 404 here at the org for a demo of some possibilities.

Essentially you just need to set your error handler to your php page..
ErrorDocument 404 /err/404.php
And that's it. You don't need any special redirection because the ?dont_exists=thisfiledontexists.php is superfluous, that information will be inside $_SERVER['REQUEST_URI'], so you can use it inside you 404 page without any extra effort. When you hit a 404, the request hasn't changed, it's still /the/missing-page.html, or whatever. This is by design.

Download the source for 404 (available from any 404 page), it has instructions, examples, and what-not.

;o) Cor

ps.. I see, Paul. So basically it's just a simple count.

If you used email instead of snail mail, you could tag on some Unique ID to the url,, or whatever, and have some more useful tracking going on.

And if you did that, (I'm just thinking out loud for someone who may read this later) you might be best to handle the tracking information in the original domain. ie. instead of a mod_rewrite redirection you have a php file that grabs the tracking data, stores (and possibly manipulates) it, and then sends a proper http header..
to redirect the user to the real url. With php, there's always more than one way to skin a cat.

yoshi - 29.01.06 11:51 am

I recently changed url using ForceType Directive and old google url index to be redirect to new url.

i get internal server error with lines below, can anyone tell me how to go about.

old url
/detail.php?listing_ id=1

redirect to new url

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^detail\.php?listing_ id=([0-9]+)$ property/guide/$1/ [R=301]



Mindless - 29.01.06 12:01 pm

Hi, i've been looking for a nice redirect script like i've seen on other community sites and your site helped me do this, thanks! but there's one question i'd like to ask.

heres the code i'm using

Options +FollowSymlinks
RewriteEngine On
RewriteRule ^~(.*) /profile.php?username=$1

currently tht code makes the url ( and it keeps that url *it does show the proper page, but I want to know if i can make it SHOW the url of that file also

so that
goes to
AND actually displays the go to url

If you can help me please email me, i have submitted my email

thanks in advance

Dan - 29.01.06 6:58 pm

Very nice article, and very well-written! The part I was looking for is the inheritance, and lo and behold, it's right here!

cor - 29.01.06 9:43 pm

Yeah Dan (another Dan!), inheritance catches out a lot of people, and this solution is far less confusing that mucking around with RewriteBase and what-not, I think. Cheers!

Mindless, simply add [R].

yoshi, you will probably find something like this..
Options +FollowSymlinks
RewriteEngine on
rewritecond %{QUERY_STRING} listing_id\=([0-9]+)$ [nc]
RewriteRule ^detail\.php(.*)  http://itest/property/guide/%1/? [nc,r]
more robust and functional; not to mention, easy to understand and hack. Note the "?" at the end of the substitution string, to prevent the query string being tagged back on.

You could go on to add checks for directory's existence and more, but I'll leave that as a fun exercise for you!

;o) Cor

Jay - 30.01.06 3:30 pm

First off, thank you for the wealth of information you've shared with us. I've been searching the net for a solution to my problem and yours came the closest to touching upon it- however, I'm still having difficulties with getting it to work and was hoping you can help me out.

Basically, I have a PHP/MySQL dynamic site that offers a ton of downloads. Now, these downloads are linked as such: "" where it actually stores download count and redirect the file to be downloaded at the actual location, which would be: ""

Now, I've placed an htaccess file inside my files directory to disable hotlinking for zips- this works perfectly when someone is direct linking to my files via the actual location's URL. It, however, doesn't work when someone direct links using my redirecting URL "". The problem lies in that since it's really a redirection, there's no actual "file_download" directory for me to drop any htaccess preventing hotlinking inside it. So I tried to do something like this:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?*$ [NC]
RewriteRule ^file_download/?.*$ [R,NC]

That didn't work. I also tried to do redirecting to my homepage rather than replace it with my nohotlink image...but that yielded the same results. What happens is that they get directed to "" and the page states an error. For I.E., it states an error but if you just hit the refresh button while on the error page, the file downloads anyway. On Firefox, I noticed that it states an error but gives a "FOUND" notice and produces a link to "" in which when you click on it, the file downloads as well.

I hope I'm not confusing you! All in all, I just really need to be able to successfully disable hotlinking to my files even when they're accessing it through the redirection URL. Any ideas? Any help you can give me would be great. I've been tearing my hair out trying to figure this thing for days now!

cor - 30.01.06 10:01 pm

Jay, my first instinct says "edit the redirection". You say this is a database driven site, so I presume that it's php, and not mod_rewrite, that's doing the redirection. Referrer information is available there, so why not use it there?

If it *is* mod_rewrite doing the redirection, then add rewritecond statements to *that*.

If the first isn't possible (and it sounds like a hack that would be welcomed by the creator of the CMS, or perhaps you might like to suggest it) or the second isn't the case, you could still work on the links afterwards with mod_rewrite. I would have thought something like this would work..
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)? [nc]
RewriteRule ^file_download [r,nc,l]
which looks remarkably similar to what you tried yourself. Why didn't it work? What happened? What errors did you get? etc.

At the end of the day, it's near-impossible to prevent a determined downloader from grabbing your files unless you control access in some way outside mod_rewrite. My own distro machine uses "passthru" to pass the data form the (totally user-inaccessible) folder and feed them to the user's browser. It's either that or else use some sort of authentication mechanism to control access to the files.

With more information about how the downloads are processed, perhaps I could come up with a better solution. If you still need help, get back to me with the errors you are getting from the rewrite rules, above. Perhaps even the name of the CMS, if it's something available.

have fun!

;o) Cor

Dan - 31.01.06 10:38 am


show the error-page filename and NOT the not-found filename.

cor - 31.01.06 3:07 pm

Well, Dan, you (or rather, a mod_rewrite diective set by you, or someone) must have previously done some kind of redirection on the request. That's probably where your trouble lies.

Create a 404 page (whatever you set as the 404 page in your .htaccess) and put only this in it..

= getenv ("REQUEST_URI");
$servname = getenv ("SERVER_NAME");
'<br /><pre>',"I can't find http://$servname$requri</pre>";

If it doesn't show the name of the REQUESTED page, then you'll need to check for rewrite rules that might be catching the requests, or similar.

Keep us posted.

;o) Cor

Greg - 01.02.06 5:46 pm

Great Site. Very helpful.

I would like to redirect:


RewriteRule (.*)/ referral.php?K=$1

It works great when I have the slash at the end, but how do I tell it to look for the end of line instead of the slash?
When I use:
RewriteRule (.*)$ referral.php?K=$1
It passes "referral.php" into K.

Any help would be appreciated.

cor - 01.02.06 6:00 pm

Greg, you are close, something like..
RewriteEngine on
RewriteCond %{REQUEST_URI} !referral\.php
RewriteRule ([^\/]+)/? referral.php?K=$1
would do the trick.

The RewriteCond ensures you don't get in a loop. Note: we specify not "/" in the matched expression (.+) so that regardless of whether someone uses "gregkersh/" or "gregkersh", K will always equal "gregkersh", in other words, without the slash.

If they used "heellyeas/foo/my/bar/baby!", K would equal "heellyeas".

;o) Cor

Greg - 02.02.06 4:08 am

Hot Dog! That worked perfectly.

Thanks a bunch!

help - 03.02.06 3:18 pm

hi i have 5 applications in different folders in my htdocs.I need to redirect all but one of them to a different location.

ex. should remain the same
where as any other should redirect to a diff site say
Please help!!!!

asdf - 03.02.06 11:50 pm

working on mod_rewrite means using ones location bar! quit the crap!

you should be aware that your javascript on this site not only functionally breaks the location bar in firefox 1.5 but also all the buttons up top, not exactly prime time for working on mod_rewrite

cor - 04.02.06 1:16 am

asdf, I don't use Firefox 1.5 normally, because there are no updates for extensions I need, but I'm posting with it right now. Also, I came via Google, so that every ounce of JavaScript could be activated (including the funky highlighting).

Result: everything is 100%, as expected. The location bar is also unaffected.
I knew this, but I had to check.

asdf, maye you need to check your browser settings (or possibly your firewall/AV). Feel free to chuck specific errors, screen captures or code blocks my way, though probably email is best, yeah? This has nothing to do with mod_rewrite.

help, you're just not trying!

I'm not going to create a rule, you can scroll up easily enough for that, but I'll give you the essential clue: you need a rewritecond line that checks for NOT and then rewrites only for that match.

Like I say, scroll up through the comments; it's all there.

;o) Cor

onk68 - 08.02.06 3:41 am

hello all
ok this is the problem that i am having i have a site but i want ot move the entire site down one directory i tried this

RewriteCond %{HTTP_HOST} ^(www\.)?$ [nc]
RewriteRule ^(.*)$ [R=301,L,NC]

but i always get an error that my server has tried to redirect that will never complete i know that it is because i am redirecting to the same url with just a sub folder but i dont know how to make it not do the redirect after the redirect

any help would be greatley apresheated dont laghf i cant spell very good if it ant code it dont make cence

commssioned_rewrite - 08.02.06 12:40 pm

This is a Question:

I have a problem with google sitemaps feature and I am wondering if this is because of the use of apache mod rewrite on my site.

I am not the programmer of the admin - I am the business ownner. I am doing the sEO and basically google wants a HEAD command to to return a 404 instead of a 200. My site returns a 200. Is it related to this?

Sorry if this turns out to be a bozzo type question . . obviously this is not my area of expertise. :)

cor - 08.02.06 10:32 pm

commssioned_rewrite, until now, I knew absolutely nothing about google sitemaps, even what they were, but after some light reading, it looks something like the idea I suggested back in Oct 2004. (combined with my funky robot links page) Nice one Google! smiley for :D

In answer to your question, of course a missing page should produce a 404 error1! That's the whole point! Your problem isn't google sitemaps, as such, but with whatever it is you are doing with 404 errors. What are you doing with them?

When you say "google wants a HEAD command", what do you mean? Google emailed you and asked you for a HEAD command by return? Or you are getting an error somewhere? Where? Exactly. Is it the software that creates your sitemap that's failing?

If you want me to look deeper, you'll need to be more specific, or else just go fix the 404 handler!

onk68, you need to add a condition line, probably one that checks the request does NOT contain the term "Dream/", something like..
rewritecond %{REQUEST_URI} !dream/ [nc]

;o) Cor

If you use Firefox, with the Web Developer extension, go into the information menu and choose "View Response Headers" (the bottomost option) which will tell you what page gives what headers.

And anyone who develops web sites in any way and doesn't use Firefox with the Web Developer extension should probably go and sort themselves out right now!

onk68 - 08.02.06 11:44 pm

thanks man works perfectuly can i use this methad to do more than one site on a singel server i hope so ill play with it and see thanks again

cor - 09.02.06 12:51 am


If your host uses CPanel, (at the time of writing) you have to use the "add-on" domain, then simply redirect your newly aquired domain to - using the following rules..
rewriteengine on
rewritecond %{http_host} !^$ 
rewritecond %{http_host} ^(www.|otherdomain.)? [nc]
rewriterule ^(.*)$$1 [R=301,NC]
to keep everything ticking from the main TLD. It really lives in a subfolder called "otherdomain", but see what happens if you try..

in your browser. Basically, once your DNS is pointing in the right direction, and Apache is ready to play (i.e. there's a valid host entry in its config somewhere) you can do all sorts of funky stuff inside your own space. Imagination is the only limit.

Have fun!

;o) Cor

kai - 15.02.06 2:15 pm

hi, great write up... i've been trying to figure out for a few days now how to do the following redirect using htaccess, hope you can help!

I want to rewrite : to

I know this is probably super simple, but at the risk of embarassing myself, here's what I've tried:
RewriteRule ^/index.php?option=com_smf&Itemid=71&$ /forums/index.php$1 [r,nc]

smiley for :eek:

cor - 15.02.06 5:09 pm

You tried, kai, that's the main thing! So many don't…
And anyway, it's not super simple; unless you know how..   smiley for :ken:

Here's what you need..
RewriteEngine on
RewriteCond %{QUERY_STRING} ^option=com_smf [nc] 
RewriteCond %{QUERY_STRING} Itemid=71 [nc]
RewriteCond %{QUERY_STRING} topic=(.+) [nc]
RewriteRule ^index.php /forums/index.php?topic=%1 [r,l,nc]
It's fairly self-explanatory, though a couple of parts are worth a mention.

The ^ in-front of option=com_smf instruct mod_rewrite to only process the rule if option=com_smf is the first variable. If your variable order is likely to change, remove that. It doesn't matter too much if you remove it now; but I wanted to add that because we don't have many examples of this kicking around here.

I'm thinking I might do a part three that is only examples from these comment Q&A's.

So the three rewritecond lines check that each of the variables exists and the first two are com_smf (simple machines forum? good choice!) and 71, repectively. The third also captures the value of topic, and that value is then available as %1 in the rewrite rule itself.

I also added an "l" to the flags, for "last rule", so no further processing continues after this rwrite. You could have many similar rule blocks in one htaccess file.

have fun!

;o) Cor

ps.. I notice that your rewrite rule begins with a forward slash ^/index.php…, so perhaps you are doing this in httpd.conf or a vhosts file or something, as opposed to an .htaccess file. Yeah?

If that's the case, simply add the forward slash back in.. RewriteRule ^/index.php /test/etc. … I'll leave the above example without the slash, though, because many will copy-and-paste, and most folk are using .htaccess to make these sorts of changes.

kai - 16.02.06 2:27 am

Man, Cor, THANKS SO MUCH! Like I said I've been slaving away the past few days trying to figure it out, scoured SMF & Joomla forums all over... and you answered it with one post. smiley for :geek:smiley for :cool:smiley for :D

Yes, I'm running SMF smiley for :cool: but moving away from Joomla (towards Tinyportal actually), hence the need to redirect all com_smf links to default SMF URLs.

My next step is to redirect SEF URLs, which would be in the form of,com_smf/Itemid,71/topic,385.0. Let's see if I can figure this one out...

ps.. I notice that your rewrite rule begins with a forward slash ^/index.php…, so perhaps you are doing this in httpd.conf or a vhosts file or something, as opposed to an .htaccess file. Yeah?

Err, nope, sorry I guess the ^/ wasn't supposed to be there and threw you off? smiley for :lol: I'm just doing this in 'plain ol' .htaccess.

I'm thinking I might do a part three that is only examples from these comment Q&A's.

^^ would be a great idea!

Thanks again, cor :)

kai - 16.02.06 4:56 am

After spending a bit of time tinkering, I realized redirecting,com_smf/Itemid,71/topic,385.0 is a bit different than my previous URL. For starters, there are no variables, so I don't need as many QUERY_STRING bits, correct? (no ?option=abc)

I'm trying something like this without the RewriteCond:
RewriteRule ^/component/option,com_smf/Itemid,71/topic,(.+) /forums/index.php?topic=%1 [r,l,nc]

What I want the above to do is to capture the part after "topic," and rewrite it as %1... but apparently it's not happening.
THEN I went on to try RewriteCond, with something like

{URL matches component/option,com_smf/Itemid,71/topic,X}
{rewrite as /forums/index.php?topic=X}

the not working code:
RewriteCond %{QUERY_STRING} ^/component/option\,com_smf/Itemid,71/topic\,(.+) [nc]
RewriteRule ^(.*)$ /forums/index.php?topic=%1 [r,l,nc]

Am I anywhere close? smiley for :erm:


cor - 16.02.06 12:48 pm

Hey! Thanks kai!

Your second challenge is quite interesting. As you say about the variables, technically, there are none. It's a lot simpler than you imagine; this should work just fine..
RewriteEngine On
RewriteRule ^component/option,com_smf/Itemid,71/topic,(.+) /forums/index.php?topic=$1 [r,nc,l]
Crucially, note the use of $1, not %1. The latter is for braces matched in RewriteCond (conditions) lines. $1 is for braces matched in the RewriteRule line.

Basically, you had it to start with, except with %1 instead of $1, and, of course, you added that bloody slash! smiley for :roll:

have fun!

;o) Cor

howto? - 16.02.06 2:08 pm

My server is not allowing me to upload htaccess file.
So, I have managed to create the htaccess file thro' a php code, but the url rewriting stuff is not working.
Any suggestions, pleaseeee.

cor - 16.02.06 2:20 pm

howto?, quite possibly your host does not allow .htaccess files. Otherwise why would they prevent it?

Or possibly your ftp client is incorrectly setup; have you uploaded .htaccess files before?
being mindful that many visitors are beginners! smiley for :D

One simple test: put the following command into your .htaccess file..
Which is a special command designed to produce a "500 error". It's foolproof. Drop that command into your main .htaccess file, and then load your front page.

If you DO NOT get a 500 error, and your page loads just fine, then .htaccess is disabled on your site, and you'll have to ask the server admins about it. Tell them to get their act together, or whatever.

for now..

;o) Cor

howto? - 16.02.06 2:46 pm

Thanks a lot Cor,
First - its a yahoo server.
Spoke with them. They do not support .htaccess.
Secondly - I have used htaccess before. I tested it out the same code on my other sites (not hosted with yahoo) and its working fine.

My problem -- Client does not want to shift from Yahoo! server as his site is running there for quiet some time and yahoo does not support htaccess.

Am I in a soup??

cor - 16.02.06 3:09 pm

Ahh, Yahoo! That same company that helped the Chinese government to prosecute a reporter for publishing "dissent". I'd get as far away from them as possible. smiley for :blank:

Be straight with your client. Tell him that if he wants this functionality, he will have to move to a real web host. There are loads of great deals kicking around.

Use the trick I just used on page one, say "If you are serious about your website…", or something like that. Headology.

If you have a few clients, consider getting yourself a sub-hosting deal on a server with gobs of space and bandwidth, then you can run all your clients domains inside it, in an environment you know and trust, as well as give them a great deal on their hosting, better for everyone!


;o) Cor

Bilio - 18.02.06 2:21 pm

hi, it's possible makes ?id=x&y to x.html&y.html to ??

if that is possible, please gives me one example

Thanks a lot

cor - 18.02.06 5:17 pm

What did you try?
and what happened?

;o) Cor

Bilio - 19.02.06 12:58 am

i tried
<IfModule mod_rewrite.c>
Options + FollowSymlinks
RewriteEngine on
RewriteRule $1.php ^(.*)\.htm$

but doesn't work. I don't know if is that.

if not.. please show me the correctly code.

remember, to
Thanks a lot!

cor - 19.02.06 2:45 am

<IfModule mod_rewrite.c>
  Options + FollowSymlinks
  RewriteEngine On
  RewriteCond %{QUERY_STRING} id=(.+) [nc]
  RewriteRule ^(.*)$ /%1.html? [r,nc]
will work.

;o) Cor

ps.. in case you wondered, the "?" at the end prevents mod_rewrite tagging the variable back on the end of the new URI, prevents it getting itself into a loop.

Bilio - 19.02.06 11:07 am

Hello. Thanks!
between very test i don't can work that.
i tried with
<p><a href="?i=asdasd">asdasd</a></p>
<p><a href="site.php">site.php</a></p>

it shows in the same one.

the link ?i=asdasd had to pass asdasd.html or not?

Bye!smiley for :lol:

AMJ - 21.02.06 3:40 pm


I am trying to permanently redirect our PHP scripts to a more search engine friendly all HTML format. However, when I put "R=301" in any line other than the first RewriteRule, the site stops working and FireFox displays "The page isn't redirecting properly".

Can you help? Any assistance would be greatly appreciated.

Here is the contents of our .htaccess file:

DirectoryIndex index.php

AddType text/css .css
AddType text/x-server-parsed-html .html
AddType text/x-server-parsed-html .htm
Options -Indexes

RewriteEngine On
RewriteBase /

RewriteRule ^index.php$ gb/index.html [R=301,QSA,L]
RewriteRule ^(.*)/index\.html$ home.php?sl=$1 [QSA,L]
RewriteRule ^index\.html$ home.php [QSA,L]
RewriteRule ^(.*)/product/(.*)\.html$ product.php?productid=$2&sl=$1 [QSA,L]
RewriteRule ^(.*)/category/(.*)\.html$ home.php?cat=$2&sl=$1 [QSA,L]
RewriteRule ^(.*)/pages/(.*)\.html$ pages.php?pagecode=$2&sl=$1 [QSA,L]
RewriteRule ^(.*)/(.*)\.html$ help.php?section=$2&sl=$1 [QSA,L]

desperate - 22.02.06 3:01 pm

Hi Cor,

The site is very helpful. Thanks a lot. Here is my problem:

I want to redirect to which was pretty easy.

Redirect /index.htm

This also redirects to, while I just want to

Sooo out of luck and sad (Soolas) - 22.02.06 3:31 pm

Good lord. I beg of you to help.

I have a forum and I want it to have a myspace look.

this works (There is a google site map thing there I hope that isnt affected as well):

Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(sitemap.*\.(xml\.gz|txt))$ vbseo_sitemap/vbseo_getsitemap.php?sitemap=$1 [L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{HTTP_HOST} ^$
RewriteRule ^$
RewriteRule (^[-_A-Za-z0-9\ ]*$)$1 [nc]
RewriteRule (^[-_0-9\ ]*$)$1 [nc]

but EVERYTHING goes thru to it. Some urls are not for example:

gets confused somehow as a uers... and of course this user does not exist... the proper "user does not exist" page shows but what if the person needed to change thier login... they cant get to the page.


If you have the time thanks second question is what if you have multiple things in your .htaccess how does the server reconize what is for what?

cor - 22.02.06 4:11 pm

Bilio, ferfuxake! if your URL's are using i="" then use THAT in the rules. You asked for id="", so that's what you got. If you don't want "id", remove the "d" !!! smiley for :roll:

AMJ, firstly you wrongly assume that something.html is more "search engine friendly" than page.php?section=something. It isn't. Why not save yourself a heap of unnecessary work and go concentrate on some content, the number one search engine friendly thing you can do!

As for the rules, as the Americans say "Don't even go there!". I could spend the next half hour going through each line of the .htaccess asking "wtf is this for???", but what would be the point? For instance, is "gb" a file? Do you really want QSA here? Why is is the last rule [L] when you *need* the rules after it to also run, etc. etc. etc.

Start simple. Remove rewritebase and other crap you don't need and do this one rule at a time.

Or a *much* better idea: forget it, it's completely and utterly unnecessary.

desperate seems to be a common posting nickname! smiley for :lol: Helluva state to be in!

I'll assume you are working in your main site httpd.conf, how else would rewrite rules span domains?

That's a clue, see? In short, put the rewrite rules for a domain INSIDE THE DOMAIN. Use a vhost block, .htaccess, whatever.

If you must put them in the main config, use rewritecond lines to catch only the requests for particular domains. Plenty of examples above.

Soolas, your second question is directly related to your issue. When I look at your rules, *I* don't know how mod_rewrite will figure it out, either!

Go read the documentation before trying something this funky, and then start simple. Remember, rules are processed in order. When a rule is matched, mod_rewrite goes back through the rules looking for any rewritecond lines preceeding it. If they match, it processes the rule, if they don't, it doesn't.

In other words, only your first rewrite rules is covered by the above rewritecond lines.

Start again!

;o) Cor

Soolas - 22.02.06 8:30 pm

So should I make two .htacess files? This folder is not at the root.

Ok. you know what. LOL. I have no idea what to do.

shakeer c k - 28.02.06 6:20 am

I want to redirect ^/myco/USeng/nav/-536884605.0/pc.html to
myco/product.jsp?cc=US&lc=eng&nav=-536884605.0 , the nav is optional.
If nav is there i should include in the new url, else dont should include in the new url. And more over i want to display the requested url on the browser address location , not the redirected new url. If anyone can help , please respond and mail me to

Deb (plain and simple) - 28.02.06 9:00 pm

I've spent most of the day trying to find out how to do with my addon domain what you did with your addon domain for Karma. I finally found it here in your post of 9th Feb, so I tried your code on mine but with names replaced obviously. Alas, it didn't work - it redirected my main site to the addon domain. I've changed it back and it is back to normal, thankfully.

So please tell me where I went wrong. I hate to see:

The two sites are totally unrelated. I managed to change by a simple redirect to go directly to its own domain name, but it didn't work for the other way too. smiley for :roll:

Deb (plain and simple) - 28.02.06 9:52 pm

btw, I did read all of part one and two before posting :)

cor - 01.03.06 9:51 am

Deb, I can't see what you are doing wrong, unless I can see what you are doing! Show us yer code!

akalias, I moved your comment to page one (makes a change; it's usually the other way around!)

;o) Cor

Deb (plain and simple) - 01.03.06 3:52 pm

Ok, are you ready?

I've got the main site, then I've got two addon domains in folders. Main site is in no way related to the other two so I want to avoid such things as: or

I want those redirected to their own domain names.

I managed to do the with:

Redirect 301 /addon/

but cannot get rid of the (it's driving me nuts! lol)

This is where I tried your code that you had used for Karma's site (lovely dog btw):

rewritecond %{http_host} !^$
rewritecond %{http_host} ^(www.|myaddon.)? [nc]
rewriterule ^(.*)$$1 [R=301,NC]

What that did was redirect everything on to

Another thing I'd like to know is this bit of your code: ^(www.|myaddon.) is that like a variable between having someone type the www or not? i.e. it can be either way?

cor - 01.03.06 5:20 pm

I need to create a smiley for :gutted:
I finished a cool reply for you, hit "publish", and my browser promptly crashed. smiley for :aargh:

/me gets refreshments, meditates for a minute, attempts to reconstruct...

Right Deb, it's clear to me now! smiley for :D

You are putting these directives in your main .htaccess file!  That's why they are interfering with your requests. These rules belong inside the subdirectory! i.e. /path/to/mainsite/addon/.htaccess

Remember, the addon domain is a real domain, and so the .htaccess file inside it becomes its "main" .htaccess, and the /addon/ subfolder is its root.

And yes, we don't want to deal with or (or even, but those are, in fact, exactly what the server has to deal with. So we have to catch them all, but only once the request is inside the subfolder.

In effect, there are four browser routes into that folder. That is why we have the (www.|myaddon.)? which catches all three incorrect routes, and permanently redirects them to the correct, cute TLD, which becomes the only way in.

Hopefully that makes things a little clearer.
And hopefully it will now work!

;o) Cor

Deb (plain and simple) - 01.03.06 6:29 pm

smiley for :eek: yes I was! The simple redirect: Redirect 301 /addon/ worked fine from there. Should I move that to the htaccess for the addon or leave it where it is or delete it? (I can just see me redirecting visitors of all my sites to the wrong ones! I can picture it now: they want a local place but they end up on the moon! smiley for :lol:) hmmm, now there's a thought for the sp*mmers smiley for :ken:

As you've been so helpful to me, thank you very much, I shall return the favour if I may. I have included my email this time and if you go to that domain >forums> guest/visitors> start topic, you will see a whole load of smileys on the left - feel free to snag any you want.

Mark - 01.03.06 6:50 pm

Great article. But something isn't working for me. Here's what I have:

Options +FollowSymlinks
RewriteEngine on

# Set the RewriteBase to "/" for the root level to base everything on... I guess.
RewriteBase /

RewriteRule ^oldpage.php(.+) newpage.php$1&otherid=0 [R]

The $1 should have all the variable stuff in it from the php.

So I'm looking for it to do this:

oldpage.php?id=1 redirects to newpage.php?id=1&otherid=0

Why is this not working? Any help would be appreciated.


Deb (plain and simple) - 01.03.06 7:18 pm

oh heck, I tried it in the addon htaccess:

rewritecond %{http_host} !^$
rewritecond %{http_host} ^(www.|myaddon.)? [nc]
rewriterule ^(.*)$$1 [R=301,NC]

Result was that it redirected the to the addon url - Great!


it did weird things to which had been ok before using the simple redirect in the mainsite htaccess. I tried removing that completely, but it made no difference. What I was getting when trying: was:

addonURL/home/CPusername/public_html/addon folder

I still need to get rid of the www too as the addon site can still be accessed by that.

My poor little brain is now boggled smiley for :eek:

Deb (plain and simple) - 01.03.06 7:43 pm

Just got rid of the www :)

...and put it back again cos it looked nayyyked! smiley for :lol:

cor - 02.03.06 3:00 pm

Deb, I'm not entirely sure what your current situation is, but to recap; you need NO RULES WHATSOEVER in the mainsite .htaccess. As far as your main site is concerned, the other domain does not exist. period. If you have any rules anywhere else except inside /addon/, delete them right now!

Whether you use www. or not in the final URL is irrelevant, simply add it or don't, to the RewriteRule line. I don't dig it, but you're right, some URL's look nekkid without it. The www inside the condition ONLY catches requests for…, it won't interfere if you add www to the start of the addon domain.

Mark, try something like this..
rewritecond %{QUERY_STRING} id=(.+) [nc]
RewriteRule oldpage.php /path/to/newpage.php?id=%1&oldid=0 [r]
That should do the trick alright.

;o) Cor

ps.. I'll pass on the smiley offer, Deb - you surely weren't serious! smiley for :eek: - but if you really want to give something back, PayPal is good! smiley for :ken:

Cornfused - 07.03.06 5:02 am

Okay now that I've read this whole page I'm even more lost than I started.

I migrated one of my forums from phpBB to vBulletin..

But alas all of my indexed pages are as and of course vB looks like

sync'ing up the topic numbers won't be too difficult, just time consuming, and a lot of rules, so in the interim I was trying just redirect all requests for /viewtopic.php to the index.php, seemed simple enough, obviously I'm cornfused...

This is what I was trying to use(from your example above.

Options +FollowSymlinks
rewriteengine on
rewriterule ^(.*)\viewtopic.php$ [r=301,nc]

Please feel free to tell whatI hosed up!

Then if I can impose a little further an example of how to properly write a rule for changing viewtopic.php?t=1234 to showthread.php?t=5678


Jack - 08.03.06 5:28 pm

I think i made a post on the wrong page, so I reposted on this pages. I added to my initial post; if you can take a look at the questions I have.

Sorry for the double post.

Thanks for your help

I am trying to change all the extentions of my .php files to read .htm but on my site nothing changes in my browser with the script that I am using. Can you take a look at it?

current display:
what I need: home.htm

My current .hta access script:

Options +FollowSymlinks
RewriteEngine on

#Parse pages with extension PHP into HTM
AddType application/x-httpd-php .php .htm

I am trying to set up a store and I have 2 addresses on a site.
The homepage address:
The store address:

I want the keep the www in the address
But I want to hide the www with the “store address location” only with the files displaying from the (eg. “shop” folder)

Can you display how I can do this?

Like mentioned before I have 2 addresses on a site.
The homepage address:
The store address:

How can I for the store address display the word “shop” in front of the web address name.

Can you display how I can do this to?

Vikas Amrohi - 09.03.06 5:10 am

I wanna use url rewriting for my website.
[edit] link removed. ;o) [/edit]

Can any one help me how to proceed with this.

Vikas Amrohi

cor - 11.03.06 2:43 pm

Ahh, got here at last! smiley for :D

Vikas Amrohi, it depends what you want to do. What do you want to do? (apart from link to your SEO site, that is)


A1: that isn't a rewrite rule, that simply instructs the server to parse .htm files as php. In other words, you can put php code inside file.htm and it will be processed as php code.

If you want to rewrite all requests for something.php to something.htm (and I question the sanity of anyone who would want to do this!) then you need something roughly the opposite of the example at the top of the page. Something like..
Options +FollowSymlinks
 RewriteEngine on
 RewriteRule ^(.*).php$ $1.htm [nc]
but again I ask, WHY?

A2: There are examples of this further up the comments. I can write the rule for you, but it's better you do it yourself. Basically you need a rewritecond line that checks for "/store/" and only applies the transformation (rewrite) if it finds it. What have you tried so far?

A3: that simply isn't possible. But you could have You'll need to create that in your admin panel (CPanel, or whatever) before you can play with that.

If you do create this subdomain, scroll up the comments a bit for some groovy ways to operate such a scheme. type-to-find: karmathedog

Cornfused, did you try reading it twice?
That sometimes helps. smiley for :ken:


;o) Cor

Olly - 11.03.06 3:00 pm

I've just completed a site build which involved maintaining the existing site structure (products.html becomes products.php etc) to allow the use of php.

The site ranks well in the search engines, and I originally thought the best way to address the change from .html to .php file endings was to use:

RewriteRule ^(.*)\.html$    $1.php      [L,NC]

However, i realise that there is a good chance that Google etc will also index the 'new' .php versions of the pages which might be seen as content duplication. I don't really want to use:

RewriteRule ^(.*)\.html$    $1.php      [R=301,NC]

as i'm not sure that all the links PR will be passed on, losing position in the search engines. I read in a post on another forum that the following could be used to ensure that all pages are seen as only .html and yet still processed as .php, but when i tried it, my browser returned an error (too many redirects).

RewriteEngine On

RewriteRule ^(.*)\.php$        /$1.html   [R=301,L]
RewriteRule ^(.*)\.html$       /$1.php    [L]

Any advice appreciated.

cor - 11.03.06 3:13 pm

Olly, If you use a proper 301 redirect, you google ranking should be unnaffected. It may blip for a few days, but probably not even that.

As an added measure, drop a nice links script into your site (click the "" at the very foot of this page for mine) so that google can find everything, or use a google sitemap.

A 301 is the correct way to do things. To google it's just the exact same page in a new location. If the only difference is the extension, google isn't going to penalize you. Content is what counts.

Don't go doing retrograde stuff like using .html links for .php pages, it only creates complications. Make a clean break, you'll feel better!

And, of course, ensure all the links on your own site link to the new address a.s.a.p.

Read this.

;o) Cor

Olly - 11.03.06 7:13 pm

Thanks for the advice - another question... smiley for :D

The new pages, whilst containing essentially the same content (keyword
density, and paragraphs of text etc), aren't *exactly* the same; part of the
redesign was to recode the site in XHTML and CSS from tables, in addition to
using PHP, and so layout is quite a bit different. With this in mind, would
you still advise using the redirect below in terms of risk of being
penalized by Google and losing PR/position?

RewriteRule ^(.*)\.html$    $1.php      [R=301,NC]



cor - 12.03.06 1:07 am

Olly, if anything, switching your design from tables to an xhtml/css scheme will probably help your ratings. Suddenly everything is so accessible, your pages are easier to spider, easier to navigate, all the good stuff.

And Google won't penalize you for outdated links on other sites, either, it's knows you've moved the content with a proper 301, so those links are still valid. But do what you can to get them updated, a.s.a.p, anyway.

Personally, I wouldn't hesitate to go through with the xhtml/301 strategy. Like I said, you may experience a Google blip, but it will be a short-term effect, if it happens at all (get a sitemap). In the long run, moving to lightweight xhtml/css can only improve your ranking, in many ways.

I switched these htaccess pages to xhtml about two months ago; Google: htaccess tricks
As you can see, my ranking is unnafected. smiley for :ken:

Of course, I'm assuming your new pages are well formed, validated xhtml, and you aren't trying to trick Google in any way; always a bad idea.

Content is what counts.

;o) Cor

Jack - 13.03.06 5:09 am

I added the script to the .hta access file to rewrite all the .php requests to .htm but, the page never displayed; an error message is all that showes up displaying a page error. Do you know what that could be?
All the .php extentions are from a small online cart that I am building, do you think that some other scripting needs to be modified?

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*).php$ $1.htm


I didnt know what to add/change with the script can you help me out with this?
Currently I have what you had posted on your site hiding the www in the address bar in its entirity.

rewritecond %{http_host} ^www\.mysite\.com
rewriterule ^(.*)$$1

cor - 13.03.06 8:49 am


1. what error message, exactly?

2. try something like RewriteCond %{REQUEST_URI} store [nc], remember, you'll need an "r" inside the rewriterule [flags] if you want to change their address bar.

;o) Cor

ps.. you keep calling it ".hta access", I assume that space is just your repeated typo. If not, remove it!

Jack - 14.03.06 4:57 am

Thanks for getting back with me; I attached the error messages that I am getting. The port 80 error is consistent, What is causing that in your script? If you can please take a look at the responses below.


Not Found
The requested URL /xcart/home.htm was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

Apache/1.3.33 Server at Port 80

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*).php$ $1.htm [nc]



Not Found
The requested URL /xcart/home.htm was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

Apache/1.3.33 Server at Port 80

Using your current SCRIPT:
rewritecond %{http_host} ^www\.mysite\.com [nc]
rewriterule ^(.*)$$1 [r=301,nc]


Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request. Please contact the server administrator, and inform them of the time the error occurred, and anything you might have done that may have caused the error. More information about this error may be available in the server error log. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Apache/1.3.33 Server at Port 80

When this SCRIPT is USED:
RewriteCond %{REQUEST_URI} store [nc],
rewriterule ^(.*)$$1 [r=301,nc]

cor - 15.03.06 4:20 am

Jack, that isn't my script, it's just apache directives. And they were just an example. The error.. The requested URL /xcart/home.htm was not found is fairly explicit; the document isn't there. If your rewrite works, and you request /xcart/home.php, and there's no actual real file at /xcart/home.htm, then you will get a 404, of course.

Additionally, your 404 page is missing. Fix that!
All regular web servers run on port 80, that part of the error isn't significant.

Are you new to all this?

Error b - you could have simply said "a 500 error", but then, I did say exactly smiley for :roll: - is probably caused by that comma you mistakenly included with the directive, which again was an example (spot the words "i.e." and "like" preceding them), something to consider and work from, not meant to be just copied blindly into your .htaccess file.

If you just copy stuff blindly into your .htaccess without understanding it, you are a) asking for trouble, security-wise, and b) likely to add punctuation not intended to be in the directives, like, for instance, a comma.


;o) Cor

Jack - 15.03.06 6:11 pm

Actually, yea I am new to this. I though that it would just overite the .php extension to an .htm guess I was off on that.

- Currently I only have php files, what do I do to make an .htm file display the php information?

- You know in the address bar if I key in a different location that isnt located in the site directory is it possible to reference the user back to the page they were at befor they keyed in a invalid web location?

IF exists in the directiory
and I key in (this directory does not exist) THEN the customer will be referenced back to the page instead of a error page displaying?

So insted of error page displaying, a client side error is redirected to the page they were viewing befor the error occured.

I understand your concern with copying files, Thank you.

You were write with the comma, it was causing the error. The page doesnt display errors but in the address bar the doesnt display.
I dont understand what you mean with (spot the words "i.e." and "like" preceding them. Confused on doing this?

cor - 15.03.06 11:13 pm

Jack, if you only have php files, WHY ON EARTH are you trying to rewrite links to .htm??? In a word: insanity. Scrub the whole (1) idea and leave the php extensions alone!

I'll get to the question you sneaked in here, after (2)

I was concerned with you blindly copying commands into your apache configuration, NOT files!

And, to get the new address to display, as I said before, add an "r" to your flags. (that's the bits inside [square brackets] at the end of the rewrite rules)

Jack said..
I dont understand what you mean with (spot the words "i.e." and "like" preceding them.

What I mean is, "Something Similar To", or, if you prefer, "Something LIKE This". In other words, the commands I gave you were Starting Points where you could begin to develop the exact rules you need. They were not the complete rules. Not for off it, sure, but not meant to be taken as-is, you know. aka "examples".

Jack said..
is it possible to reference the user back to the page they were at befor they keyed in a invalid web location?

Hmm. This Q&A might have some value after all! Yes, it is possible (what isn't?), and it's an interesting approach to 404's. There are drawbacks; the user is unlikely to know they got a 404, and when they land back on the old page, they may be slightly confused, and quite probably click the link again, just to see.

Essentially, this is how you would do it..

1. ensure you have a valid 404 script location set in your apache configuration (either in the master httpd.conf, or else in the main .htaccess for your site). If your 404 page lived inside a folder called "err" in the top level of your site, and was called "404.php", that line would look exactly like this..
ErrorDocument 404 /err/404.php

2. Create a 404 script with something like this inside it..

if(!empty($_SERVER['http_referer'])) {
header('Location: '.$_SERVER['http_referer']);
} else {
'404. Page not found. sorree.';

3. save the file inside the top-level "err" folder and call it "404.php".

The script will redirect the user directly back to where they came from. If, for some reason, the referrer information is missing (rare, but it does happen) the script(Yes, THAT *is* a script!) simply reports the 404.

You may want to add a timer to the page, and allow the user to see a message for a few seconds before redirecting back to the referring page, but I'll leave that as an exercise for you.

Of course, the very best way to deal with 404s is to not have any broken links in the first place!

;o) Cor

Jack - 16.03.06 1:17 am

Thanks for your comments, I relly appreciate you getting back with me on that added question, I will apply it and see how it works.

I have a cart I'am building using .php extention but the rest of the site is all .htm; with my questions they were all referenced with editing the store with the php extentions.

I just want to have all the extentions display the same; is their any tutorial or directions you could provide me with that could do this referencing .php extentions to .htm?

Also is it possible to hide the .php extention. I know of the integration of an <iframe> but is their any way using .htaccess?

cor - 16.03.06 5:36 am

It's a trivial rewrite, Jack. Roughly the opposite of what I first interpreted as your desire. Try this..
 Options +FollowSymlinks
 RewriteEngine on
 RewriteRule ^(.*).htm$ $1.php [nc]
That will do the job. The user requests whatever.htm, and in the background it is translated to whatever.php, but, remember, you still have to present those links as something.htm in the first place. Can you CMS1 do this?

mod_rewrite is only one half of the equation.

See (1). If you silently rewrite all requests for .htm to .php then the user never sees the .php extension, period. The crucial question is still, can your CMS present its links as .htm instead of .php?

your CMS is the other half of the equation.

;o) Cor

ps.. I'm tired of removing the [sm]small[/sm] tags around every one of your posts, can you please respect the page font size and only use [sm]small[/sm] tags around things you really need to be small, i.e. not the whole post, thanks.

CMS = Content Management System; shopping cart, blogger, wiki, whatever.

smithdiesel - 16.03.06 9:44 am

I didn't know what rule to have for redirecting the following

index.php?main_page=index&cpath=31_14 to category/31/14.html

cpath will have values like 31_14, 31_14_21 etc.

cor - 16.03.06 4:27 pm

What have you tried, smithdiesel?

You want me to help fix your code, I gotta see it!

;o) Cor

mike - 16.03.06 10:26 pm

First off, great article, easy to understand.

Unless I missed it, I haven't seen this addressed:

I'd like to change my root directory with a redirect. My current root directory and main site is located in /public_html/ but I want it to be /public_htm/folder/.

My .htaccess file, which is in /public_html/ :

Options All -Indexes
Options +FollowSymlinks
RewriteEngine on
RedirectMatch permanent ^/folder$

When I go to my site I receive a 403 Permission Error.

How do I fix this?


smithdiesel - 17.03.06 6:37 am


if the cpath value is simple a number (31) then the rule is

RewriteRule ^index.php(.+)main_page=index(.+)cpath=(.*)$ category/$1/$1.html?

i need the rule if the value changes to 31_14 or more sublevel values like 31_14_16 etc.

Can you help me.

Dino - 18.03.06 2:30 pm


I need help for my site.

I want when someone click exactly on this link he gets ?
Can you pleaase post your solutions.

fruit loops - 18.03.06 8:26 pm

Hi, Nice tutorial.
Im running into a few problems of my own.
Currently i have a site thats in "C:\apache2\htdocs\mysite"

So when i acces the site...i do localhost/mysite/homepage.php

Im trying to rewrite so that i can just do localhost/homepage.php

this is my rewrite rule, but its not working.

rewriterule ^(.+)\.php$ /mysite/$1.php

Am I doing somkething wrong? I get an internal server error.

But if i do this..

rewriterule ^(.+)\.htm$ /mysite/$1.php

it will work.

Why is that?

Also, my hompage.php files has images that is being referenced like images/image.gif. So actually, w.o the rewrite rule, the images will load properly because the relative-ness of the directories are correct. With the rewrite rule, they become unloadable ..they are being referenced as localhost/images/image.gif when they should be localhost/mysite/image.gif.

Is there a rewrite rule to fix the image issue or do i have to go through the source code and modify the path?


tony - 19.03.06 4:58 pm

I have links on a page that are derived from db field values like
Once the link is clicked I'm trying to direct the user to predefined pages with html anchors like
What is the best method / regex to include in my htaccess that would replace '?parameter=3003' with '#a3003'.

kind regards.

Dep - 20.03.06 1:45 am


I want to redirect users like this:

If user requests any of this:

then apache should redirect to:

I experimented ~2 hours but no results.. :(
This is not working: RewriteRule ^(.*)$ ?accessed=$1

Where is error? Thnx.

Jonathan - 20.03.06 3:27 pm


I have a nice site, just as I want it.
I changed it from non sef url's to sef urls (joomla)
but the old links from google don't work,
here's what goes wrong:

Not Working,NL/

So the trailing slash is the problem with these URL's

I however would prefer to redirect to:
Which also works.(completely removing the Lang,NL/ part

Basicly I only want to rewrite when "Lang,NL/" is in the URL
RewriteCond %{QUERY_STRING} Lang,NL/
Rewriterule ...

I have tried stuf, and at my last atemt my site went completely down, the root, and al subddomains and subfolders.

Sory I couldn't figure this out myself, even with all of these examples posted here.

My current .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteBase /index.php/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php
This .htaccess file makes all of the links on my site work, now I need to get old URL's from google and other sites working again.

jignesh - 23.03.06 8:00 am

it is really nice matiral. This all content help me a lot.

Dennis - 23.03.06 8:31 pm

Hello, and thank-you for one of the better examples on the web of this mod, I have a problem though, my site seems to block all images when I apply the rewrite rule for hotlinking images, this is what I am using below:
Options +FollowSymlinks
 # no hot-linking
 RewriteEngine On
 RewriteCond %{HTTP_REFERER} !^$
 RewriteCond %{HTTP_REFERER} !^http://(mister.)? [nc]
 RewriteRule .*.(gif|jpg|png|jpeg)$ [nc]
can you please help, I tried various formats, none do the trick, all my images are being blocked, page layout as well, is what I have correct? do i need to specify special access to specific folders?

any help would be much appreciated.


Dennis - 23.03.06 9:07 pm

I hope you can see this: Reminder i am on port 8080 thx
this is a free domain redirecting to my ip address, forgot to mention that.

#php_flag magic_quotes_gpc off
Options +FollowSymLinks -Indexes
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^http://(mister.)? [nc]
    RewriteRule .*.(gif|jpg|png|jpeg)$ [nc]
	RewriteBase /
	RewriteCond %{REQUEST_FILENAME} -f [OR]
	RewriteCond %{REQUEST_FILENAME} -d
	RewriteRule ^.*$ - [S=35]
	RewriteRule ^article/(.*) blog.php?id=$1
	RewriteRule ^archive/([0-9]{4})/?$ index.php?date=$1
	RewriteRule ^archive/([0-9]{4})/([0-9]{2})/?$ index.php?date=$1$2
	RewriteRule ^archive/([0-9]{4})/([0-9]{2})/([0-9]{2})/?$ index.php?date=$1$2$3
	RewriteRule ^category/(.*) index.php?cat=$1
	RewriteRule ^comments/(.*) comments.php?id=$1
	RewriteRule ^trackback/(.*) trackback.php?blog_id=$1
	RewriteRule ^page/(.*) static_page.php?id=$1

cor - 24.03.06 12:41 am


Sorry dudes, I've been a bit indisposed this week.

mike, you change your root directory in httpd.conf. It's a server directive, not a rewrite. Something like this..
rewritecond %{REQUEST_URI} !folder/ [nc]
rewriterule ^(.*)$ /folder/$1 [nc]
would work, but really, you want to do this properly in your httpd.conf or control panel; rewriting every single request is simply wasteful.

smithdiesel, this may be a first, but, I look at what you want and I can't think of an elegant way to do it, and besides, your question is back-to-front! Isn't it? I might have a wee mess around over the week-end and see if I can work something out. By the way, if you figured it out in the last few days, post the solution! Except the other way around, right? I might wait until you back to me on that. smiley for :ken:

Dino, that's too easy! There are dozens of examples above!

fruit loops, see my notes to mike, above. clearly you have access to the main httpd.conf, so why not set the document root there, or better yet, create a "mysite" virtual host. (navigate up to for details of how to make a virtual host).

You definitely don't want to go editing path statements ANYWHERE in your code. Good code will work wherever you drop it. Relative links are just fine, so long as everything else is working.

Yes, you can do this with mod_rewrite, and have all the images working perfectly (there's a good example further up the comments) but you want to avoid that route if at all possible, not only because it's wasteful, it's just plain silly!

tony, again, some great examples exist in the comments here (I really need to get around to packaging them up into a third page, because folk just don't seem to able to click the "previous page" or "show all comments" links above. smiley for :roll: Not to worry.)

You capture variables like this..
rewritecond %{QUERY_STRING} id=(.+) [nc]
rewriterule ^(.*)$ /%1.html? [r,nc]
the variable in this case being "id". And you slam it into the rewriterule with "%1". It's fairly straightforward once you know the mechanism. The "?" at the end of the rewriterule prevents Apache adding the original variables back on, by the way.

Dep, your targets are invalid, the last pair, anyway. The first set you deal with like this..
rewritecond %{QUERY_STRING} !accessed [nc]
rewriterule ^([^/]+)/?$ /?accessed=$1 [r,nc]
You can remove the "/?" from the rewrite rule condition if you want the trailing slash to carry through in the query, I just figured it was best to demonstrate how to remove it, which is what most people would want, I reckon.

Jonathan, use the principle I just demonstrated (SEE! Dep!), making your rule something like..

RewriteRule ^(.*)/? index.php

Dennis (I see you discovered the [pre] tags, good work! - by the way, I fished out your code form my handy post dumper dump and re-inserted it into your post, in [pre] tags!)

Okay, to the rule, by the looks and sounds of things it's all getting very complicated when probably all you need to do is.. wait for it.. add the name of the "free domain redirecting" HOST! Think about it, they are the referrer!

for now..

;o) Cor

Jonthan - 24.03.06 3:44 pm


RewriteRule ^(.*)/? index.php

I tried that, but it still won't work,
I still get a message that I would not be authorised to vieuw this content.
Removing Lang,NL from any url would also do,
reulting in a url like:
(two ending slashes without the Lang,NL. So the previous URL should be redirected, to this url.

Even when I try something like:
RewriteRule ^(Lang,NL)?/? index.php
my url from google still won't work.

cor - 24.03.06 7:16 pm

Jonthan, perhaps there's funky stuff happening inside your php. I'm not familiar with joomla, so I can't say what that might be.

But that rule will certainly lop off a trailing slash, so long as other rules aren't interfering with that. This..
RewriteCond %{QUERY_STRING} Lang,NL/
would mess up everything, as would this..
RewriteRule ^(Lang,NL)?/? index.php
because a) "Lang,NL" is not a part of the query string, it's a regular path part of a regular URL, and b) "Lang,NL" is not at the start of the query (which is what the "^" is all about).

check that, and remove any such junk. If you want to post your entire .htaccess (removing any data you need to keep secure, of course) I could have a look at what *might* be interfering.

Another thought; you can remove individual variables with mod_rewrite, too, so perhaps you could catch it after the main joomla rewrite (so long as it has no "L" in its flags)..
rewritecond %{QUERY_STRING} (.*&)?LANG=NL(&.*)? [nc]
rewriterule (index.php$) $1?%1%2 [l,nc]
which would turn a request for into

There will be a way, though you better be quick; very soon Google will index all these 404's and you'll be reconsidering the term "search engine friendly", which dynamic variables ARE, by the way.

;o) Cor

AQ - 28.03.06 9:51 pm

Hi Cor - Great article. Maybe I overlooked it somewhere, but here's what I am trying to do.

I have a url that reads

I'd like do a ReWriteRule that would convert make this URL:

I have a feeling that it's something simple that I am overlooking but I can't quite get the syntax down. Any help that you could provide would appreciated immensely.


cor - 29.03.06 2:10 am

Yup AQ! You overlooked it!

Scroll up slightly to this post for the most recent example, right after where it says..

You capture variables like this..

have fun!

;o) Cor

tony - 30.03.06 10:23 pm

You're a hero. Your example gave me the heads up to solve something I have struggled with for sometime now. Of course I changed it to suit my needs so I include it here for completeness.

rewritecond %{QUERY_STRING} kua_num=(.+) [nc]
rewriterule ^(.*)$$1#a%1? [r,nc,ne]

Great article. I've taken the next step and ordered myself a book on mod_rewrite from 'A'.
Keep up the good work.
Kind regards.

bcwebstudio - 30.03.06 11:22 pm

Great page! I like your style, but I fear your response...

O Wise One of the Rewrite.. I beseech thee with what to me has been a life-long quest but for you is less than but a blink of the tip of a single eyelash. My rewrites work, but I can not seem to get them to hide the rewrite browser-side.

An example of what I wish to duplicate is your blog/2003-nov example above, so I even copied that line from your example into my .htaccess and commented it out, so I could be Just Like You.

Options +FollowSymLinks
  RewriteEngine on
  RewriteRule ^monitor([0-9]+) http://bcweb/apps/docketscroller/showdocket-js2.php?monitorid=$1 [nc]
# RewriteRule ^blog/([0-9]+)-([a-z]+)$1-$2 [nc]

I'd like the visitor to see only, for example: http://bcweb/apps/docketscroller/monitor1

I didn't realize it until now, but you've been bombarding us subliminally with a big ;o) symbol in the bg. Puts me in a sarcastic mood.

bcswebstudio - 31.03.06 5:19 pm

my solution.. changing:
RewriteRule ^monitor([0-9]+) http://bcweb/apps/docketscroller/showdocket-js2.php?monitorid=$1 [nc]
RewriteRule ^monitor([0-9]+) showdocket-js2.php?monitorid=$1 [nc]
did it for me.

So why does your example:
RewriteRule ^blog/([0-9]+)-([a-z]+)$1-$2 [nc]
seem to work for you?

hafio - 02.04.06 5:35 am

Hi, i was wondering if it's possible to prevent people from saving a image from your webpages? I know there's the "anti-rightclick" method and the "hotlink protection" method. I have successfully done both but whenever i am inside my own pages, i can still save the images. Any idea? Thank you very much in advance.

ps: great tutorial site you got here, cheers!

cor - 03.04.06 3:42 pm

bcswebstudio, I'm guessing because "bcweb" isn't a real domain.

My own (new) blog permalinking uses directives placed inside the local folder, allowing me to have permalinks like this..

which actually point to..

The directive lives in /devblog/.htaccess and looks like this..
rewriterule ^([_a-z0-9]+)-([_a-z0-9-]+)/?(.+)?   index.php?archive=$1-$2&blog=$3 [nc,l]
I've had mixed results using domain-less targets inside folders, and it's usually easiest to just supply the full url, though the above works just fine with or without the "" part. On some web hosts, you can even use "http://{HTTP_HOST}/" and it works great!

As we techs are fond of saying.. your milage may vary.

hafio, unless you want to password protect the image directory, there's isn't an easy way to do it, and even then, once logged in, they can save the images easily enough.

Apparently some porn sites manage this (so I'm told) so possibly there is some kind of javascript method kicking around. If you took the image data, encoded it with something simple (at the server end), like a binary rot-13, and then had javascript decode the data before displaying it as an image, then perhaps you could protect the image itself, but someone determined could still figure out your encoding method, by simply looking at the javascript.

Perhaps you might like to do some field research? smiley for :lol:

Seriously, though, there are better ways to do this. Content creators have access to all sorts of ways to embed copyright and other information in their images. If such things are important to you, google for "image watermark" or "free Steganography" or something.

If you sell images delivered over the web, you might want to check out something like CatchLock.

have fun!

;o) Cor

Daniel - 05.04.06 2:43 am

Can I rewrite (redirect) to a different root directory?
Let's say root directory is /here/is/domain
If a browser enters then he will be forwarded to the directory /home/of/zzz where an index.html resides
^(.+)zzz$ /home/of/zzz


cor - 05.04.06 5:23 am

Daniel, yes, you can use an internal redirect (no "r" in the flags), so long as you don't go outside the server's root, or your domain root, if you are on a shared server.

There are so many factors which can affect your access to various paths on the system, this one is best done with a suck-it-and-see approach, using some obscure filename as your test.

Looking at your question, however, I'd probably guess that it's NOT possible.

for now..

;o) Cor

hOzEr - 05.04.06 11:08 am

how i can make one regex to accept a-z,A-Z,1-9 and accept "%" a-zA-Z1-9% , don't work. ?? example: ol%ds (it has of accept the %)

thanks a lot. smiley for :D

cor - 05.04.06 3:46 pm

Good question, hOzEr!

You probably just need to encode the "%" symbol for transport. In other words, your actual links would be, or whatever. You can't send a raw % in a URL; it has a special meaning; the server will only gronk. So encode the links. Then, this..
rewriterule ^([a-z0-9%]+)$  index.php?var=$1 [nc]
works just fine.

The captured variable would be ol%ds, as expected.

;o) Cor

Gigi;) - 06.04.06 9:50 am



is it possible (& how smiley for :)) to allow hot-linking, but the pics will have a nice watermark/text on itself?

THX! Great stuff in here!

Gigismiley for ;)

cor - 15.04.06 10:02 am

I could have sworn I answered this days ago, and a nice full reply, too. damn!

I explained how you'd need to serve them up with a php handler, and use GD to overlay the text on the image. I even gave a code example! wtf! smiley for :aargh:

och well, that's what you do! smiley for :roll:

Essentially this is what ampsig does, except you probably wouldn't want as much text, or as varied. Grab the source for lots of text-on-image type code examples!

;o) Cor


Hey! I fished my old reply from the post-dump (see! this is why I created that thing!)..

Sure, Gigi, that's possible, and a GREAT idea! But we've left the realms of .htaccess and dived into the wonderful world of php GD (or ImageMagick, if that's your bag); ie. server-side image processing, something I rather enjoy doing.

Instead of redirecting to a "hot-link image", You simply pass the requests through a php image handler and get it to overlay your watermark. Very clever!

I altered my own hot-link image a few weeks ago, and I have to say, it was a similar stroke of genius! Most hot-linking images are plain things, "no hot-linking" type messages and what-not, not only very boring, but they DO NOTHING.

Mine is now an image of the some text. It reads..

So, instead of stealing images, my hot-linkers do free promotion! Just a pity you couldn't generate an image with an embedded link. Although, of course, you can embed lots of other things in them. smiley for :ken:

With php and GD, it's very easy to place text on an image, like this..

// 'watermark' in the upper left (x=6, y=3) of an image..
$my_text = 'watermark';

// open image and lay white text on it..
$img = imagecreatefromjpeg ('example.jpg');
$white = imagecolorallocate($img, 255, 255, 255); // white
imagestring($img, 4, 6, 3, $my_text, $white); // size 4 built-in typeface

// send the image
header("Content-type: image/jpeg");

Of course you could go on to use semi-transparent TrueType fonts and do all sorts of other fancy stuff, but that's it in a nutshell.

Have fun!

;o) Cor


Milos - 17.04.06 2:41 pm


I've created the .htaccess file with following lines:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^index\.html$

And placed it in my wap subdomain folder.

So, I wanted to redirect my subdomain to address

The problem is that it won't work if you just acess the address, it'll only work in case you type in

Can I make the redirection work when you just acess

Milos smiley for :)

Good Sit - 18.04.06 7:13 am

tell me use of .htaccess file

cor - 19.04.06 3:12 pm

Milos, that's because "index.html" is specified in the rule.
simply remove that. something like this..
RewriteRule ^(.*)$$1 [nc,r]
would be better. Check back through the comments for some very good sub-domain examples.

Good Sit, start at the top of the page!

;o) Cor

Milos - 19.04.06 4:05 pm

Yes, it works. smiley for :D

Thank you man, you'r in my favorites now!

cor - 20.04.06 1:36 am

You mean I wasn't already? smiley for :eek:

smiley for :lol:

;o) Cor

rajesh - 20.04.06 3:04 pm

i need help in writting a mod rewrite rule for a domain.
the problem is i have the url: . i don't want the folder/valentine to appear in the url.

smiley for :roll:

Dennis - 20.04.06 5:34 pm


Me again,

quick reminder, you suggested that my redirect host was the actual referer for my hotlink problem, well I contacted them and have seen other examples of redirect sites and my actual redirect hostname is the referer.

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?mister\ [NC]
RewriteRule .*\.(jpg|jpeg|png|gif)$ [NC,F,L]

is not working for me, hotlinking continues, can you please guide me as to where my problem is?

your last suggestions was to replace http://(www\.)?mister\ with http://(www\.)?my\

if you can clarify this for me it would be greatly appreciated, you have my email address, contact me if you dont mind.


stu - 21.04.06 2:12 pm


Im trying to make to redirect but it comes with double slashes like

Im using this: RewriteRule ^index\.php$$1/

Is there any way to fix this problem.


Parikesit - 21.04.06 2:38 pm

Dear All,

Can I use mod rewrite for mirroring my website?

I have 2 server, server1 (ip=202.*.*.*) and server2 (ip=198.*.*.*). I want to split the visitor by ip-address.

When it comes from ip=202.*.*.* it will be redirected to my server1, otherwise it will be redirected to server2.


cor - 21.04.06 5:53 pm

Parikesit, it's really too late. By the time we get to reading .htaccess files, we are already performing the request. Setting up a permanent "round-robin" with .htaccess is probably doable, but a crazy waste of resources.

Your best bet would be to catch this sort of thing at your gateway, google for "balance" (along with a few web server related keywords) and you should get your man. Squid could probably do this, too.

From the balance manual..
A "%" instead of a "!" as a group separator declares the previous group to be of type "hash". This means that instead of a round-robin algorithm, a hash distribution based on the client ip address is used to determine the destination channel.

In other words, balance can do what you need.

rajesh, simple answer: move your document root to /valentine.

Or is this an "add-on" domain of some kind? If so, valentine shouldn't be in the URL, unless something is wrong with the setup.

If you want a more intelligent answer, give me some details about your setup, and *exactly* what you are trying to achieve, and *exactly* what the trouble is.

stu, try taking that extra "/" off the end of your rule, that should fix it. smiley for ;) By the way, the rest of the rule sucks, too. Where DID you get that thing!? This is enough..
RewriteRule ^index.php$ [nc,r]

Dennis, that server is password protected, no way anyone can hot-link images from there! Your rule looks to specific to me (you don't need port numbers, for example), but if anything that should make hot-linking more difficulty, not the other way around. I'm surpised you can load images at all, even on your own pages!

If you want to mail me with the actual URL of your site (as accessed from the outside world), and a copy of your .htaccess, and the actual URL that is hot-linking your images, I'll definitely look into this for you, get back here with the results.


;o) Cor

DavidR - 21.04.06 9:31 pm

Can you quickly tell me how to modify the following bit of .htaccess code derived from your site:

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^www\.davidr\.com [nc]
rewriterule ^(.*)$$1 [r=301,nc] that it not only redirects '' to just '', but so it also redirects '', '', '', and '' *all* to '' ? (Just three domains, but six possible variations, and I'd like them all to redirect to and use just ''.)

Thanks sincerely!

Dennis - 22.04.06 12:06 am

Hi Corz,

I sent you all the information via email.


cor - 22.04.06 12:10 pm

DavidR, try rewritecond %{http_host} !^davidr\.com [nc]

Quick enough? smiley for :)

Yup, Dennis, some of it. I await the rest!

;o) Cor

DavidR - 22.04.06 6:56 pm

sorry, now I'm confused. wouldn't it still need the variables and stuff so that still goes to ? - 23.04.06 1:22 pm

Fabulous site.

Dennis - 23.04.06 4:02 pm

sent missing info


J-J - 24.04.06 12:44 am

Great info, has helped alot, although I do have a request.

I am trying to hide a URL, its long and its uggly. I have managed to redirect with no problem. It leaves "" in the browser address bar but shows the page correctly.

I really would like it though to be able to have - however when it takes me to the page, everything thinks its in mydomain/forum/car/ which obviously it isn't so pictures dont load and links don't work. Surely it can't be far off as the script is generating the page, just not correctly. Is there any way round this?

Also, when someone clicks on a link that has been auto generated, its the 'ugly' URL, is there a way to catch that, and send it to the clean address, incase someone wants to copy and paste the link? The urgly URL looks like:
I want it to look like:

Dennis - 24.04.06 2:42 pm


I have successfully created my rule,

Thank you for your help.

cor - 25.04.06 1:44 am

I'm not sure what the state of play is, Dennis, time-zones and what-not, but hopefully your recent post was after your recent email! smiley for :lol:

My thoughts are that though the rule was shakey, it would work, the trouble is most likely further up the .htaccess file.

And it's "cor"!!! smiley for :aargh: For a capital "c", I use a left bracket, but that's just me. "" is like "cor's org", as in MINE, but you can't have apostrophes in TLDs. cor's == corz, see? smiley for :ken:

DavidR, yeah, but you still need the rewriterule! I would have explained more deeply, but you wanted a quick answer! That rewritecond should handle the whole show, though, unless I'm missing something.

J-J, the most important part of all this is the generation of the links in the first place. That's where you need to make the changes. Once you have your software producing the flat links, it's a trivial matter to redirect them to the *real* dynamic links in the background. It's irrelevant which delimiters you use (the characters separating the data, "-", "/", etc), so long as you match them in your rewrite rules.

Then you simply *don't* use the [r] flag, and keep everything transparent (the user ALWAYS loads the page's dynamic link in reality, only on the surface does it ever look flat, like the ocean). Drop something like this inside your forum directory..
rewriterule ^car/([0-9]+)/?  garage.php?mode=view_vehicle&CID=$1 [nc,l]
because the only value that changes is the number, the rule itself is very simple. If you replaced "car" for ([a-z]+), you could process that, too, have "view_vehicle" be something else, but you didn't specify.

But most importantly, you need to generate these links in the first place, which means inside your content management system. I'm stressing this because in your post it's almost an afterthought, an added bonus or something, but THAT is where the fundamental changes must be made. If you can't generate flat links, forget it. But if it's php or something like that, dig in!

If it's not your own CMS, contact the developer and ask if there's an easy way to do it. In corzblog it's a simple checkbox to switch between flat and dynamic links, but probably most CMS aren't so easy.

have fun!

;o) Cor

nagendra - 25.04.06 8:42 am

I have two problems

1. I don't want to show my link or url to any one.
It should be static like
but now it is showing like,,etc

2. I have the url as I have to redirect it to At the same time i don't have the folder nare, and i should have the nare will be in name variable


cor - 25.04.06 1:24 pm

No, nagendra, you have at least three problems!

1. If you "don't want to show my link or url to any one", you might as well not bother having a web site! and and ARE static links.

Unless your site is all on one page, or controlled from one file, you need to have more than one link! And people *will* need to see them! Really, I don't know what you are trying to do, but if you show me the code you've tried so far, I might get some clues.

2. You don't need the folder "nare" to exist, because you are redirecting..
rewriterule ^nare/? index.php [nc,l]
something like that, yeah?

If you want help with 1.,provide more information and code, or a clearer explanation of exactly what you are trying to achieve.

;o) Cor

nagendra - 25.04.06 1:50 pm

I have the url as I have to redirect it to At the same time i don't have the folder nare, and i should have the nare will be in name variable.

for the above problem, it will not be nare all the time. That is also dynamic which is retrieved from the database, so i want code for that

I am having the whole site which has some 20 files, but i don't want to show all the urls in the address bar. I have to show url only as I can call it internally know. I want code for that

cor - 25.04.06 1:59 pm

Show me your code!

I can't help unless I know what you want to go FROM AND TO. ie. examples.

Scroll up through the comments here to see how people usually frame these things. Even if it's back-to-front, at least I'll get an idea about *exactly* (and it must be exactly) what you are trying to do. "I want code" is not a big help to me, in fact, it's a real turn-off.

I want money!


Next, so, how will those twenty files be called? Is there some dynamic link? What are the variables? What are the target URL's? What do you have generated in the pages, what does the user see? etc., etc.

I'm 100% certain that a) what you want to do is really simple, if only we knew what it was, and b) the answer is most likely already here.

As for the "nare" thing, if "nare" will be a variable, simply make that rule..
rewriterule ^(.*)/? index.php [nc,l]

But, don't you want the "nare" to appear anywhere in the target URL???
Perhaps index.php?raboof=nare, no? Something like that?

I'm not a mind reader, at least, not unless you are sitting in the same room, which you are not.

;o) Cor

DavidR - 25.04.06 7:13 pm

When I asked if it could be done quickly, what I meant was the equivelent of "could you [if it won't take you too much time] tell me..." as in, I didn't want to impose on you but figured it would probably take you two seconds. My apologies if you interpreted it otherwise.

Could you please explain to me why this doesn't work?

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^www\.davidr\.(com|net|org)/(.*)$
rewriterule ^(.*)$$2 [r=301,nc]

cor - 25.04.06 10:42 pm

With ye, David! Well, you're right, it only took me a couple of microseconds to work out your solution. On the other hand, explaining everything that's wrong with your latest ruleset is gonna take ages!   smiley for :lol:

For a start, it (the rewritecond) demands that the URI have "www" in it, so any,, and links will not be caught. Then it goes on to to be specific about the rest of the URL, that it must have a forward slash after the TLD, so hits on plain, net, and org etc are now also lost to the rule.

The rewriterule itself creates a captured "$1", but you then go on use "$2" in the target, which doesn't exist. In short, it's a mess! This is all you need..
rewritecond %{http_host} !^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]
(assuming mod_rewrite is enabled, etc). The condition catches absolutely every URI that isn't*something* and redirects it to*whatever*. Requests to*etc.* pass clean through.

So long as your DNS is setup, and those other TLD's actually point to your site, it should all work swell.

;o) Cor

Dennis - 25.04.06 10:56 pm

my sincere apologies, I just hate it when ppl get names wrong, it was not intentional, yes my email was sent before my post, all is fine and thanks again.

cor - 25.04.06 11:35 pm

No worries, Dennis, it doesn't really bother me much, but I enjoy dropping that in every now and again! smiley for :lol: Really, I am my org, and vice versa, so it's a kinda compliment, really. smiley for :)

All the best, dude!

;o) Corz

Lou - 26.04.06 3:08 am

Wow!!! Great Stuff! I'm gonna try a few things in here to see if I can fix a problem.

Trying to rewite a vhosted directory on an SSL site to another directory on an internal (non-SSL) server. Am having lots of problems with either Access Denied (Follow Symlinks?). I've done a similar thing for non-SSL pages for the rest of the site with Reverse Proxying - no prob!

But can't get it to work with SSL -> non-SSL Proxying or Redirecting.

Thanks for the great site! Lou

Paresh Parihar - 26.04.06 7:20 am

I am getting Internal server error if i uncomment the followsymlinks line.

# Options +FollowSymLinks
RewriteEngine On
RewriteBase /usr/local/httpd/htdocs/1247/1204/beta/

Any reason why this is happening. If i keep it commented the site works fine.

stu - 26.04.06 12:19 pm

"stu, try taking that extra "/" off the end of your rule, that should fix it. smiley for smiley for ;) By the way, the rest of the rule sucks, too. Where DID you get that thing!? This is enough..

RewriteRule ^index.php$ [nc,r]"

That gives me an "Couldn't redirect properly" error with Firefox.

And removing that$1/ last slash like /$1 gives same error.

cor - 26.04.06 2:39 pm

Well, stu, if two perfectly good rules throw your web server into a spin, clearly the trouble is elsewhere. Really, mod_rewrite doesn't get any more basic than this! Check the rest of your .htaccess. If that's fine, mail your web hosting company and ask why even simple redirects don't work.

Paresh Parihar, then leave it commented! Most likely your server configuration is set higher up (in .httpd.conf, by the admins), and certain overrides aren't allowed. Or something else!

With mod_rewrite, as with many other things, when it works, you stop tweaking!

Lou, best of luck with that! I've not played with redirecting between ssl and non-ssl, so anything you come up with, tricks or whatever, will be useful, for sure. If anything above inspires a solution, all the better.

But if you do find yourself banging your head against a wall, bang it against mine, instead. Most things are doable, we could probably figure it out.

;o) Cor

stu - 26.04.06 5:21 pm

My full .htaccess file is:

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^www\.domain\.com [nc]
rewriterule ^(.*)$$1 [r=301,nc]
RewriteRule ^index.php$ [nc,r]

With the last line comes this error: "The page isn't redirecting properly - Firefox has detected that the server is redirecting the request for this address in a way that will never complete."

I'll contact my host if you confirm that it's not my code that is causes this.

cor - 26.04.06 10:59 pm

stu, smiley for :lol: No wonder Firefox is giving you an error!

That's what we call an "infinite loop". Anyway, you don't need the last line, just delete it.

If you really must have index.php redirected back to the plain TDL , then first, realize that you are doing two separate things here; the first ruleset removes the "www", the second redirects the "index.php" hits back to the plain TLD. They aren't connected, so I recommend you put a couple of linebreaks between these two sections!

To prevent browsers entering a loop, simply add rewritecond line for this second ruleset, like this..
RewriteCond %{REQUEST_URI} ^index.php [nc]
RewriteRule ^index.php$ [nc,r]

;o) Cor

DavidR - 27.04.06 3:28 am

Thanks for everything, you've been awesome.

I just have one concern - won't the following code (written by you, except I escaped one period you missed) break calls to other, valid subsomains of ? Like won't it take and make it read just

# corz
RewriteCond %{HTTP_HOST} !^davidr\.com [NC]
RewriteRule ^(.*)$$1 [R=301,NC]

I guess my full original request should've asked to redirect *.davidr.(com|net|org) to either if the asterick is www, or else to * if the asterick stands for something other than www. I don't even know if this kind of complication is possible in regexp w/out multiple lines.

cor - 27.04.06 6:34 pm

Ahhhhhhhhh! I see!

Yes, Davidr, it would. Like I said, that one will redirect absolutely everything that isn't exactly "" (the dot doesn't need to be escaped, "." == "any character", so I often leave them unescaped in places where it could only be a dot).

There's always more than one way to skin a cat, but if you want to use subdomains, you would probably be best to break this up into two section - as I was just explaining to Stu. First the "www" thing..
RewriteCond %{http_host} ^www [nc]
RewriteRule ^(.*)$ http://davidr/$1 [r=301,nc]
That's probably the best way to deal with that, seeing as you have so many domains. Your subdomains won't get caught with that, but any request beginning www will be sent to Then we deal with the other domains..
RewriteCond %{http_host} ^(.*)davidr.(org|net) [nc]
RewriteRule ^(.*)$ http://%1davidr/$1 [r=301,nc]
These are just off the top of my head, but should work. Yes, it's possible to bundle both sections together, but why create confusion? This is easier to understand, and importantly, understand six months later!

have fun!

;o) Cor

manny - 28.04.06 1:11 pm

Hello. Can you help me make my urls that look like this:

look something like this:

and for categories with 2 or more words:


cor - 28.04.06 6:07 pm

manny, I already have! see above!

If your rules aren't working, show us the code, and I could help to fix them. If you'd like me to just do it for you, simply deposit £100 in my PayPal account!

;o) Cor

Matt - 29.04.06 10:16 am

Can you help me with a sub-domain rewrite?

This is my current .htaccess file

Options +FollowSymlinks

RewriteEngine on

#Redirect http://* to*
rewritecond %{http_host} !^www\.domain\.com
rewritecond %{http_host} !^domain\.com [nc]
rewriterule ^(.*)$$1 [r=301,nc]

This works fine, but what I'd like to do is keep the sub-domain showing in the browser's address bar, i.e.
rather than

I think the rewrite rule should be

rewriterule ^(.*)$ http://$$1 [r=301,nc]
as I have my DNS set to redirect * to my domain, but all that happens is I get a page not found error. Could it be that the DNS mapping is via CNAME rather than via A?

I'd go ahead and try this, but the server is down atm and I can't try it directly!


Dennis - 29.04.06 1:06 pm

Hi cor,

can you help me create a rule to deny all "connect" requests. In the rule i sent you it does not seem to be working, they get a 403 from the denied list, I would like apache to drop the request without processing request.

thank you

zissakos - 29.04.06 1:58 pm


thanks for the great article!

I have a problem that (I think) hasn't been mentioned yet:

Rewriting works fine and the desired page is loaded, but: the images and links in the resulting page are broken. No images are shown and the links dont't work, because the script seems to think it's inside "article/" but of course it is not.

What is wrong?

My .htaccess is:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^article/([0-9]+)$ showarticle.php?ID=$1

=> I want people to use
instead of

Take a look on your own here

cor - 30.04.06 1:28 am

No, Matt, don't do that rule! Bad things will happen. All you need to do is remove the "r-301" from your flags. TADA!

Dennis, I don't know what you mean by the "deny list", but the "- [f]" combination is supposed to give them a 403, that's as good as it gets; unless you want to direct them to or something. You can't tell apache to just "do nothing", as far as I know. It lives to serve!

Of course, if you have a big ole 403 page with fancy graphics and oodles of text, well, that kinda defeats the purpose, doesn't it. Ensure you setup a very basic 403, a single word perhaps "bye!"..
ErrorDocument 403 "bye!
Yes, the single double-quote is intentional. The absolute least you can do is..
ErrorDocument 403 "
So they get nothing a blank page. The connection wasn't "dropped", as such, but it's near-as-dammit.

Anyway, clearly you are becoming completely obsessed by all this hot-linking stuff; why not just get a bigger hosting package? smiley for :lol:

By the way, my own new hot-link protection method is working extremely well1, there are "" adverts all over the place these days! The great thing about hot-linked images is that generally the webmaster (the guy who actually nicked it) thinks everything is fine and dandy, because he is seeing the image from his cache (cache being the bane of .htaccess tweakers everywhere).

Sometimes it can take weeks for him to realize that he has been advertising the org, and their evil hot-linking plan has been foiled, that's when it hasn't scrolled off the page already. My current favourite hot-link site has two big adverts in their forum posting form, right there amongst the smilies. You just can't pay for that kind of coverage! smiley for :lol:

zissakos, erm, gimme a sec, I know this one!

This is nothing to do with .htaccess, well, not much. I believe we did cover this, but it would be a real scroll to find. Essentially, it's the links themselves.

Note how your main logo works; if you look at the link you will see that it is "absolutely" linked, that is, it starts "/", and tells the browser that the image location is relative to site ROOT. The other links will be linked "relatively" (I haven't actually looked at the source, but they will be), ie, they will *not* begin /, but instead be ../yadda/img/some.gif or img/some.gif or whatever.

Because you are doing an invisible (background) rewrite (no "r" flag) the browser really believes that it is inside /article/ so when it sees the relative image link (say, img/some.gif), it looks for /article/img/some.gif

Does that make sense?
Basically, you have two choices..

1) use the "r" flag, like this.. [r] probably a bad idea in your case, as you are trying to NOT show the *real* path.

2) re-link your images.

Option 2 is the best bet, but may mean no small amount of work. If the links are generated, there may be a way to do it very simply. As I mentioned above, my own CMS can switch back and forth with a single checkbox, but that sort of stuff needs to be coded into the back-end.

If they are not generated, then either, a) forget the cute new rewrite altogether, or b) get cracking in your text editor!

for now..

;o) Cor

an image
1. come to think of it, it was probably on page one I mentioned this, but here's how it works. Instead of a 403, I send them a cute image that simply reads "".. So, whenever someone hot-links, they do free advertising for me! hot-link away! As mentioned above, because of the "cache effect", these adverts usually slip right past the webmaster doing the hot-linking, sometimes permanently.

Dennis - 30.04.06 3:05 am

Thanks cor,

what I meant was I am seeing this in my log: - - 28/Apr/2006:17:59:37 -0400 "CONNECT HTTP/1.1" 403 202

the 403 is fine but I dont know if the 403 is coming from my "deny from" or from:

RewriteRule .*$ - F

I thought the RewriteCond would just drop all "connect" requests without processing and providing a 403.

Dennis - 30.04.06 3:22 am

cor, sorry for a double post but wanted to add this from the log, its kind of like being taunted, - - 29/Apr/2006:17:10:44 -0400 "GET / for :) HTTP/1.1" 400 226,

now dont get me wrong I don't care if they get 400 errors, but it seems I've been targeted it began with hotlinking, but since I solved that problem, they have started DOS attacks, and the "connect requests" from anonymous proxies is my new problem of the week. I had a 15MB log file of connect requests, from different ip's changing every 3 seconds. 80% of the ips originated from China and 20% from the US. They brought apache to a crawl and was hoping first: is my connect rule correct?, and second: is there a better one for my dilemma?


cor - 01.05.06 6:39 am

Hmm. If it were me I'd redirect all CONNECT requests to a php handler. The php handler then takes the IP address and automatically adds it to the list of denied IP's. If I were feeling fruity, I'd setup a database (flat-file, of course) to have them drop off again after a week or so.

Apache can't just not process, that goes against its nature. Only by processing can it know how to process the request, or not to. The least it can do is a blank 403.

The answer to your first question is whichever comes first. Both produce exactly the same result, a 403. If you use the 403 I put in my last post (a totally blank response) these requests aren't really a problem, they take almost no time to process, and it would take zillions of such hits to pose a serious DOS attack.

That just leaves the logging. Why not flag those requests with some sort of environment variable, and then add that to your logging directive (really, this is stuff for page one)..


And then in your logging directive..

CustomLog logs/access_log env=!go-away

Of course, you need access to the httpd.conf/virtual host setup for logging directives, so you might have to ask your admins to do this. If that's not possible, tell your log viewing software to ignore it, if possible (analog, whatever). Or if you just want to save the bandwidth and time in downloading the logs, maybe run some sed script on them first.

But at the end of the day, if all you actually send to the clients is nothing at all - a blank page..
ErrorDocument 403 "
it shouldn't become a major issue. Annoying, yes, like the many-MegaBytes-a-day of almost-spam that doesn't fill the comment pages, thankfully, but does waste a tremendous amount of bandwidth; life is too short to worry about these things.

Basically, unless you have access to the ipchains (erm, firewall) settings on the server or its gateway, sending a blank page is the best (read: least) you can do.

for now..

;o) Cor

ps.. have you considered <LimitExcept>?

cor - 01.05.06 6:46 am

Of course, you may wish to pass these requests to a php handler, one designed to DOS-the-fuck out of whoever sent the request, or worse.

I'm not saying that's smart, or clever, or condoning this cource of action in any way; it would likely get you booted from your web host, for starters, possibly thrown in jail, who knows. Do spammers prosecute? smiley for :lol:

But on a home server, with a sympathetic ISP, it might be fun. smiley for :evil:

Of course, if it's a home server, your black ice isn't restricted to php. smiley for ;)

;o) Cor

Dennis - 01.05.06 12:01 pm

Understood, thanks again!

Jan - 01.05.06 11:17 pm

Does the .htaccess file have any influence on the way a bot sees a robots.txt file?

It seems like googlebot can't reach my robots.txt, it keeps getting a 5xx error.

My .htaccess file looks like this:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !\.(jpg|jpeg|gif|png|css|js|pl|txt|xml)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php

I have no idea what this do, but is it making trouble??

cor - 02.05.06 12:16 am

Jan, remove "|txt" from the RewriteCond, and google will once again be able to access the robots.txt file.

In fact, it's probably best to remove the whole lot (comment it out, by putting "#" at the start of each line) and get a real 404 page!


;o) Cor

DragonFlyEye - 02.05.06 3:57 am

Hey cor, no posts in a while, not sure if you will even find me, but this tutorial is a big help! One thing, though: I am wondering if there are any particular security risks in rewriting URLs from static to non-static extensions? Meaning a URL that looks like being rewritten as I've seen other sites that say there is, such as this one:

Hoping for an opinion on this before I go ahead and do it. Blogging software rewrites URLs as a regular function, but they don't usually go from .htm to .php, so I'm leery about doing this.

Thanks again for the great tutorial!

cor - 02.05.06 5:09 am

Hey DragonFlyEye, that's not the same thing!

That thread is not about rewriting URL's it's about fooling Apache into parsing html files as php code (more .htaccess page one stuff), aka. forcing a new "handler", and yes, there are certain vulnerabilities in doing this. I don't do it much at all, not because of vulnerabilities, it's usually just messy, or lazy.

Here at the org, .blog files are parsed as php; in case anyone were to load them directly, they would see HTML formatting as opposed to the plain text. There's nothing insecure about that. The trouble with setting the .htm or .html extensions to be parsed with php is that web applications often produce files with these extensions, and if their content isn't known, parsing those files is risky.

There isn't a risk parsing .htm or .html as php so long as it's only done in specific folders containing known, non-user files. ie. not globally, which would be silly. By non-user files I mean files where guests couldn't possibly put arbitrary data. Request logs are a prime example.

On this page, we generally do the opposite, that is, redirect away from the .htm extension to a real document ending .php, so, if someone requests a file called page.htm, even if it exists, they are redirected to page.php.

In most areas of the org, it's simply not possible to load a file with an .htm or .html extension, though there are hundreds. The data for this very page is in a file called "htaccess2.htm", but you can't access it directly, it is "included".

Two different thing, see!
Hopefully this helps you make a good choice.

;o) Cor

DragonFlyEye - 02.05.06 12:50 pm

Ah! I see! That's why I asked, so I could get good advice. Thanks so much!

DragonFlyEye - 03.05.06 3:45 am


Perhaps I'm just missing something here, but my .htaccess file is giving me a 500 error. Mind you, I already have an .htaccess file on the root of the server that looks like this:

# BEGIN DragonFlyEye

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [l]

# END DragonFlyEye

There is a subdirectory called "vblog," and I would like to push any requests for, say, "/vblog/thevideo.htm" to "/vblog/vblog.php?yt=thevideo" and this is where I'm getting my 500 error. The .htaccess file for the /vblog directory is as follows:
Options +FollowSymlinks
RewriteEngine on
RewriteRule (.+).htm vblog.php?yt=$1 [nc]
Grrr! What am I doing wrong? Thanks again for the help!smiley for :cool:

cor - 03.05.06 8:05 pm

The top-level rule is a bit OTT, but it's your server. Plenty spare CPU and memory, I hope!

And the next rule looks fine. There's a slim chance that Options +FollowSymlinks is bringing up the 500 error, on rare servers, overrides have been disabled, and it can cause errors, very rare, though.

Try removing it.

;o) Cor

John - 05.05.06 9:06 pm

The code you have for lose the WWW is not compatible with most of the code generated by password protection scripts.

IE: If you put
Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]

in an .htaccess file in the public_html directory and below that directory you have a password protected directory called blabla with the following code in a .htaccess file
AuthType Basic
AuthName "Restricted Area"
AuthUserFile "/home/corz/.htpasswds/somewhere/passwd"
require valid-user

and you navigate your browser to

everything works as expected, but if you navigate your browser to

then you end up with a 404 page instead of being redirected to as expected.

Can anything be done to make this compatible with .htaccess password protected directories?

-- John

cor - 05.05.06 11:56 pm

In response to your first statement: neither is the twenty-first century, then. Nor mod_rewrite! And the phrase "code generated by password protection scripts" just makes me shudder. smiley for :eek:

I must assume you are using "basic auth", and so I must strongly recommend: DON'T! There are so many better ways to authenticate users these days; throwing the password over the wire in plain text hundreds of times a minute isn't very clever. We demonstrate the technique, as a learning example, but no one sensible actually authenticates with it!

And the "lose the www" technique is meant to catch the odd stray request from new (read: unaware) users. It's certainly not designed for requests from users familiar enough with your site to need to login!

Having said all that, if, for some crazy reason you are locked into an antique server; maybe an ageing boss, or something; and your error documents are kept in /err/ and you put..
rewritecond %{request_uri} !^err
before the other RewriteCond lines, you will get your login dialog. Once authenticated, the rewrite rule will guide them to the www-less version.

As will every other node between user and server, in plain text, over and over again.

In short; TADA!

;o) Cor

John - 06.05.06 4:41 am

First I mistakenly said a 404 message it's actually a 401 message.

I'm not sure what you consider an antique server but this is a shared server running red hat 9 and cpanel.

I asked my host about the error logs and they replied.

The error logs for the domains are at root: /usr/local/apache/logs

You can view errors for your domain by pulling them up through cpanel, but they aren't kept locally in your web space in a directory such as "err"

So I asked if they could make a symbolic link from /home/myAccount/err to the relevant error log in /usr/local/apache/logs

their reply was
The error log is for all domains on the server. They aren't separate logs per domain.

Am I hosed or is their hope?

BTW I love your little penguin with the apache feather.

cor - 06.05.06 12:16 pm

John, I mistakenly forgot to mention that I knew you meant a 401 page. smiley for ;)

That's not an antique, so you have no excuse, get a better authentication system, make it a priority!

And who said anything about logs??? smiley for :eek:

I meant YOUR ERROR DOCUMENTS! aka "error pages", eg. "401.php", "404.html", or whatever. Any user can set those in .htaccess (see page one of these articles, and my musing about the empty 403 page, above), this has nothing to do with your logs, though while I'm here I have to say I'd run a mile, and fast, from any host who didn't give me access to my own logs1. How are you supposed to ... (insert a dozen essential webmaster tasks) ? smiley for :eek:

So, setup custom error handlers, 401, 403, 404, etc..

ErrorDocument 401 /blabla/401.php

And at the start of your rules, put..

rewritecond %{request_uri} !^blabla

And you're done.

;o) Cor

ps.. there's a few versions of the penguin server image in the archives, here.. /public/images/powered by penguins/, photoshop document, that sort of thing. Feel free to use it for your own Linux promotional needs!

They just mean that the logs are at first created in one big directory. If it's CPanel, you probably do have access to your own logs; check out the "Raw Access Logs" option.

John - 07.05.06 6:35 am

Thanks for the response cor.
I misunderstood part of your previous response but think I understand better now and will delve into it more tomorrow.

Do you have any suggestions for better authentication system?

I also thank you for the offer to use the graphic.

I and a group of 3 others are working together to bring an older, but at one time very good bbs back to prominence.
It's a PERL script that runs on both nix and doze. I myself will have absolutely nothing to do with setting it up on a doze server though. Too hard to communicate with doze admins (who all know everything or think they do) on how to get the right permissions set on directories.

Obviously your graphic could only support Linux servers though. Just wanted to make that clear before using the graphic and hope the offer is still open.
An alternative idea I got (though graphics are not my forte) was to get someone to do a similar penguin wearing the apache feather in an indian headband.

-- John

cor - 07.05.06 2:56 pm

For authentication, if very much depends on the web-side code you are using. I use php, so I cooked up something for that, but perl is outside my ken, so I have no idea what's available.

If it's a bbs, doesn't it come with its own admin structure?? Surely!

If not, for a perl coder, it shouldn't be too hard to knock up something. A user database, a "session" to work with, coupled with pajamas-like client-side hashing, bingo! Of course, there's always SSL, and "https://...", if you can afford a certificate, or don't mind "dodgy certificate warning" at your logins.

For "root" access, to change files, directories, etc., you want to use ssh, sftp, scp, etc. Though if it's running on a windoze server, most of these things are not available without first being separately installed. Does it have to run on a Windoze box? Why not just keep the servers strictly *nix?

As for the graphic, really, I retain no hold over the work, do what you like with it! It would be silly to use it on a windows-served site, though, agreed.

for now..

;o) Cor

ps.. I make icons and "wee graphics" as a form of occasional meditation (how all the graphics here at the org got made), if you like, I can have a crack at the headband thing some time; it's a nice idea. I wish I'd thought of it! smiley for :ken:

John - 07.05.06 3:39 pm

Up until recently the BBS was shareware. The original author no longer has the time to update and support it.
People who have purchased it in the past have it installed and running on both nix and doze servers.

If you'd like to take a shot at the headband graphic that would be great, but I must say that at this time our little group has no funds to pay anyone with.

-- John

cor - 07.05.06 4:32 pm

I seeee!
So you will be continuing the development, excellent!

If you are distributing this thing, folk will start asking for a serious authentication fairly soon; "basic" auth and its counterparts simply don't cut it these days. You might want to take a look at pajamas (link from last post), with perl's string handling, it wouldn't be too tricky to create something like that. Tie it into your user database and you're done (yeah, like it'll be that easy! hahah)

As for the graphic, definitely no charge either way. If I made it, I'd be putting it up here for all penguin-lovers to use, us included!

Good luck with the perl!1

;o) Cor

I don't believe in luck, but when I look at perl scripts, I just know that it's a factor!

adil_rauf - 09.05.06 6:46 am


i have a problem in which i have to make subdomains using just folder creation method using php and then whenever the user enters the foldername as subdomain ie it gets to folder named 'test' and shows further traversal of site with pages like aboutus.php etc as etc

please reply i am in need thanks i advance

Frank - 09.05.06 9:52 am

Thanks! Never understood much of rewriting. Now I think I begin to grasp the basics (read many tutorials, but only yours makes any sense to me). I'll be trying my own stuff soon, now that I understand it.

Thanks! I think I'll check out your site for more useful information smiley for :D

NiteOwl - 09.05.06 7:15 pm

Nice article
Being a newbie with Apache and just learning PHP I have a dilema that I am hoping to find a better direction for and the info presented here might point a direction but not the specifics.

I want to redirect all requests to sub folders of a web site so that I can process them through my own template page.
For instance a request to mypage/subfolder/somefile.htm should get redirected to mypage/index.php
The index.php page is used to load the requested page within a templated design keeping the site consistent.
Content pages are created by various individuals at a local middle school so I cannot rely on them following special formatting rules for the page and it's links.

I setup a .htaccess file to deny access to all sub folders then trapped the 403 error and executed error.php which evaluates the requested URL and then redirects to index.php?requestedpage.htm

This works except for one thing. Each sub folder has it's own Images folder and though the primary page loads the images cannot load because access to them is stopped by the htaccess file.

I could use LOTS of htaccess files to start/stop denying access but it seems kludgy at best and the content providers may create new folders on their own which would never be able to get access without a local htaccess file to allow it again.

Is there a better way to do this? It seems like rewriterule might do it but I do not understand it well enough. All the examples deal with specifying a specific filename and in my case I want to just saying any request below this path needs to be redirected and I need to get the requested path so I can parse it out to determine where it should point.


Koki - 10.05.06 2:42 am

Hello Cor,

I really need some help here please. I keep reading but it seems the rewrite rule I need is just too hard for me to figure it out by my self.

What I have as code on my sites is this:

and because is a big, ugly SE unfriendly URL I would like to change it a this: ( 40540 is unique ID, all the links have one) or or something like that.

Now let me explain this:
The out.php is part of a counting/trade script so all the links have to pass through it.
The variable "url: can be like this ( examples:
and this that the urls are always different makes it difficult for me to figure it out how to rewrite.
The variable "link=text" can be changed to "link=40540" that will be the unique ID for that particular link if this is from some use to making the rewrite rule....what else.....ah yes, I am on 1.3.34 Apache core.
Your help is greatly appreciated!


cor - 14.05.06 10:26 am

heh, it's always guaranteed that if I'm away for a few days, I come back to a nice wee pile of .htaccess "challenges" smiley for :cool:

adil_rauf, yours is the biggest challenge, because I haven't a clue what your issue is. After many reads, it seems as if you want me to code some php for you. smiley for :eek: If that's true, feel free to get in touch by the usual methods!

Cheers, Frank! That's the main plan! As time permits, I sprinkle my magic learning dust on many interesting subjects, because quite frankly, I know everything!1 smiley for :lol: Check back regularly!

NiteOwl, I agree, planting .htaccess files all over the place isn't the way to deal with this. Certainly not when content comes from these sources. You probably want to deal with this one time, in the root, essentially capturing everything, and passing it to one Master php handler. This simple rule..
RewriteRule ^(.*)$ /index.php?mypath=$1 [l,qsa]
will pass ALL requests to a php handler in the root of the site (index.php, though it could be any file, anywhere), and passes the entire query string to the handler as a variable "mypath" (I would avoid using "path" on its own, being a regularly "reserved" word). An other variables in the original request are also passed through ([qsa])

Once inside php, your options are wide open, and I'd definitely recommend handling these complex path manipulations inside php rather than .htaccess; as well as the considerable performance advantages, php has superior string handling capabilities, so you can easily manipulate links, image locations, etc, before spitting out the page. There was another good reason that I've forgotten since reading your post! smiley for :blank:

Note, there is no "r" in the flags, so it's a completely background rewrite. The user's original URL is still in the title bar, so you will want to decide what that will be before you begin. As it's completely fictional, it can be as "cool" as you like.

I really must get a beta of the new corzblog code up asap (I had to postpone development of the latest version at around 80% completion, but it works brilliantly) if only to demonstrate how I do the permalinks. One simple rewrite rule passing all the necessary information to php, and php doing clever stuff thereafter. With the right code, you can create a truly flexible system thats easy to maintain (always a level-one priority!) and easy to expand; I can switch from regular to "short" links with no more than the click of a checkbox.

Koki, first, understand that long, variable-filled links are NOT search engine or SEO unfriendly2, but most definitely IS!

The second thing you have to realise is that these are OUTBOUND links, so they have no impact on your SEO, only that of the sites the links point TO. The link text can be whatever you like, the visible part, and you could perhaps work on that, but it makes no difference what the actual links are.

Essentially, this is a waste of your time and effort, and I'd recommed you forget it, go do something productive instead, like fix your page titles, or whatever.

Okay, I admit, it could affect your SEO, but probably not to anything like the degree you imagine. If you really want to make any impact at all with these outward links, you need rewrite the links not to codes and digits, but to long descriptive plain english titles. You could even use variables to HELP your SEO efforts. This link..

out.php?link=" is actually quite a good outward link, SEO-wise. So long as the linl pointed to a relevant site with reasonable PR, etc.

But the links all being different makes this a huge task, with very little bang for your bucks, so I say again, FORGET IT! You could impact your SEO efforts in infinitely better ways for *much* less effort.

I'm serious about the page titles.

;o) Cor

  1. Well, between me and my brother, we know everything smiley for :ken:
  2. that automatic router scripting thing I put up last week is already top of google over 6 million other pages for a variety of search queries, so I ken fit I'm talking about!

Koki - 15.05.06 7:13 am

Thansk for the reply Cor. I thought that this is gonna be some more complex task. Actually the idea behind this rewrite was to make all those links to appear as content (subpages) that makes part of my site. As they say "... content is king....."
Anyway, thanks again,

cor - 15.05.06 9:39 am

Koki, yes, content is king!

And when the user, google, whatever, clicks the link, it takes them off-site, to someone else's content.

So, no way you can fool google, or anyone into thinking those pages are part of your site (and therefore bestow PR on you) unless you use some kind of handler to grab the page, parse it, and represent as an actual page on your site.

And then it's no longer an outward link, but a rip-off!

I recommend, spend the time making some unique content of your own. One paragraph of good, unique text, is better than a dozen pages nicked from elsewhere, PR-wise.

Google sees all!

;o) Cor

NiteOwl - 15.05.06 10:25 pm

Thanks for the info, I will give it a try.
A universal redirect is kind of what I was hoping for up front but others pointed me in other directions.

I have tried a variety of rules and can manage to pull back the originally requested path and any querystring parameters but I cannot retrieve anchor tags.

This is my latest attempt:

RewriteRule \.(html|htm|php|php4|php5)$ /jfk/urltest.php?&url=%{REQUEST_URI}&%{QUERY_STRING} [R,NE]

I have searched around for info on retrieving anchor tags once intercepted via an htaccess file but nothing I have read has been encouraging. The only reason I have not given up is that none of the people saying it could not be done seemed to truly know for certain.

Also, when I use a RewriteRule like above, the anchor tag get's passed along so that when the urltest.php page loads the address line still includes the anchor (in Firefox but not IE) though the url has been drastically altered which makes me think the text must have reached the server at some point so there should be a way to retrieve it.

I will play around with the rule above and see what I can get it to do. I am newb with Apache so...

As for the end-result URL, I just need to keep two parameters in there when finished as flags for the navigation system. I will be handling some of it server-side but want to keep bookmarkable addresses without a huge amount of translation and the variables tell the top and mid navigation controls how to set themselves and which folder group to work out of.
Learning the ins/outs of Apache and PHP at the same time is really a hard way to go about an already complex project. smiley for :)

justmakeitup - 16.05.06 6:48 am


I have a weird problem.

I have been doing some mod-rewriting to create subdomains on the fly. In essence my code works. I had the hosting provider enable wildards and I added some .htaccess code.

Now here is what is happening...

The code does create a virtual subdomain
RewriteEngine On
RewriteRule ^.htaccess$ - [F]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^([^.]+)$
RewriteRule ^$ /%1/$1 [L]

I know I miss REQUEST_URI in thios code but no matter what I did something didn't work.

What I get once there is a subdomain is the following.

turns into

and this is fine...

BUT when I click on a link within the page it is supposed to take me to: 

however, it does not. Then out of curiosity I tried:

naturaly it worked... :S

I had a fellow programer who is much more savy in htaccess programming look at it and he said that my version of apache doesn't get the backtrail to accomplish what i want.

He came up with this:
RewriteEngine On 

RewriteRule ^.htaccess$ - [F] 

RewriteCond %{HTTP_HOST} !^(www.)?DOMAIN$ [NC] 
RewriteCond %{HTTP_HOST} ^([^.]+).DOMAIN$ [NC] 
RewriteCond %1---%{REQUEST_URI} !^(.+)---/1(/.*)?$ 
RewriteRule .* /%1%{REQUEST_URI} [QSA,L]

But no luck.

How could I accomplish having links on my subdomain actualy stay in the sudomain?

This on the other hand
RewriteEngine On
RewriteRule ^.htaccess$ - [F]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^([^.]+)$
RewriteRule ^$ /%1 [L]

works,, but the absence of the / in the end of the rewriterule only allows for pointing links to the subfolder on the main domain :(

Help ???

Neil - 18.05.06 11:18 pm

Well, I'm a beginner at this and was feeling very pleased that I'd managed to set up a .htaccess file to direct mobile users to a separate version of my home page "mindex.xhtml" instead of "index.html".

RewriteEngine on
DirectoryIndex index.html
RewriteCond %{HTTP_USER_AGENT} "Windows CE" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "Palm" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "Nokia" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "BlackBerry" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "MOT" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "LGE" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "SIE" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "Sony" [nc,or]
RewriteCond %{HTTP_USER_AGENT} "SAMSUNG" [nc,or]
RewriteRule ^index\.html /mindex.xhtml [r,l]
ErrorDocument 404 /404.shtml

It works OK when going to the root of the site firefox and IE go to "index.html" and my phones go to "mindex.xhtml", but if I follow a link from any of my pages with any browser to "index.html" I'm sent to "mindex.xhtml"smiley for :erm:
Obviously for some reason the RewriteRule is working without the RewriteCond operating, but why?

Any ideas?


Juergen - 22.05.06 9:25 pm


I just want to do replace a .gif file with a php script.

rewriterule ^test\.gif$

This works fine, but I want to avoid that test.php is shown in the adress bar instead of test.gif. Any ideas ?

cor - 25.05.06 11:27 am


Okay, like fourth try at getting up-to-date here smiley for :aargh: Gonna go for a short version. smiley for :roll:

NiteOwl, good luck with that! (though I don't believe in luck, you get my drift). It's good to get those Apache skills while you can, and even better if you can do it on someone else's expense account!

If you get stuck with any more specifics, jump back here (though don't expect a same-day, I'm snowed under!)

justmakeitup, managing access to *real* subdomains with .htaccess is simple and painless. Creating them with .htaccess rarely is. This (essentially your first example, with some minor edits)..
RewriteEngine On
RewriteRule ^.htaccess$ - [f]
RewriteCond %{HTTP_HOST} !^
RewriteCond %{HTTP_HOST} ^([^.]+)
RewriteRule ^$ /%1 [l]
should work okay. Pay careful attention to the bits I removed.

Neil, try removing the last "or". smiley for ;)

And finally (w00t!).. Juergen, looks like in your real rewrite rule you are using the [r] flag. Answer: don't! If not, definitely get back here!


;o) Cor

Neil - 26.05.06 10:37 am

Now that makes sense smiley for :D
I really must start thinking some time.
Thanks very much.

cor - 26.05.06 2:39 pm

No problem Neil, always glad to help, especially folk improving accessibility for mobile devices.

You also might want to consider doing something like this..
RewriteCond %{HTTP_USER_AGENT} SIE|LGE|MOT|BlackBerry|Nokia|Palm|Windows\ CE|SAMSUNG [nc]
which I was gonna set as an "exercise", until I realized that figuring out how to get the space in "Windows CE" would probably just give you a headache. (you could also use "." instead of "\ ", meaning "any character". Using quotes would most likely give an error.)


;o) Cor

Kjetil B Moe - 26.05.06 5:42 pm

Hi, great site! I makes it much easier to understand the htaccess magic. I have a problem here though:

I am currently having a virtual domain at lets say The site is also available at the address, but the cms-system requires one address and returns errors when trying to use this url. I would like all requests to to be redirected to the Apaches redirect will not work here, and I've tried with the following

Options +FollowSymLinks
RewriteEngine On
rewritecond %{http_host} ^ [nc]
rewriterule ^/mysite/(.*)$$1 [r=301,nc]

Could you please give me a hint here? I'm stuck.


Bumble Bee Tuna - 30.05.06 8:46 am

We both need help.

The google translator link you demonstrate only works with computers in English. My computer is from the USA and I now live in Germany. Therefore it works great for me, but when I would tell a local to go to my website and they can just hit the German translation link, it never worked. I tested this theory at a dozen different internet cafes. It makes complete sense too for the reason of when you access the Google search engine from your laptop in different country, your laptop still displays results in your native language. But a local internet cafe will have them in their language.

That was your help, now mine.

I'd like to take a website like with the projects at the bottom, and not have the search engines crawl the project links at the bottom as I believe it's too many links leaving the page for SEO purposes. But at the same time, I like the page updating regularly with related content so that the search engines constantly come back for updates without needing to specify a return time in meta. And if it's not used for this purpose right now, maybe someone else could find it useful for promoting another website from their indexed one that they don't want search engines indexing but still want their visitors to check it out. How could we do this in .HTACCESS?

I've been referencing your website for several months now and just love it.

- Bumble Bee Tuna!

cor - 30.05.06 10:02 am

Kjetil B Moe , my first hint is remove the "=301" until you get it working! See the notes in the main article about this; it's much more important than most people imagine, I imagine.

Next, lose the "www". I mean drop it altogether. If you want to add it back later, mindfully, cool.

Now that rule. Taking into account all the above, you probably only need to make one small change, that is, remove the "/"..
rewriterule ^mysite/(.*)$$1 [r=301,nc]

Bumble Bee Tuna! Glad you finally got around to adding some text on-site!

Yes, the Google links aren't exactly perfect. If I were being kind on myself; something I certainly need to do more; I would say that it was a "proof of concept", and leave it at that! smiley for :lol: Actually, a little bit of tweaking with the links, and they could probably do what you want, if you want something else, that is.

Now to your links..

Firstly, unless you have a *LOT* of links, I mean thousands, it's unlikely to have a negative impact on your SEO efforts. Navigate to /links.php here at the org; that page does have thousands (probably), and Google doesn't mind at all; gives my site a thorough indexing, thank you.

I don't entirely understand the next bit, about someone else using something. Using what? The more I read it, the more confusing it gets! Anyways, unless you specify a return time (and I recommend that you do) then search engines will come back more or less as frequently as you update the page.

Most search engines like pages that are "active", but not too active. Ideally you want some fixed content at the top (I mean the first paragraphs) and then something moving underneath, like this page is, or indeed,, except done better.

Frankly, I wouldn't bother. You don't want to start messing with cloaking, or any other dodgy "SEO Techniques", hiding content from google, false redirects and shit; it's just asking for trouble.

Feel free to come back and explain..
And if it's not used for this purpose right now, maybe someone else could find it useful for promoting another website from their indexed one that they don't want search engines indexing but still want their visitors to check it out. How could we do this in .HTACCESS?


;o) Cor

Bumble Bee Tuna - 30.05.06 12:38 pm

Feel free to come back and explain..

And if it's not used for this purpose right now, maybe someone else could find it useful for promoting another website from their indexed one that they don't want search engines indexing but still want their visitors to check it out. How could we do this in .HTACCESS?

What I mean by this is say you take and you are working on a new page for it. like

you want your visitors to perhaps give feedback or input as to what you should be adding to it. besides providing text on the referring page saying "enter" to get a sneak preview. you'd rather have a hyperlink but not have it indexed by robots/crawlers until it's finished - is this possible?

this is what I was inquiring about and I would not think it dodgy unless you are selling PR links from your site and people aren't getting the status they paid for. smiley for ;)

I could be wrong, but I'm pretty sure I've seen websites doing this.

cor - 30.05.06 1:12 pm

Ahhh.. I see what you mean. And it's an interesting idea; I often have pages that are in-progress and up on the live version. Google finds them all (via abovementioned links page) but I don't mind at all; it's fun to watch it climb the ranks. Why would you want to prevent google finding these pages?

As to the "solution", I'd add the page to my robots.txt file, which is designed for doing exactly this sort of thing. For starters, the syntax is a lot simpler than mod_rewrite!

;o) Cor

kai - 01.06.06 1:46 pm

hi cor, I'm back... from 15.02.06 smiley for :)

I now want to reverse my URL re-writes the OTHER way, and change: to,com_smf/Itemid,71/topic,751.0

-and-;topic=751.0 to,com_smf/Itemid,71/action,post/topic,751.0/num_replies,0

The latter rewrite is a bit challenging. If there is a number other than ".0" at the end, I would want to change:;topic=758.1 to,com_smf/Itemid,71/action,post/topic,758.0/num_replies,1

Are these changes possible with .htaccess?

Sean - 02.06.06 9:45 pm

Hi Cor,

Great site! I'm learning. smiley for :)

I was wondering if I could get your specific optinion to a topic which relates to one of yours you touched upon above. I am re-working a site and am concerned about inboud links and search engines pointing to the old pages once I change them. Instead of having a .htaccess line for each permanent redirect page, I was hoping for a generic solution that will apply to all of them. Here are the 2 format specifics...

The Site is

Currently the pages show up like this in the URL address bar as... etc.

they will get changed to this format/convention...

Is there a generic permanent redirect option I can use in the .htaccess file which will work for them all? Can you help me?

Thanks very much.


justme - 03.06.06 9:31 pm

I have rewriting to do 'subdomains to folders'. How can I add check that when there is no folder called subdomain it will go to instead of trying to go to folder that doesn't exist?

I'm using example above
RewriteEngine On
RewriteRule ^.htaccess$ - [f]
RewriteCond %{HTTP_HOST} !^
RewriteCond %{HTTP_HOST} ^([^.]+)
RewriteRule ^$ /%1/$1 [l]

There should be something like this
RewriteCond ^www\.domain\.com/%1 !-d
but can't figure it out.

tell me someone

cor - 05.06.06 7:51 am

kai, it's not quite reverse, more like the same but different, and it's easier than you think. We already covered how to capture variables. You could do something like..
RewriteCond %{QUERY_STRING} ^topic=(.+)\..$ [nc] 
and to only perform a particular rewrite when the last digit is zero, or not, simply add that to the rewritecond lines, either rolled into the above, or on it own .
RewriteCond %{QUERY_STRING} !.*0$ [nc]
or something like that.

You might just want to capture it, and use it as-is..
RewriteCond %{QUERY_STRING} ^topic=(.+)\.(.)$ [nc]

Sean, yes, same story as above (about 2 inches)..
RewriteCond %{QUERY_STRING} ^(.+)$ [nc]
now whatever was after the "?" in your original query will now be stored in "%1", so you can redirect with that.

It depends on the format of your other site links, but assuming they are all something.shtml like your examples, you could do..
RewriteCond %{QUERY_STRING} ^(.+)$ [nc] 
RewriteRule ^index.shtml /%1.htm [r,nc]

justme, the "-d" checks for the existence of a directory, NOT a URL path, or domain+directory, just the directory, so you only need to test "%1" on its own.

;o) Cor

hjb - 06.06.06 10:01 am


I am having problems with a long set of redirects.
The [L] command seems to have no effect is some cases.
.htaccess works from top to bottom yes?
So if a redirect is done with the [L] tag then everything below it should be ignored yes?
Strange because that doesn't seem to work here:

some code..
Options +FollowSymlinks
RewriteEngine on
DirectoryIndex index.php

#log out rule
RewriteRule ^logout/?$ /?logout=1

# redirect all view profile pages
RewriteRule ^profiles/([0-9]+)/? http://%{HTTP_HOST}/profiles/?user=$1 [QSA,L]

#no www!
RewriteCond %{HTTP_HOST} ^www\.example\.(hjb|com)$ [NC]
RewriteRule ^(.*)$ http://example.hjb/$1 [R]

# if no subdomain then do nothing
RewriteCond %{HTTP_HOST} ^example\.(hjb|com) [NC]
RewriteRule .* - [QSA,L]

# if we DO have a subdomain
RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.(hjb|com)$ [NC]

# ONE - redirect subdomains (with no other stuff) to ham
RewriteRule ^(index\.php)?$ /ham/?hamurl=%1 [L]

# other redirects
RewriteRule ^addwidget/(index\.php)?$ /ham/addwidget/?hamurl=%1 [L]
RewriteRule ^admin/delete/?$ /ham/admin/?delete=1&hamurl=%1 [L]
RewriteRule ^admin/cars/delete/([0-9]+)/?$ /ham/admin/cars/?delete=1&car_id=$1&hamurl=%1 [L]
RewriteRule ^admin/home/delete/([0-9]+)/?$ /ham/admin/trips/deletehome.php?hamurl=%1&trip_id=$1 [L]
RewriteRule ^admin/edit/([0-9]+/?)$ /ham/admin/edit/?hamurl=%1&car_id=$1 [L]
RewriteRule ^admin/?$ /ham/admin/?hamurl=%1 [L]
RewriteRule ^admin/([a-z]+)/?$ /ham/admin/$1/?hamurl=%1 [L]
RewriteRule ^admin/(.*)$ /ham/admin/$1?hamurl=%1 [L]

RewriteRule ^([_0-9a-zA-Z]+)/(index\.php)?$ /ham/cars/?hamurl=%1&carname=$1 [L]
It seems to be doing TWO even after ONE has been done?!
When I check hamurl and carname on the cars index page I am getting ham for the the value of hamurl and carname is null.

Why is TWO happening after ONE has been done?

Could it be anything to do with this being tested on localhost?


REGIX - 06.06.06 10:41 pm

Hey, cor, (or anyone smiley for :D ), can you send me a htaccess file that'll not display certain files, such as CSS or JS files? But, the scripts inside the server still need to access the files. Is there a way? smiley for :erm:


cor - 07.06.06 10:00 am

REGIX, htaccess only controls access for surfers, it has nothing to do with your server-side scripts access to those files. In other words, assuming the files' permissions are correct, scripts can always access the files, no matter what you put in your .htaccess file.

hjb, the [L] flag is supposed to prevent further rule processing IF the rule is successfully applied. I started at the bottom, working up, and first I see %1 being used, and I wonder, where is that supposed to come from? There's no rewritecond line before it, and therefore, no bracketed expression to match!

Back to the drawing board!

;o) Cor

REGIX - 07.06.06 11:49 am

Unfortunetly, my scripts don't get what is expected. See, I have a simple list of redirects, such as this:

Redirect ^.*\.css /index.php

It'll stop anyone from viewing the code directly, but the scripts are getting the redirected page as well, not the actual CSS file.

What I'm aiming for is no viewing the file, but my scripts can still access it. Is that possible?

hjb - 07.06.06 12:01 pm

I did indeed go back to the drawing board and now have a condition for every rule.

All is now working nicely.

cor - 07.06.06 12:21 pm

Good news, hjb!

REGIX, you misunderstand how this all works. Scripts don't use css files, browsers do. They are loaded directly by the browser. You can't redirect them, the browser needs to access them directly. It's not like a php "include", where the file is pulled in server-side. But it can be..

The only way around this (and why you would want to prevent someone downloading your css files is quite beyond me) is to use php (or similar) to inlcude the css file and spit it out as part of the page, inside style tags. But, the user still sees the css code, only not directly.

Bottom line, unless the browser has direct access to the css code, in one form or another, the page will have no styles.

You could perhaps use hot-linking code to prevent access from browsers that aren't loading the page associated with the stylesheet, but even that isn't foolproof, not by any means.


;o) Cor

kai - 07.06.06 12:39 pm

hey cor, I am getting somewhere!

1. To redirect
# to

I did this:

RewriteCond %{QUERY_STRING} ^topic=(.+)\.(.)$ [nc]
RewriteRule ^forums/index.php /index.php?option=com_smf&Itemid=71&topic=%1.0 [r,l,nc]

2. To redirect
#;topic=786.2 to

I did this:

RewriteCond %{QUERY_STRING} ^action=post\;topic=(.+)\.(.+)$ [nc]
RewriteRule ^forums/index.php /index.php?option=com_smf&Itemid=71&topic=%1.0&action=post&num_replies=%2 [r,l,nc]

I have added the above 4 statements into my htaccess and it appears to be working, but wonder if you have any comments.

Thanks so much for your help! smiley for ;)

Sean - 08.06.06 1:26 am

Hi Cor,
Thanks..just a quick follow up if I may...

-Old Path-

I place this in the htaccess file...
Options +FollowSymlinks
Rewriteengine on
RewriteCond %{QUERY_STRING} ^(.+)$ [nc]
RewriteRule ^index.shtml /%1.htm [r,nc]

Now when I type this in the address bar the old page...

I get this in the address bar of the redirected page...

The new page does show up however what I want to show up as the new address in the address bar (which is the real new address) is this...

Advice please.

Also what do the search engines think the address of the page will be going forward?

Best Sean

pratik vanol - 08.06.06 6:58 am

hi, I m trying to redirect the URL.
suppose I will write in address , I want redirect it to

I am not able to understand how I write the .htaccess for this. where I put .htaccess file in public_html folder or subdomain's folder.....
plz help me..

CamihuVn - 08.06.06 7:11 am

Hi All
I have read about make htaccess
I want changer:
When i mouseover link at status Bar changer .vip
Thank so much....

cor - 08.06.06 11:43 am

Looks fine, Kai!

Sean, you mean, you want to remove the query string from the end of the URL? If so, simply add a "?" to the end of the rewrite rule..
RewriteRule ^index.shtml /%1.htm? [r,nc]
As for search engines; they will follow your redirections in exactly the same way as browsers.

pratik vanol, assuming the subdomain is correctly setup in your hosting/admin panel, then the rules go inside the subfolder.

CamihuVn, I can't help you with your code, unless I see your code. What have you tried?


;o) Cor

pratik vanol - 08.06.06 2:57 pm

I want to create througth programming. What can I do......
I want to create .htaccess file for that.
but dont know what write inside it.
url redirecting.

Sean - 08.06.06 9:59 pm

Hi Cor,

I get this in the address bar of the redirected page...

so I want to get rid of the query string AND the rest ( contactus ) so that it is just this...

Help! lol smiley for :)


justme - 09.06.06 7:37 am

"the "-d" checks for the existence of a directory, NOT a URL path, or domain+directory, just the directory, so you only need to test "%1" on its own."

Ok. So can you or anyone tell me what I have to exatly include in the following code, im rid of regexps+htaccess etc:o . My problem was how to point to if there is no subdomain folder in sub directory. Now when accessing random subdomain it is just trying to go to path that doesn't exist. Tell me this
RewriteEngine on 
RewriteRule ^.htaccess$ - [f]
RewriteCond %{HTTP_HOST} !^
RewriteCond %{HTTP_HOST} ^([^.]+)
RewriteRule ^$ /sub/%1/$1 [l]

cor - 09.06.06 4:18 pm

Sean, dude! I answered this already; add a question mark!

justme, first, I don't see how this is a problem. On what internet do people just enter random subdomain names into their browsers? Surely these come from links.

Anyways, when I said that the "-d" checks for the existence of the directory, I meant in the server's file system; you need to use a real path, for example..
rewriteCond %{HTTP_HOST} ([^\.]*)$
rewriteCond /home/sites/ -d
If you don't know the real path on your server, find out (a phpinfo() is useful here).

At the end of the day, I don't like the idea of rewriting arbitrary subdomains to possibly-existant folders, and if I were stuck using mod_rewrite to create my subdomains (which, thankfully, I am not), I'd create a single folder in the root for ALL my subdomains to live in, and then (incorporating the above folder existence check) do something like this..
rewriteCond %{REQUEST_URI} !^/subz
rewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.org
rewriteCond /home/sites/ -d
rewriteRule ^(.*)$ /subz/%1/$1 [l]
The folder being called "subz", and all the actual subdomains would live comfortably inside there.

Any requests to non-existant folders, say are redirected to the root version, i.e., while correct requests, for example, would be directed to the real file at /home/sites/, "yes" being one of our actual allowed subdomains.

Of course, I'd likely add a second wee set of rules to catch direct requests to those folders and redirect them to the proper subdomain, but I'll leave that as an fun exercise for you!

;o) Cor

ps.. if you use pre tags, you don't need to do that [[double square brackets]] thing, which turns regular bbcode tags into visible square brackets (i.e. fex them up).

Sean - 09.06.06 7:07 pm

Hi Cor,

Sorry about the last question, I thought the "?" was the query string. ;(

Anyway if you could just bare with me for one last question? I'm a newbie and this is really helpful so thank you.

The last question is this...

The new redirected path is now correct except that there is no "www" in the new path. For example this is showing up... instead of....

Also are these considered "Permanent redirects"?

Thanks so much.


justme - 09.06.06 10:02 pm

This one was correct, thanks for your help.
rewriteCond c:/progra~1/apache~1/apache2/htdocs/sub/%1 -d

justme - 12.06.06 9:08 pm

Well none of subdomain-to-folder rewritecodes have worked yetsmiley for :eek:

For example none of these have worked properly:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com?$
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com?$
RewriteRule ^$ /%1 [L]

This is doing: --> (WRONG)

One did 'forward' correctly but when accessing (test -fol inside sub -fol) it took me to (WRONG) but still was working, note that ONE slash. And if I was trying to access something.php inside subfol(even if was working) it accessed root folder's one(or did 404).

Wtf is going, none of the trillions have worked yet.
So can anyone please provide GOOD WORKING ONE!

Hamid - 13.06.06 7:45 pm

The rewrite url shorted up my URL as I wanted, but it affected image URLs as well, so none of my images appear. Can you help me please



luke - 14.06.06 2:28 am


I am a total novice. My first .htaccess file is not working:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteRule ^.htaccess$ - [F]
RewriteRule ^site/(.*)/(.*)$ site.php?screen_name=$1&site_name=$2

It brings up site.php but does not pass the variables to the php file.

Any idea appreciated!

bcswebstudio - 15.06.06 9:33 pm

I've implemented your great suggestion under "automatic translation" above. When I'm at work on our org network, it works great. When I'm off the network (ex. at home), however, the page translates only when it's a directly requested page (ie. when the english page is viewed and you click the link to get /faq.php-es, the page that turns up is /faq.php w/o rewrite! I suspect it has to do with outgoing http_referer being blocked from within our network and not from without-- any thoughts on this?

wonderful page/info.. I've been here before and stumbled across again-- bet you never thought you'd still be answering questions so long after having posted the info!

Kmax - 16.06.06 6:13 am

Hello all,

I am trying to pass an ip to an activex control.
But I want to put a "fake" or "proxy" ip in there instead of the real one... so when you view the source you just see or whatever.

Then I would like apache to send the data to the real ip and not the fake or proxy one.

Do you know if mod_rewrite can do this?
Send one ip to another one with all the http:// on it?


mremptywallet - 24.09.07 11:16 pm

I have no idea on what to do with my htaccess file. I am currently running a wordpress site and it has a default htaccess file. I am hosted on Go Daddy and i am trying to test out a new blog setup called Habari the requires PHP 5.1 or higher. I am on Go Daddys 2.0 hosing for Linux that supposedly allows you to user PHP 4 and 5 with 2 lines of code,
AddHandler x-httpd-php5 .php
AddHandler x-httpd-php .php4

My questing is i added the 2 lines of code but it does not work. I cant run the new Habari system. Can anyone here let me know how my htaccess should look?

<snipped - Cor>

cor - 25.09.07 12:31 am

mremptywallet, I snipped your code, it was just confusion. However, that was your only link to mod_rewrite, which is what this page is about. If you want to post it again, fee free; but please use [pre] tags to post code, then you can use any characters. like so..
<FilesMatch "\.(php|inc)$">
    SetHandler application/x-httpd-php

Though I'm not sure how relevant it is; all the useful information was missing. I'd try commenting out the entire mod_rewrite section, unless you absolutely need it. At least while you test to see if your AddHandler command is working.

As to the AddHandler command, I do know that GoDaddy's web hosting has minimal .htaccess support, but enabling php should be fine. Use only one line..

AddHandler x-httpd-php5 .php

Though I would probably recommend this instead..

AddType application/x-httpd-php5 .php

(that's a regular [code] tag, btw, "/" is just fine)

There's also "SetHandler", if you get really desperate. See my example at the top. Note: any one of these commands could be presented inside a <FilesMatch> block, or directly. You could also use blocks, and do it more safely like this..
<IfModule mod_php4.c>
    AddType application/x-httpd-php .php

<IfModule mod_php5.c>
    AddType application/x-httpd-php5 .php

Which would use php4 if php5 wasn't available.

Have fun!

;o) Cor

noname - 29.09.07 10:16 pm

Well, THANKs for sharing!

Concerning your "www" rewrite rule, what do you think about this variant (which does not have the specific domain inluded)

RewriteCond %{HTTP_HOST} !^www\.      [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^(.*)        http://www.%{HTTP_HOST}/$1   [R=301]

cor - 01.10.07 12:11 pm

The first time I read it, I instantly saw the beauty of it. Then I looked again. smiley for :eek:

It seems to do the exact opposite of what is required; that is; ADD "www." to all requests that do not begin "www.". That's nuts! That's exactly what we are trying to get away from.

However, I'm willing to pretend that you did, in fact, post this wonderful snippet (inspired by your good self)..
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^www\.(.*) [nc]
RewriteRule ^(.*)	 http://%1/$1 [r=301,nc,l]
In which case, I would probably reply along these lines..

Ha! Everone's got a better "lose the www" rule! smiley for :lol: Just kidding. It's really a good thing; every time a fresh pair of eyes hits the page, the possibility of interesting new approaches exists. What do I think? I like it!

What I like best about it, is the portability; you could run the exact same .htaccess file on your mirror AND your live site, and get the same result. This is a highly desirable thing. I recently and happily discovered that my new server does not require domain names in r=301 rules* (my old server insisted on them), so I've been moving towards this state myself. Simplicity rocks!

Another cool thing about this rule is that it can be used to redirect multiple domains. I have a couple of other domains running inside, in their own sub-folders. This simple ruleset in the main .htaccess file would redirect ALL domains to their correct format. Pretty neat. I'm using it right now!

So I'd recommend your approach in a flash; however, it would need to first be tested on a particular server, pererably with your "test" domain..

I used to have access to a server where almost nothing worked. This sounds useless, but it was, in fact, quite the opposite, and I regularly dropped php and apache code on there to see how it would fare, a sort of crash-test-dummy-server. Your code wouldn't work on there!

I used %{HTTP_HOST} a lot more in rewrite rules myself, until I moved servers once and they all broke. Big fun! I tend to only use it in rewrite conditions these days, where it never breaks, so far…

Anyways, I like your variant so much, I might even do a "variations" section, with a few alternative approaches.

Cheers! smiley for :D

;o) Cor

I'm guessing this is because my current host has (correctly) setup my domain as "", wheras my old host had it set to "", so removing the "www" and redirecting to the HTTP_HOST would have created an infinite loop.

Terrykm - 15.10.07 2:13 am

My .htaccess has this rule

RewriteRule ^viewcart$ /store/cart.php?m=view [NC]

which works fine - that is, it loads the View Cart page.

However the url of that page is /viewcart

But in order for any subsequent clicks on that page to produce the desired outcome the url needs to be

Any way to do that with a rewrite rule?



Harsh - 15.10.07 6:40 am

hello every one,
i am new at apache,
and i want to rewrite my url through .htaccess ,
but it redirects my page to another directory,
so plz any one can guide me to solve my problem in which i can rewrite my url with out redirecting my page.

my url is like that
i want to rewrite url like this

adam - 15.10.07 11:55 pm

Hi Guys, I'm trying to figure out what exactly the following script does:

AddType   application/x-httpd-php .html
Options   +FollowSymLinks

RewriteEngine On

RewriteRule ^(.+\.(gif|jpg|css|png|exe))?$ - [L]

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.+)/(index\.html)?$ index.html?url_path=$1 [QSA,L]

I guess the last line is the that is confusing me. I think that it is taking everything in the URL that is before the index.html part and rewriting it to index.html?url_path=xxxxxx.

Is this a redirect or simply passing a parameter into a script?

Thanks for any help in advance.

cor - 16.10.07 1:49 am

An intriguing little ruleset, that, adam. In fact, it looks more like two rulesets, joined together, with something wonky in the middle, somehting which would probably be happier in a block like this, like this..

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?mydomain\.com [nc]
RewriteRule ([^denied])\.(gif|jpg|css|png|exe)$ /denied.gif [l]

Which is another common Hot-Link prevention approach. As it stands, it will interfere with the following rules, though having said that, my test server doesn't respond well to the [L] flag, and so I rarely use it and lack a great deal of experience with it, and if I see "- [L]", I generally do [F], instead. It should stop processing rules right there, and send a 403. Is this what you want?

The first bit; parsing .html files as php; is nothing unusual.

The last part, is as you describe, except that it first checks to see if the requested resource exists as a file or a folder (-f, -d; a wasteful process, best avoided), and rewrites missing files to index.html?url_path=xxxxx. Interesting. It looks like a snippet you "found". Are you attempting to do something in particular?

Terrykm, YES! Whatever it is you want.

Harsh, scroll up, there's a whole article about this!

;o) Cor

Murali - 16.10.07 9:44 am

Thanks a lot....

adam - 16.10.07 10:40 pm

Hey, thanks for the reply Cor. I figured the first part was to parse html files as php which is cool. So, the second part is related to blocking image hotlinking. For the site this is used in I don't think this is going to be an issue, really, but you never know. You are right the rules you have shown interfere with the rest of the rules and the site breaks!

I am doing some work on an existing web app and I have 'inherited' this htaccess file! Took me a while to figure out what is going on but basically all links are rewritten as index.html?url_path=xxxxxx. The index file resides in the apps root directory. So you can't access a file by typing the path of the script. You have to access it via the index.html file.

The xxxxx part is then processed by the app as an array and the script figures out which modules to load up etc. I suppose it would be neater to rewrite the xxxxxx part as a proper query string and process that? That would mean a rewrite of the parser bit though...does that make sense?

What do you mean rewrites missing files? So if a file doesn't exist it just rewrites toindex.html?url_path=? Also I am not clear on what the
[L], [QSA] and [NC]
flags are doing.

One last question, the %[SCRIPT_FILENAME] refers to the same resource that is being rewritten in the last rewrite rule?

By the way, I really like the site. Nice and original and a good colour scheme etc. Good stuff!


cor - 17.10.07 2:13 am

Ahhh... inherited code. Ouch!

Yes, the index.html is the "master" page, by the looks of things. The previous creators probably added this catch-all facility to grab stray requests (missing files, etc.), and pipe them through the "parser", as you call it; perhaps hoping for a second chance at the URL's, or at least throwing up the default page, rather than a regular 404. Not a bad strategy, though wasteful; Apache1 has to check for the file existence, and folder existence before processing every single request. That's quite an overhead.

If I'd inherited that code, I'd probably pull off another .htaccess trick, do something like this, instead...
ErrorDocument 404 /index.html

adam said..
The xxxxx part is then processed by the app as an array and the script figures out which modules to load up etc. I suppose it would be neater to rewrite the xxxxxx part as a proper query string and process that? That would mean a rewrite of the parser bit though...does that make sense?

Yes, it makes perfect sense, and I guess leads us right back to the start of my post. For me, writing code continually becomes more and more about writing maintainable code. It might be someone else, or it might be me, a year from now, maybe after six months working on songs and poems; either way; we're gonna need to be able to pick up the code and work with it, without having to spend days trying to get our heads around it. If only people could grasp the value of good NOTES, preferably right next the code they refer to.

Confusion is the enemy of time. With my own code, I become more than occasionally obsessed with making things simple. Simplicity if the friend of time, I'd have no doubts; no question at all, I'd rewrite the code so it made sense, nomatter how long it took.

However, in the real world, one needs to weigh up many things; do you have the time? Are the changes feasible? Will they take lots of effort to implement? Will they affect your inward links and SEO efforts? Will the content management still work, afterwards? smiley for :aargh: And so on.

Getting a clear and logical URL scheme is extremely important, so if it's a relatively new site, it's definitely worth taking the time to get it right from the start. That's always going to be easier, in the long run, than trying to retro-fit a site with improved logic some way down the line.

Consider nice flat links. I've been using them for my blogs, and find them most elegant.

Which brings me neatly to the site design. Thank You! So few people comment on it, and was such a lot of work! The switch to XHTML+CSS wasn't plain sailing, by any means, but the clarity of the current code, and how easy it is to maintain and add to the site, gives me a warm fuzzy glow every day! Simplicity all the way, baby!

for now..

;o) Cor

  1. As for the flags, I'll have to direct you to RTFM, not so much because it's easier for me, but because there are many other useful flags; and a knowledge of each is another string to your bow. There are a few places in these articles where I hint at possibilities, but don't delve there; hoping the readers' curiosity will be peaked enough for them to hunt some. It's worth the effort.
  2. I've not done this; it just popped into my mind as a cute solution to the file-checking overhead. It would work though, so long as you remember that, at least techically, regardless of the fact that it's the front page, the browser has received a 404 error, which just happens to also be the front page. As soon as they click somewhere, all this is moot, but it's good to know.

Anirban - 19.10.07 9:08 pm

Hello Cor,

Your article helped me a lot to understand how to use htaccess. There's a problem with what i am trying to do. This is what i wanted to do. I've got a page called profile.php which takes in the parameter uname as the username who's profile i need to display. So, what i wanted to do is to make the profiles to show like on myspace... like

But, the problem which is coming up is that it's now showing the index also as a blank profile page as it's technically not having anything on it. This is what i used for the htaccess.

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^([A-Za-z0-9-]+)?$ profile.php?uname=$1 [L]
Options -Indexes

So, since it's supposed to take as a uname=myprofile so now it's taking blank as the uname for the index of I tried by redirecting to the index file but got a Internal server error. So, i'm in a messy situation. Can you help me out? If you can i'd be very thankful. Thanks for all the info you already provided till now.



cor - 20.10.07 8:28 am

There are a few ways to tackle this, Anirban. The easiest is probably with a RewriteCond statement..
RewriteCond %{REQUEST_URI} !^index\.htm(l)? [nc]
before the RewriteRule line (or index.php, if that's what yours is). You might also consider removing the "?" from the RewriteRule command, so only requests with something in them get redirected, otherwise loading your TLD on its own will get you redirected.

You may also want to consider merging the -Indexes option into the first Options statement. While having two separate statements is fine; technically speaking; it's bad practice, and inevitably leads to confusion and errors later on. I generally do..
  1. caching
  2. errors & denials
  3. options
  4. rewrites
  5. extra stuff (php directives, etc)
And keep roughly the same system throughout all my .htaccess files.
Lots to consider!

;o) Cor

Anirban. - 20.10.07 9:41 am

Hello Cor,

Thanks man the problem is now sorted out smiley for :)smiley for :)thank you so much. Now the files are working just fine.



Harsh - 23.10.07 12:34 pm

hello every one,
i am new at apache,
and i want to rewrite my url through .htaccess ,
but it redirects my page to another directory,
so plz any one can guide me to solve my problem in which i can rewrite my url with out redirecting my page.

my url is like that
i want to rewrite url like this

for that wrote my .htaccess file as follows
Options +FollowSymLinks
RewriteEngine on
RewriteBase /code/
RewriteRule ^(.+)/([a-z]+)\.php$1/$2 
RewriteRule ^(.+)/([a-z]+)_([a-z]+)\.php$1/$2 

i have tried a lot with that code by adding and removing RewriteBase and but every time my page is redirecting instead of rewriting my url and give me error like this "Object Not Found Error 404"

So friends plz if any one can help me to resolve my problem then i will be very thakfull to you all,

scott - 23.10.07 1:51 pm

Okay, rewriting rules are OFFICIALLY, retarded.

^images/(.+).(.+) /images/fetchimage.php?fkey=$1.$2 doesn't work. (500 Internal Server Error)
^images/(.+) /images/fetchimage.php?fkey=$1 doesn't work. (500 Internal Server Error)
^images/(.+).([a-z]+) /images/fetchimage.php?fkey=$1.$2 doesn't work. (500 Internal Server Error)
^images/(.+).(jpg|jpeg|gif|png) /images/fetchimage.php?fkey=$1.$2 does work somehow?

If any of the top 3 were to work, I'd expect the SECOND one at least, it's not even remotely complex, but I'm convinced whoever wrote the protocol for these expressions seriously f'ed up somehow. But meanwhile my code is crippled and I'm pissed off for having to spent hours trying to figure this sloppy system out. smiley for :ehh:

OMFG and now your comment system is giving me lip about unbalanced BBCode tags smiley for :aargh:

cor - 23.10.07 2:07 pm

Harsh, "everyone" left the minute they got their solution. That's just the way thing are. You can thank them "all" if you like, but they won't hear you. It's just you and me, for now, and I'm not your free tech support guy.

I already spent a lot of time covering exactly your situation; I wrote a whole article about this stuff, in fact, and I already answered you, pointing you to that very article (above), which I recommend you read. I also recommend you read the Apache manual page for "RewriteBase", which you clearly haven't, at least if you plan to use it.

Your solution is the most basic of rewrite rules, explained, here.

scott, haha! synaptic breakdown, clearly overdoing the rewrite rules. But that's not rewrite code, none of it; there's no actual "RewriteRule" commands, for a start. If you want me to take a look, use [pre] tags and post the actual code you are using. Check below the comment form for more juicy tips like that.

And for the record, mod_rewrite is officially not fexed up, it only looks that way sometimes, until we figure out the rule exacitaly. Then it's a beautiful thing.

;o) Cor

scott - 24.10.07 1:29 am

Options +FollowSymLinks
RewriteEngine on
RewriteRule ^images/(.+).(jpeg|jpg|gif|png)$ /images/fetchimage.php?fkey=$1.$2 [nc]

I'm trying to capture all requests to /images/* and redirect to /images/fetchimage.php?fkey=*
It's not working so well smiley for :blank:

I think what is going wrong is it's getting confused and doesn't know what to associate with each $n reference, or something. Although I still don't get why
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^images/(.*) /images/fetchimage.php?fkey=$1 [nc]

doesn't work. I even tried ending it with a $ anchor, I have no idea how it's getting confused and can't enable logging. I really don't want it to ONLY access the script if I enter "/images/a.jpg", and then getting a normal 404 if I enter any other extension, or none at all. Makes everything seem so choppy.

And I just had a thought, if fetchimage.php is in the /images/ folder would it be possible it's getting into an infinite loop? Do rewrite rules also check the location they are rewritten to?

scott - 24.10.07 1:35 am

Yep, that was exactly what was happening. Moving the file to the root dir made everything peachy keen. I guess I just needed some sleep to see what the hell was going on there. Oh well, thanks alot for the tutorial here, never knew about rewrite rules, and despite certain frustrations it's certainly helped alot. And now I can continue on with my worthless quest to rebuild my website! Yay.

cor - 24.10.07 6:54 am

Good work, scott!

It's very like when I was at school, I'd put up my hand to ask the teacher something, and invariably, while I was explaining the problem, I'd come up with the solution.

I realized that often, all it takes, is to run through the problem AS IF you were explaining it to someone, and I started doing that instead, to great effect.

The "infinite loop problem" is a common one; I do it myself every once in a while, and go "Oops!". A simple RewriteCond statement will fix it, either checking for the existence of a real file, or better; that the request ISN'T for fetchimage.php..

RewriteCond %{QUERY_STRING} !fetchimage.php [nc]

If I'd looked more closely at your original post, I probably could have seen that; but I've learned the hard way that it's not worth trying to diagnose incomplete snippets, and I don't even go there! If I'm gonna frazzle my synapses, I'll do it with my own code! smiley for :aargh:

Putting the fetchimage.php file in a different directory would also simplify things; always desirable. I guess you now realize why that one line did work, yeah? If not, I'll leave it with you as fun for your brain.

And hey! The quest to rebuild a website is rarely worthless; in fact it's almost always the opposite, especially if you are taking some old HTML mess, and transforming it into lovely XHTML+CSS. Mmmm.. Simplicity rocks.

Have fun!

;o) Cor

jim - 26.10.07 6:03 pm

Hi, I am trying to
rewrite my_domain_name/username to my_domain_name/tools/tools.php?uname=username

so that people can access their pages easily.

I am new to htaccess thing. Although I tried very hard, I really can not make it.
Could you please show me how to do it?

Thank you so much

jim - 26.10.07 6:12 pm

by the way, the username may be in unicode. I don't know whether it matters though.

Cor~ I need you...

Thanks a million in advance

cor - 26.10.07 6:16 pm

Did you know, you can edit your posts?

Anyways, show us what you've got already, the code that isn't working.
Use [pre] tags to post the code.

;o) Cor

ps. I'm in the middle of moving the site to a new server atm, so I may not respond immediately.
A email from PayPal always gets my attention, though! smiley for ;)

Brasso - 27.10.07 7:06 am

Hi Guys,

I'm new to this so please help!smiley for :ehh:

Does anyone know how I can do the following rewrite? -

changing all urls that start****** to

The text after /hotel.php? could be anything ie:


basically, I need all urls that use /hotels.php? to be re-written to homepage

Hope this makes sense!smiley for :eek:

cor - 27.10.07 12:39 pm

Try reading the article (above).
That will help.

;o) Cor

samorsomething - 29.10.07 11:23 pm

Thanks for the great tut, it's helped me out a few times and I been back 3 or 4 times... So far hasn't been anything I couldn't tackle.

Have to say though its funny reading all the comments and seeing all these please help me posts.
I'm gonna check out the rest of the site and hopefully find a way to play with this tagging system.

cor - 29.10.07 11:56 pm

You're welcome!

And yeah, they are a source of amusement, but more so; noise, and after strengthening the initial message a few times, I think they are slowly thinning out! smiley for :lol:

erm.. tagging system?

;o) Cor

Abhijit Mukherjee - 30.10.07 6:36 am


I want to convert my URLs Querystring to Folder structure

currently I am having

I want to make it or

How do I do that? can any body help me

Thanks in Advance

cor - 30.10.07 7:35 am

Or, perhaps not.
Do you see what we're up against?

This human seriously believes that by plainly showing that he couldn't even be bothered to read the HUGE notice above the comments, let alone the article itself, he will somehow entice me to donate my time to him, for free; something I have clearly already done, evidenced by that big wodge of text above these very comments, the part that so many seem to just skip over1 in their haste to ask for "help", something I'm about to provide, except in a deeper and truer sense..

Of course, regular readers know well that the reason this individual hasn't posted any code, is because he hasn't got any!  He didn't even attempt to get it working; figured someone else would just do it for him. Abhijit, do you have slaves in your locale? Is there some sort of cultural factor at work here? I don't think so.

Now, if this was a community, which it is not, some bod would definitely pipe in with a suggestion, and with some luck, you might even coax a solution out of your appalling situation. But relying on luck isn't going to get you, or your website very far, is it? Fact is, if every I-can't-be-arsed web master out there was to fuck off and do something he actually took seriously, the web would become an infinitely better place for us all2.

Let me guess, you're starting a mobile phone site? Because we definitely need more of those. Or maybe something truly revolutionary, but based-on youtube? Go away! You may find you have a real purpose in life. Something else. You could be living a charmed existence, benefitting mankind, and doing something you truly en-joy, and for all the right reasons, instead of just adding to the noise.

That's how I feel about the web; I'm passionate about it, I dream code. You obviously don't give a shit about being a web master, or else you'd right now be pouring through the basic documentation, checking out the recommended reading, learning all you need to know to do the task, pounding your home server, and sharpening your skillz until you know  the web.

If you had ever thought about it, you would have realised that the title "Web Master" implies that THERE IS SOMETHING TO MASTER! Mastery of begging does not qualify.

Hey! This is great getting, thanked in advance; basically carte blanche to say whatever I want and know that I already  have your "appreciation", which I've anyways come to learn means, "thanks. bye".

So, in the deepest and truest sense of the phrase, please..


for now..

;o) Cor

1. Not all, though. I had an amusing morning recently, downloading copies of this very article from other web sites.
Amazingly, a couple of them actually completed the arduous task of mentioning where they stole it from.
2. Don't foget to take down your sites before you go!

Mato - 07.11.07 9:16 pm

Hello im trying and trying something but i cant!

First of nothing i need to say that i have a rule on .htaccess on my root folder (, and it have the next code:
Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} [nc]
rewriterule ^(.*)$$1 [r=301,nc]

I say it because maybe it modify the new thing im trying to do.
I need a redirect from:


This is possible?

Thanks in advance

cor - 08.11.07 12:29 am

Yes Mato, it's possible. In fact, it should happen automatically, without any rewriting. I just answered this on the other page recently, simply add..

DirectoryIndex index.php

To the top of your .htaccess file, and you're done, at least, you should be.

;o) Cor

Justin - 12.11.07 4:56 am


Thanks for your help. I have some problem, it would be great if you could help me here . . .
Options +FollowSymlinks
RewriteEngine on

addtype application/x-httpd-php .html .htm
RewriteCond $1 !^(index.php|js|images|listingImages|system/plugins|robots.txt|css/)
RewriteRule ^(.*)$$1 [L]

above is my htaccess file. and its works great. But i want a slight modification

What I want is if the above rule fails {the url does not exits } then use another rule. some what like this..

Options +FollowSymlinks
RewriteEngine on

addtype application/x-httpd-php .html .htm
RewriteCond $1 !^(index.php|js|images|listingImages|system/plugins|robots.txt|css/)
RewriteRule ^(.*)$$1 [L] 
#if this one fails{page not found} then below rule should be follow$1 [L]

Please help me.

best regards,
Justinsmiley for ;)smiley for ;)

Luis - 12.11.07 12:33 pm

Hey Cor,

I don't have any question to bother you, but I couldn't help dropping a line to tell how how much I've laughed reading your answers to those i-am-a-webmasta guys. Very nice article. I have implemented a rewriter for ASP.Net, working in a very similar way in essence. The basics are easy, but ASP.Net deals with postbacks and there are a few things to consider. I recommend these links if anyone was trying to apply this to MS environments:

* Tip/Trick: Url Rewriting with ASP.NET
* MSDN: URL Rewriting in ASP.NET
* Jesse Ezell Blog: Fixing Microsoft's Bugs: Url Rewriting
* The Passion and the Fury of URL Rewriting

I have successfully implemented URL Rewriting on my website (it's in Spanish, though):
The goal of rewriting the URL, in my case, was to make the site more SEO friendly, but I have other websites with copyrighted pictures and I think that rewriting can be very helpful. Also to avoid hot linking, etc..

Thanks Cor!

cor - 12.11.07 1:20 pm

Note to self: don't do comment replies when you've just woken up!

I posted this to my development mirror, earlier. Here it is again, except on the correct server smiley for :roll: ..

Thanks for your help. I have some problem, it would be great if you could help me here . . .

Oh! I intend to, Justin! There's a link at the foot of this post that will sort you right out! Let's have a look, shall we..

Okay, I see what you've got. (by the way, avoid RewriteCond $1, it only causes confusion later on, stick with RewriteCond %{REQUEST_URI}, which is readable)

And I see what you want.

What I don't see is, what you've tried.

;o) Cor

ps. this might help.


And in the here & now..

Thanks for the links, Luis; it's a dimension of rewriting I rarely consider, being Linux across-the-board, at least for serving. I'm sure others will find them useful; I'll likely pop them somewhere in the main article. Cheers!

I am glad you enjoy the text, too; it's great to have an opportunity to really help people, dontcha think! smiley for ;)

Luis - 12.11.07 2:38 pm

Even if someone is lazy, if they don't even bother reading the basics, how can they think about having a decent website.

Hey I now have a question: how does rewriting affect a server's performance? If a shared server has lots of users with dozens of rewriting rules, does that slow down the server? Can be the case that a hosting provider denies the chance of doing rewriting? I understand that every http request is validated against the regular expressions we've created on our .htaccess file.

In IIS you don't have a built in option yet, but it's coming up in the newest version (IIS7). However one can create a custom module to do the rewriting. While I've been working with it I've come to think of all the code that is executed each time! And when it goes further than regular expression matching (security checking, DB connections) before rewriting, it is even worse.

Also we have a very particular situation for which I think I can't use rewriting with reg. expressions. We have to inject the language and the version & subversion numbers of the requested content in the URL. That means manually checking and messing with the path. But then again that is very particular, and for many people regex are just OK.

Well, I am going to read your cover of RSS.

Keep it up!

Regards from Barcelona (Spain)

cor - 13.11.07 11:17 am

Yup, good web sites generally represent hundreds, if not thousands of hours work on the part of their developers. Quite often with little reward, except the work itself, which is, thankfully, enough.

And yes, you are right to be concerned about rewriting affecting performance, because it shows you clearly understand the sheer volume of code involved in performing these manipulations. But mod_rewrite is extremely efficient, and in the real world, you won't see a performance penalty.

However, some mod_rewrite code can be extremely inefficient; that is, user-code. directives with a -f or -d switch are an instant performance hit. If such rules live in your main .htaccess, and are checked on every request (people do this! nuts!), it can have implications. Also, double (.*) sections in a single pattern can affect performance; mod_rewrite has to look twice, so to speak, so some thought needs to be applied on a busy server, for sure.

However, it's practically unthinkable that a host would setup Apache without mod_rewrite, and extremely unlikely they would deny this facility to their clients, unless they wanted to go out of business, or were just hosting for fun. mod-rewrite is too handy, and its usage too widespread, that you would be hard pushed to find a non-mod_rewrite enabled server to compare performance with!

What a web master needs to know is, will performance be an issue?
And the answer, as always, is Test Test Test.

It has to be said that rewriting in .htaccess is much less efficient than in a server context (vhosts, or httpd.conf), but still, almost miraculously efficient compared to what one might expect from the processing involved. I haven't studied the source code - one day maybe - but I'd wager it's full of juicy goodness!

Good luck with your IIS rewriting implementation; a task I do not envy.

;o) Cor

Tiredwithrewrite - 14.11.07 3:43 pm

I have read your article and have tried out a few things but Im still not able to accomplish my real task.

Below is the htaccess file that I have and out of that one condition works perfectly for me but the actual part where I wan to have directory type of URL it is not working smiley for :ehh: Can you please please help me?
Options +FollowSymLinks
RewriteEngine on 
RewriteCond %{HTTP_HOST} !^www\.mysite\.com$ [NC] 
RewriteRule .?{REQUEST_URI} [R=301,L] 
RewriteRule ^partner_details/([0-9]+)/([0-9]+)/([0-9]+)$ partner_details.php?catp_id=$1&p_id=$2&mcat=$3

The first part works fine where in if user enters then the URL changes to
but the second part where partner_details.php has to change to partner_details/ is not working.
I am using Apache 1.3.37.

cor - 14.11.07 4:10 pm

Tiredwithrewrite, the rule looks fine. I'm assuming you meant to say..

but the second part where partner_details/ has to change to partner_details.php is not working.

And not the other way around. Right?

The only things I can think that might be wrong are..
  1. you are supplying the wrong kinds of URLs.
    Your rule REQUIRES that the URL is in the exact format..

    except with other numbers. Unless all three sets of numbers are there, the rule will fail

  2. you have no line break at the end of your .htaccess file after these rules. In other words, that rule is on the very last line of the file.

  3. something else

"something else" could be something real silly, like partner_details.php doesn't exist, or partner_details.php send a location header, or some other such tomfoolery.

It's more likely to be one of the first two, though.

;o) Cor

Tiredwithrewrite - 14.11.07 4:28 pm

Hi Cor,

First of all let me really thank you for the quick reply.

Sorry about the confusion:
Yes I want my URL to be like

Ok as for the format of URL well it is exactly as it is. Meaning the three parameters are being passed. SO I can actually cross out the first one.

As for the second "Line Break". If that means [L] then I have tried that too and it still does not work.

And Im sure that the partner_details.php does exist because it is working normally:

So i too can think that its only the second point. Guess im doing it wrong there. Is there any special way to give a line break? As mentioned I have tried [L]

Thanx again for you reply.

cor - 15.11.07 6:08 am

A line break (aka "newline") is the character that is formed when you hit <enter> on your keyboard. Like <br /> in HTML, but for real files.

If the last rule is on the very last line of the file, place your cursor at the very end of that line (End key) and then hit <enter>, then save.

;o) Cor

Tiredwithrewrite - 15.11.07 6:44 am

Hi Cor,
Well yes there was no line break and the rule was the last line. I have changed that and yet im not able to get the result. My URL still shows up as

Is there something else that i need to do like restart Apache or the server or may be initialize the .htaccess file in any other way? I have currently just copied the file to the server. Any permissions to be set? Im quite in experience in these terms :(
In any case I really appreciate the help that you have given so far. Thanks a ton for that.

cor - 15.11.07 2:20 pm

My URL still shows up as

erm, isn't this what you want? smiley for :eek:

You seem to be confused.

What you have now achieved, is a rewrite FROM /partner_details/2/33/2/ TO /partner_details.php?catp_id=38&p_id=27&mcat=1, so if you type this into your browser..

It will be rewritten (in the background) to /partner_details.php?catp_id=38&p_id=27&mcat=1, and partner_details.php will load, with the variables catp_id, p_id, and mcat available to the script (though the browser will still display the flat link in its address bar).

You're done!

Of course, your page also needs to be producing these links in the first place. I'm assuming that whatever software you run on your site (or the HTML, if it's a static page that has these URLs on it) is actually PRODUCING flat links in the form of /partner_details/2/33/2/, right?

Your rewrite will translate the incoming /flat/link/ requests into ?variable=foo type requests.
But it can't create the links for you!

;o) Cor

Tiredwithrewrite - 15.11.07 2:54 pm

No wonder Im really tired smiley for :blank:
I am actually looking for a way to transfer:

I still am under the impression that in the RULE you first specify the PATTERN then what you want translated.smiley for :ehh:

Cor Im really sorry if I have been silly and troubled you. But like i said I want to make by ugly looking URL to look beautiful by removing all the ? = & etc.

Im using PHP MySQL on my server.

I feel like a FOOL

cor - 15.11.07 3:11 pm

There's no need to feel foolish; your rewrite rules are 100%. That part is just fine. Trouble is, it's only half of the story.

For what you want, you do need rewrite rules, but you also need to create those flat links in the first place.

Perhaps you imagined that .htaccess could do both parts "automagically", and on-the-fly. No. That's just not possible. The flat links have to be on the page in the user's browser, and aside from special circumstances .htaccess has nothing to do with that. That's up to your web code.

I don't know what you use for a back-end on your site, but whatever it is; some php CMS, or shopping cart software, or whatever, THAT is where you need to make the changes, THAT is where the actual flat links are created. If the back-end doesn't generate a flat links on the actual page the user gets in their browser, then the user will never see, nor request /flat/links/, will they?

What rewriting does, is transparently converts the flat links the user clicks in their browser, BACK into proper ?variable=foo type links, for use in our back-end.

For the whole thing to work; you need both parts; back-end code, and .htaccess rewrites.

If there's still any confusion, please do get back here with another comment/question. I'd like to pin this down absolutely, so I can add a section about it in the main article; you are not the first to make this set of assumptions.

;o) Cor

Chris - 15.11.07 3:51 pm

Just a quick line to say thanks for not only a couple of great pages on the mysterious .htaccess inner workings, but almost even more for the fantastic and entertaining comment section!

If you're ever in Zermatt for a bit of skiing, etc, give a shout -- a beer or three are reserved as a small thanks smiley for :cool:

cor - 15.11.07 4:26 pm

Cheers, Chris!
Czech Lager for me!

I'm building a list of venues. I reckon, in a decade or so, I'll have enough pit-stops lined up to do a world tour! smiley for :D Hey! I'm serious! smiley for :lol:

As for the comments, well, it's funny you should say that, because I was just having a read through some of the older ones myself, which I rarely do (break-time, following up a suddenly popular inward link) and thinking the very same thing! Some of them are rather good, aren't they.

Och well, back to work..

;o) Cor

Jamie - 15.11.07 7:52 pm

Hi there!

First of all, great article!
It's the first useful resource I could find helping me with my htaccess problems.

But there is something I miss in the article. I noticed how you described the REQUEST_FILENAME in case of allowing (or denying) access to single files but I miss the flags you can put behind REQUEST_FILENAME.

Could you please explain some more on this because this is were I get stucked.

Why do I get stucked on this? Well I will explain with this example:

Options +FollowSymLinks 
RewriteEngine on 
RewriteOptions MaxRedirects=15

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*) /index1.php?p=$1 

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^en/(.*) en/index.php?p=$1 

This should do 2 things:
1. Make sure all people who go to are 'secretly' transfered to
2. Make sure all people who go to are 'secretly' transfered to

Problem is: the first one works but the second doesn't.
How is this possible?

cor - 15.11.07 10:20 pm

If you change everything after "RewriteEngine on", it'll work great!

;o) Cor

Jamie - 16.11.07 9:50 am

Uhhh ok.... That's an easy answer.

Which lines should I change and why? I did as you described in the article and I honestly can't see what's wrong.

cor - 16.11.07 12:11 pm

smiley for :lol: At least you came back. Good for you! Lots of folk would have scurried off with their tail between their legs! (you get points for this) At any rate, the only lines that remotely resemble ANYTHING in my article are..
Options +FollowSymLinks 
RewriteEngine on 
That's it! Who knows where you go the rest! Hopefully not from any of the examples in these comments, which are specific to the poster being answered. For starters, I normally wouldn't recommend the use of -f or -d unless they were absolutely necessary. And this..
RewriteOptions MaxRedirects=15
is just another way of writing..
# my code sucks, I expect it to fail
which I never do! I haven't even given that to someone in a trick reply!!! Part of me wants to stop this post right now, because attributing that mess to me is tantamount to libel! smiley for :lol:   Now that we're done with the formalities, let's look at why your (someone's) code doesn't work..

The first and biggest problem is that the rules are back-to-front. How do you expect any request to ever reach en/ when you have already redirected everything* with the first set of rules?

Secondly, the -f or -d serve no real purpose here. The seem to have been placed there for no other reason than to slow down your page response time. For images, was it?

Thirdly, why is the main index called index1.php? That also smacks of luser mentality, like you can't get anything to work, so "let's try giving them different names and see if that helps". Dude!

I know it seems complex, but really it's quite simple if you take it step by step, and apply logic. Let's see what you are trying to achieve..

This should do 2 things:
1. Make sure all people who go to are 'secretly' transfered to
2. Make sure all people who go to are 'secretly' transfered to

Basically, you want transparent translation from flat -> dynamic links. That's not so hard. By simply switching them around (putting the "en/" rules first) we have most of the solution. But we also need to get rid of those nasty -f and -d switches..

Instead of checking the filesystem for every existing file and folder (with every single request), why not just redirect everything that isn't index.php? Something like this..
RewriteCond %{REQUEST_URI} !index.php
RewriteRule ^en(.*) /en/index.php?p=$1 [l]

RewriteCond %{REQUEST_URI} !index.php
RewriteRule ^(.*) /index.php?p=$1 [l]
So far, so good. But you will probably want to allow direct access to images or other resources; no problem, you simply add conditions (RewiteCond statements) for those.

Finally, you probably noticed that the rewrites themselves can be compressed into a single rule, well spotted! So at the end of the day, the whole lot is simply..

RewriteEngine on 
RewriteCond %{REQUEST_URI} !index.php [NC]
RewriteCond %{REQUEST_URI} !\.(jpg|png) [NC]
RewriteRule ^(en/)?(.*) $1index.php?p=$2 [NC,L]

;o) Cor

ps. If index.php is the only .php file on-site, you could roll that extension into the second RewriteCond and do the whole lot in two lines.

Jamie - 16.11.07 2:04 pm

Wow... *silence*

Honestly I didn't expect a response to my question, I'm very suprised, this is great! :-D

First of all: yes I do suck in writing code (but I try)!
Second, lets comment back on some things you said:

The RewriteOptions MaxRedirects=15 line I just put in because my apache error log told me so. I now realise it's rubbish.

The structure of my page:
/index.php (a page where people can select their language (dutch or english).
/index1.php (the site in dutch)
en/index.php (the site in english)

That's the reason I have an index1.php. May not look nice but if the rewrites work my visitors won't even see it.

Other thing: I now really get why not to use -f or -d.

And no, I didn't notice the rewrites to be compressed to a single rule.

Well, did it work for me? Unfortunately no...

I now have this:
RewriteEngine on 
RewriteCond %{REQUEST_URI} !index.php [NC]
RewriteCond %{REQUEST_URI} !\.(jpg|png) [NC]
RewriteCond %{REQUEST_URI} !\.(css) [NC]
RewriteRule ^(en/)?(.*) $1index.php?p=$2 [NC,L]
And it works fine for the english pages but not for the dutch. When trying to visit i.e. it puts me back to

What have I missed here?

cor - 16.11.07 3:02 pm

Ahhh.. What's missed? Indeed! .. STRUCTURE. You used the word yourself.

Yours is illogical; site structure, that is. I didn't know about the audio/ folder, nor any of the other goodies you might have in there. Of course there's almost always a rewrite solution, but as you soldier on, things could get more and more complicated for you. The real solution.. Fix the Structure.

If your site is in Dutch and English, why not have two folders, en/ for English, and nl/ for Dutch? If there's some Nationalism involved, forget it! We're all the same! And anyway, English r00lz! smiley for :evil:

With two folders side-by-side, life is *much* simpler. It means you can get rid of that index1.php (which still looks so wrong! hey! The webmaster will see it!). You can then create other folders in the root for images/, css/, whatever/, safe in the knowledge that won't be affected by your rewrite rules covering en/ and nl/. It will also make it easier to add other languages later on, if you so desire.

With good structure, your rewriting task is made easy..
RewriteCond %{REQUEST_URI} !index.php [nc]
RewriteRule ^(en|nl)/(.*) $1/index.php?p=$2 [nc,l]

Finally.. Ahhhhhhh!! This is for LANGUAGES!!!!!! smiley for :aargh:

Are you aware of Apache's content negotiation capabilities?

;o) Cor

Fred - 18.12.07 2:34 pm


I wonder, is it possible to rewrite the url of a page that has an iframe on it to the url of the iframe content?

In other words, I have this page: index.php?template=forum on it there is an iframe that is wraping a forum, so when the user browses the site the index.php?template=forum url doesnt changes according to the forum contents... of course... my idea is to replace the index.php?template=forum by the forum urls.

Is it possible to do this in the .htaccess file?

Thanks in advance smiley for :)


sex hikayeleri - 21.12.07 2:28 pm

thanks a lot.

John Norwegian - 22.12.07 12:25 pm

Hey sir!

Wonderfull reading, ive been rewriting for ages but never been hailing the creator of the mod_rewrite.

Do we have any statistics on how much all the rewriting we do slows the processing time down?

Anyways, i was wondering, and im positive ive seen this in some scripts, here goes:

My domain:

On my domain i have a static URL (in a php page):

How would i go on about rewriting this to the following URL:


smiley for :geek:

Rahul Roy - 27.12.07 12:43 pm

I just want to redirect my webdevelopmentexpert .com to http://www. webdevelopmentexpert .com using .htaccess. Please tell me the proper procedure.

kuku - 03.01.08 1:29 pm

Really good article. Thank you very much.

But i have two problems. i use below code to rewrite url. it is working fine.

RewriteEngine On
RewriteRule ^(.*)-(.*).htm siteview.php?pid=$1

original Url -

after rewrite -

Problems ------
1. How can i take off page ID ?
2. How can i use -, between two words(%20). like this -

Thank you

Jerry - 14.01.08 9:51 pm


I am trying to do a redirect from all index files to the root because of search engines and "duplicate content" as they call it even though it is a same page.

I have URLs like this

and and I want to redirect that to

(yup, just kill that index.htm)

But it just won't work.

I tried this:
RewriteRule (.*)/index\.html?$ $1/ [R=301,L]
and it errors
Same with this:
RewriteRule ^(.*)index\.htm$$1 [R=301,L] 
Rewrite engine is on.
Any suggestion would be greatly appreciated.

rookie - 21.01.08 7:52 pm

I have to put the .htaccess file at my domain root. Say suppose I want to put the .htaccess file in c:\a\b\c\abc.war and I installed Apache at "C:\Program Files\Apache Group\Apache2".

So what will be the setting I have to do to make Apache to understand that it has to refer .htaccess file in c:\a\b\c\abc.war and not the Default one that it uses.

I have made some changes like

AllowOverride All

in httpd.conf file to make it work.

I also put the following code in .htaccess file:

Options +FollowSymLinks 
RewriteEngine on 
RewriteCond %{REQUEST_URI} ^/abc(.*)$
RewriteRule ^(this¦that¦other¦whatever)/(.*)$$1 [R=301,L]

But still I am not able to see the effect for this smiley for :roll:

I have gone through the whole article part I & II but I was not able to find any thing that tell the setting/Steps to be made at Apache Side.

Any Comments/help would be really helpful


Alexandre - 23.01.08 12:17 am

thanks a lot Cor your article was super helpful!

Alexandre - 23.01.08 5:48 pm

there is one thing that remains unclear even after reading your article (which otherwise clarified most of the htaccess questions i had, thank you for that). I'd call it "htaccess subfolder inheritance":

Reading your article i understood that an .htaccess in the root folder will affect all its subfolder, unless overwritten by subfolder-specific .htaccess files. Yet that does not work for me so far.

Is this correct or not? Does it need a special setting so that it works this way?

just in case, here is my htaccess:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^projects/([a-za-z]+)/([a-za-z]+)/([a-za-z]+)/([a-za-z]+)$ projects/$1/$2/$3/$4/ [r]
RewriteRule ^projects/([a-za-z]+)/([a-za-z]+)/([a-za-z]+)/([a-za-z]+)/$ app.php?section=$1&sortBy=$2&dsAnchor=$3&item=$4

it returns "The requested URL /projects/time/2006/touch was not found on this server." whereas it should have added a slash and then redirected to app.php?section=projects&sortBy=time&dsAnchor=2006&item=touch

What i'm doing wrong?

MUSTAFA BASARAN - 24.01.08 8:27 am

thanks for more information..

Faheem - 24.01.08 10:05 pm

Hi Guys,

I have a simple condition to apply but its getting most complicated to me..

I want to redirect any user that comes to any sub folder of my site to a specific location with the name of that sub folder..
it works like that

RewriteRule ^([^/]+).com/([^/]+).php /website/$2.php?user=$1&file=$2 [L,QSA]

the prob is to make above statement work I have to brose it like that

the thing is that I want to remove (.com) from there
it should be

and i need to get values like this..

I tried it this way.
RewriteRule ^([^/]+)/([^/]+).php /website/$2.php?user=$1&file=$2 [L,QSA]

but this gives me a 500 error.

can anyone help please ?

also what if I want to use user as a sub domain ?
and this one should read as

Please do help.. my whole project is depending on it..

Thanks in advance

Monika - 26.01.08 1:49 am

Great read, I've tried a few other resources/books to understand this topic. They didn't work for me. You not only managed to make it clear but also very funny. Thank you!

Losh - 29.01.08 6:38 am

Great tutorial, i finaly understand this whole Rewrite thing. Thanks!

Moaku - 01.02.08 8:44 am

Hi guys ! I've found many usefull informations that I could use later inthere but it doesn't solve the problem I was googling for...

I'm currently not using mod_rewrite and use an htaccess that redirects the 404 error to / so it points to index.php, my default site parser.

In the whole site from now, i'm using a basic get syntax so the url looks like "/?p=home".
For conveniance, I want some pages accessible via an easier URL, so I made a parser that can parse URLs detected in the "easy" way like "/wiki/article" for example... and makes it compatible with my $_GET based syntax internally, so both URLs types works (so, when /xx/yy is called, it triggers an error 404 which redirects to the main script that internally converts the URL).
All works just fine at displaying phase, but at processing phase, I quickly noticed that $_POST was dropped in the process. I googled and found no way to enforce the $_POST redirection.

After reading this page, I was wondering if some url rewrites with mod_rewrite could do the trick but I'm not familiar enough with regexps yet.

Or better... a way to toggle an "AlsoTransmitPostDataOnPermanentLinks" variable that I could have missed in php.ini ?

Well, any advice would be welcome smiley for :)

Harel - 11.02.08 10:15 pm

I have a problem I hope you can help me?

I have my WordPress (2.3.3) installed in A "WP_blog" directory.
For some reason when I click on tags on a post it adds the "WP_blog" directory and the index.php to the url and the results are lost.

If I delete (manually)the "/WP_blog/" part of the url the link is working fine.
So my question is how can I redirect the url results to ?

btw: I have two wordpress installation on the other one its working just fine.

Thank you

JohnnyTwoShoes - 14.02.08 7:33 pm

Hey man, thanks for the advice! Nice write-up.smiley for :D

cor - 26.02.08 7:33 am

Sheesh! I can't leave this page for five minutes! smiley for :lol:

Thanks for the flowers, guys! There's hope for the human race, after all!

Fred, yes, but I don't think that's what you want.

John Norwegian, the speed penalty is minimal. Unless you are running some HUGE volumes, or a slow server, I wouldn't give it a second thought. As to your question, why not simply change the URL?

Rahul Roy, no.

kuku, 1: if the target page doesn't require it, simply ignore it. 2: Exactly the same way you did with one, except add another bit..
RewriteRule ^(.*)-(.*)-(.*).htm siteview.php?pid=$1
Though I'd probably recommend (.+), which is safer (read: less "hungry"), or perhaps ([^-]+), if you are certain of the number of parts between the dashes in the URL.

Jerry, I do exactly this here at the org, and it goes something like..

RewriteRule ^(.*)/index.htm(l)? /$1/ [r,nc]
I say "something", because I use this only for directory listing readme.htm(l) files. Using .htaccess for index files is certainly doable, but if you have any ($POST) forms, you will probably run into troubles, and so instead I cooked up this..

if (substr($_SERVER['request_uri'], -9) == 'index.php' and empty($_POST)) {
header('Location: http://'.$_SERVER['http_host'].str_replace('index.php'''$_SERVER['request_uri']));

Which I insert into the top of my php init file (called at the start of most of the pages here). Works great.

rookie, it sounds like you simply need to specify a new DocumentRoot, or else create a virtual domain for that folder. Not really an .htaccess issue; more an Apache setup issue.

By the way, I notice "¦" characters in your code (pinching code from Webmasterworld?), remember to switch those for proper pipes "|" in any real .htaccess code.

Alexandre, your first rule is catching the request. To avoid this, use something like ([a-z^/]+) at the end of the first rule.

By the way, (a-za-z) is exactly the same as (a-z). Did you perhaps mean to do (a-zA-Z)?

Faheem, really, your whole project depends on this? Man! You're screwed! But if this is true, it definitely sounds like I should be charging for any reply! smiley for :lol:

Anyway, first realize that the TLD isn't part of RewriteRule matching (it's only looking at the part after the TLD). If you want to capture that, you will need to use RewriteCond %{HTTP_HOST}. More details above.

Then switch out those silly ([^/]+) for plain old (.+) and try again. Better?

Lastly, the &file= sections are redundant. You have already established what the page is. Why repeat it?

Monika, I'm toying with the idea of a new front page that uses clever Javascript to randomly pop up large-text versions of some of my best thank-you's, perhaps following the users mouse, or something. Yours will be there, no doubt! Quite possibly Losh's, too. Terse; I like it!

Moaku, as far as I know, there's no way to keep $POST variables alive during a redirect. You might want to consider converting them to $GET variables (as part of "the main script that internally converts the URL"). When it's all done, you could convert them back.

They could also be stored elsewhere. It sounds like you are doing some server-side scripting there, so perhaps you could grab them, and store them in a file/session variable/etc.

Having said that; I'm curious as to how $POST variables could be transmitted to a non-existent page. To me, the whole problem seems effete.

Harel, I'm not familiar with WordPress, but it sounds like a WordPress misconfiguration - try their forum. If you're sure it's .htaccess troubles, come back and post the actual .htaccess code.


;o) Cor

ps. if your comment was deleted, I recommend you read the HUGE notice above this comment facility before trying again!

Stefan - 28.02.08 3:55 pm

Thanks for this nice overview.

I have probably a simple question :-) hopfully.

I have an index.php which has a forward to a page.php its a kind of pre page for the cms for intros and stuff like this.

Now I want that the page.php will shown up like:

it should be just:

Please can you help me?

cor - 28.02.08 4:28 pm

Yes, and without rewriting (what this article is about)
simply do..

DirectoryIndex page.php

;o) Cor

Stefan - 28.02.08 8:42 pm

Thank you very much. Still I found some very interesting aspects on this site. But you are right I was looking for this.


Neal - 29.02.08 4:36 am

There is a lot of very helpful information on this site. Thank you for making it available. I added the mod rewrite to part of my site where when you enter an it takes you directly to My question is: How do search engines see this? Do they see or


cor - 29.02.08 9:35 am

Yes Stefan, there's lots of useful info kicking around. What you were after probably should have been added to part one (the first page of the series) a long time ago; I've had more than one question about it.

Neal, Google sees what browsers see (except as one long stream of text, as opposed to "seeing", as such). If the domain is ONLY available as, then that's all Google will see. However, if it's ALSO available as, then Google will see that, too. Simply ensure that's not possible.

As I like to say, "Google sees all".

;o) Cor

Neal - 29.02.08 12:58 pm

I have the working as or, but when i try to go to a page as I cannot pull up It cannot find the page.

cor - 29.02.08 3:17 pm

And I cannot find my glasses!
Thing is, I don't even WEAR glasses!

;o) Cor

Neal - 01.03.08 12:55 am

So there is no way to have that kind of functionality?

cor - 01.03.08 11:44 am

On the contrary, it's very doable, and quite common, too.

;o) Cor

ps. I am deleting the comments below this as I type this addendum. Readers of this page are not interested in your tech diary, or rather, diahorrea. After you have read the article, the important, and rather BIG notice above the comments, and searched through all the comments themselves, and still haven't got your solution; feel free to come back with an ACTUAL question, providing all the relevant data, and having already done all the relevant leg-work, yourself.

berny - 01.03.08 5:50 pm

hi cor!

after hours of googling, i didn't figure out a very strange mod_rewrite problem. - then i ended up with your well-written article, but still no solution. - maybe you could help me...

here's an excerpt of my .htaccess file. - everythings' redirects as desired (tested on several browsers on os). - nevertheless, google doesn't index anything. - same problem, if you check my page with the w3c validator. - it gives an 404 error (an example link:

<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteBase /

# BEGIN FAlbum
RewriteRule ^photos/([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?$ /wp-content/themes/connections/photos.php?$1=$2&$3=$4&$5=$6&$7=$8 [L]
# END FAlbum

# BEGIN WordPress
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress


thanks much in advance.

cor - 02.03.08 8:36 am

I suspect the trouble you are having is that (older) HTTP/1.0 requests are failing, whereas normal HTTP/1.1 requests succeed (usually caused by HOST_NAME based redirects - possibly your vhost setup). You can test this with a tool like Sam Spade, get it to send one of each kind of request. However, as far as I know, most all browsers send HTTP/1.1 requests, so it's not really an issue.

I have heard folk complaining about certain WP plug-ins sending the wrong headers, both HTTP/1.0/1.1 mix-ups as well as incorrect 404 headers; but my knowledge of WP is almost non-existent, so I wouldn't hazard a guess at any tweaks, even if they were necessary.

Not validating? Perhaps, when accessed directly, the W3C validator sends an HTTP 1.0 request. I do know that if I use the link from Firefox's HTML Validator (Tidy) icon, W3C validation works just fine for your /photos/album/wok-tum/ page - W3C says it is 100% XHTML 1.0 Transitional (the plug-in actually uploads the browser-rendered source). Try that.

Not indexed? Google uses both HTTP/1.0 and HTTP/1.1, I think; but for sure, your pages ARE being indexed, see here Cor do a search like this). Whether they are ranking for terms you'd like them to, is another matter, entirely in the realms of SEO.

At the end of the day, your WP install/gallery relies on certain .htaccess code being as it is, and it's probably best not to mess about with it too much. Your site works fine, and any anxiety is over something most of us are blissfully unaware of, and even if we were aware, would probably take for granted.

In other words, you have nothing to worry about.

;o) Cor

berny - 02.03.08 11:22 am

hi cor!

thanks for your detailled reply. - you are right, that my photo-root page gets indexed, but all subpages like albums and photos are left out. that's what happens with other pages, which i redirect this way as well.

anyway, you second my thoughts and i will check wordpress (and plugins) as well as contact my webhost. thanks once more.


berny - 02.03.08 1:16 pm

me again. - i solved the problem. - for anybody, who uses wordpress and calls plugins external via including the wp_blog_header (which you need to execute database calls, embed the theme, ...): just manually send a HTTP/1.1 200 OK Header to overwrite the 404 header which has been set by wordpress itself. so, cor, you were right, it had nothing to do with the mod_rewrite.

maybe their is a wordpress function out there, which one can use to tell wordpress, that the 'external plugin' has been executed correctly without changing the core. - i have a look on that later.


cor - 03.03.08 4:06 pm

Ahh yes.. WP plugins! Pesky buggers!

I dunno about being right, as such; but I'm glad my clues were useful to you. Two heads, and all..

At least you have everything working now; that's what matters. And some handy info here for anyone else that might wander by with a similar issue. Cheers!

;o) Cor

Franz - 05.03.08 11:36 pm

Thanks a lot, this tutorial is great. I was looking for something that makes: and so on

i know how i would do that, but only for known amount of parameters and attributes. i want that to be flexible. for none, one or fifty!

keep up your good work, man!

greets from Germany

kai - 06.03.08 7:28 am

hey man, it's kai from 15.02.06. just dropping by to look for the solution you posted from 2 years ago (time flies). nice to see that you are still helping many!
cheers smiley for :cool:

cor - 06.03.08 11:19 am

Well, kai, I help some. Some are beyond help!

Hey Franz, look up the comments a bit, you'll see a rule that does pretty much exactly what you want. Something like (the mydir/ is optional - if you need this rule to cover *all* requests, simply omit that part)..
RewriteRule ^mydir/([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?([^/]*)?/?$ /foo.php?$1=$2&$3=$4&$5=$6&$7=$8 [l]
Technically, if you requested, say,, you would get a query string something like foo=bar&=&=&=, but as the extra (empty) variables are ignored, your script (in this case, foo.php) would receive a single $_GET variable..
[foo] => bar
You could conceivably code in hundreds of "spaces". You can also do it with or without the "=", and create your own variable names in the target URI, ie..
... /foo.php?var1=$1&var2=$2&var3=$3 etc.
Pretty handy.

;o) Cor

Derrick - 06.03.08 6:23 pm


I am trying to take advantage of a bunch of old links that were populated on the search engines from our OLD MIVA ecommerce site using .htaccess rewrite rules. All are working well, except for the following:

I am trying to redirect to:

My redirect rule keeps getting lost at the ? following the merchant.mvc as I "think" it is interpreting the ? as a rewrite separator...

Is there a way to escape the ?

Here is what I have tried unsuccessfully:
RewriteRule ^mm5/merchant.mvc?Screen=PROD&Product_Code=?ABC123?$$2

Thanks for any insight you can provide!

Derrick - 07.03.08 1:46 am

I realized my understanding of the ? was incorrect. It was the regex ? that confirms 0 or 1 instance of the previous character. No chance of working!

I ended up going down a slightly different path, but figured out where most of the issue is. I had to use %{QUERY_STRING} to get the entire line including the parameters that were being passed after the ?.

I converted to using a couple of RewriteCond's and a RewriteRule instead:
RewriteCond %{REQUEST_URI} ^/mm5/merchant.mvc$ [NC]
RewriteCond %{QUERY_STRING} ^Screen=PROD&Product_Code=ABC123$
RewriteRule ^.*$

I don't have the Product_Code generalized yet, so I have coded the couple of entries I am concerned about for now and will pass as variables when I figure it out (hopefully tomorrow).


cor - 07.03.08 7:46 am

Hi Derrick.

Your first mistake; and it's a most common one; is that you are conceptualizing the rules back-to-front. You want to redirect FROM, in other words; from the short URL (which the user types into their browser) to the long URL (in the background, so the user doesn't see it).

This might seem like a trivial distinction, but is the root cause of a great many rewrite problems. If what I think you are trying to do is correct (i.e. create "short" aka. "flat", aka. "friendly" URLs), you need only do something like..
RewriteCond %{REQUEST_URI} !mm5/merchant.mvc [nc]
RewriteCond %{REQUEST_URI} ^/(.*)$ [nc]
RewriteRule ^(.*)$ mm5/merchant.mvc?Screen=PROD&Product_Code=%1&Category_Code=R 
Which will work great, so long as ALL your links are for Screen=PROD, and Catagory_Code=R; i.e. these two variables are fixed. You can probably see what's going on; all requests NOT for mm5/merchant.mvc (i.e. all short URLs) are redirected to mm5/merchant.mvc using the product code %1, which we capture in the RewriteCond. In our example URL, that would be ABC123.

Remember, there is no QUERY_STRING in the original (flat) URL, so you can't use it in RewriteCond statements; the whole point of flat URLs is to NOT use a query string! QUERY_STRING only exists after we create it, with our RewriteRule.

For greater flexibility, you will probably want to incorporate these other variables into your short URL, which could instead look something like.. (though maybe small case, huh?)

The rules for this aren't much more complex..
RewriteCond %{REQUEST_URI} !mm5/merchant.mvc [nc]
RewriteCond %{REQUEST_URI} ^/([^/]*)/([^/]*)/([^/]*)$ [nc]
RewriteRule ^(.*)$ mm5/merchant.mvc?Screen=%1&Product_Code=%3&Category_Code=%2
Here we capture all three variables (which must be supplied in the correct order in the short URL), and use the captured variables, %1, %2, and %3 to build the query string in our target URL (in no particular order - so long as the target script (merchant.mvc) receives the three variables, it won't care about the order in which they arrive).

I don't know how Miva works (or even what it is!), so perhaps Screen and Catagory_Code are permanently fixed, and the first set of rules is all you need, but I figured it was a good opportunity to explain how to take it a step further, if required.

for now..

;o) Cor

Richard - 07.03.08 10:48 pm

Hi there, this is a great tutorial and has helped me a lot. I have been looking for information like this to help me with a problem on my site.

I already have a gaming section on my site at but I am now creating a library of game reviews. The game review URLs currently look like this because of the plugin I am using to create them:

In this example, it is a PSP game called Exit.

I want my URLs to look something like this instead:

I have added the /game/ extra level to make sure I don't bump into any of the existing /gamer URLs.

No matter what I do I get an Internal Server Error, can you give me any advice?

cor - 07.03.08 11:54 pm

A 500 error means there's an error in your .htaccess code.
My advice would be to fix that error.

If you can't spot it, post the actual code you are using; perhaps I can help you pin it down.

;o) Cor

imachine - 17.03.08 12:48 am

How can I use mod_rewrite to achieve the urls similar to stumbleupon

I pretty much would like to rewrite to

Any help would be greatly appreciated. Thanks.

cor - 17.03.08 3:14 pm

imachine, firstly, you will need to have wildcard subdomains set up for your domain. That's the most important thing, or else requests for will never reach in the first place.

After that, it's fairly straightforward rewriting, and I'm fairly sure everything you need is already here. Go for it!

If you have any problems with the .htaccess code itself, drop it here, and I'll have a look at it with you.

;o) Cor

bill - 17.03.08 5:36 pm

Great resource!

I have a question about something that seems simple, but cant find any info at all.

What if you want to have your page read /blog/ instead of /blog.php or /blog

What would you need to put into .htaccess to get that ending /

Thanks for the great article!

matt - 19.03.08 5:18 pm


I'm having a problem that I can't figure out. I started using mod rewrite several months ago with this ...

Options +FollowSymLinks
RewriteEngine On
RewriteBase /encoder-repair/
RewriteRule ^([^/]*)\.html$ mfr.php?aid=$1 [l] 

This rule worked fine for about a month. Then I added a second rule producing this ...

Options +FollowSymLinks
RewriteEngine On
RewriteBase /encoder-repair/
RewriteRule ^([^/]*)\.html$ mfr.php?aid=$1 [l]
RewriteRule ^([^/]*)/([^/]*)\.html$ model.php?mfr=$1&model=$2 [l]

Everything went fine, no errors when I access the site, no complaints from customers.

Two months later I check my Google Sitemaps account and see many "500 Internal Server Errors". I go back through my logs and see the errors started the day after I added the second rule, and, its only happening on web crawlers. There are successful Googlebot crawls, and ones that get a 500-error. Same with Yahoo Slurp.

Please help. I can't reproduce the error. I make a change then wait for the host activity logs to see any improvements. So far I'm striking out!!

cor - 19.03.08 7:13 pm

bill, simply put your blog into a folder called blog, and have its main page as index.php, index.htm, or index.html. Then Apache should take care of the rest. If that's not possible for some reason, and you still need help, provide more details about what your blog page is.

matt, is that RewriteBase really necessary? Generally speaking, mere mortals don't need it, and if they do; it's usually a sign of trouble elsewhere.

Without seeing your error logs, it's difficult to hazard any more guesses. Have you looked at your error log? Knowing exactly what requests throw up the 500 error will be of great help to you. Not the access log, the error log.

;o) Cor

Rob - 01.04.08 5:44 am


Thanks I have read this and all the comments its been very helpful so far. But I have a problem my url is

RewriteEngine On
RewriteRule ^([^/]*)\.html$ /artist-listing.php?artist=$1

But this gives me a URL of de Vlaminck.html

When what I really need is

I promise I have read your article and I am sure the answer is there I'm just to new at this to work it out


cor - 01.04.08 10:19 pm

What I think you are trying to do (given the general gist of your post1, and the current linking system of your site2) is have URLs with dashes, e.g. Maurice-de-Vlaminck.html transparently converted to URLs with query string with spaces in them, e.g. artist-listing.php?artist=Maurice de Vlaminck.

Two things concern me about this. Firstly, that artist-listing.php would prefer spaces to dashes; the former creates headaches; and secondly, that your back-end can create these friendly, flat .html links in the first place.

However, I'll assume that you have these things covered, and suggest you do something like (which would convert links with two dashes)..

RewriteRule ([^/]*)-([^/]*)-([^/]*)\.html$  /artist-listing.php?artist=$1\ $2\ $3 [L]

If you need to capture more or less dashes, put rules above (4, 3, etc.), and below (1) to catch the other possibilities. There may be a more clever technique, but my brain is in recovery today, sluggish.

If I've misunderstood entirely, ask again, being specific about the precise link the user will see and click on the page, and in their browser address bar; and exactly what URI you want your handler to accept; and I'll have another look.

;o) Cor

1 note: I genericized the last URL in your post
2 Which is actually mixed - some of your links have dashes, some spaces, so I'm not 100% about which variant is your preferred target. Most had spaces, though, so I've assumed this for my response. I have also assumed you required the [^/] conditional for some future purpose, and used that, too.

Rob - 02.04.08 12:46 pm


My current file and database works using this url as the artist field is populated with spaces between the names in the database.

What I want to be able to do is have a link thai looks like this

convert to the original link so that it searches the database correctly.

So users will see but it will convert to server side

I am hoping this will make my links more search engine friendly. de Vlaminck.html will not work well as a link for the search engines as I understand it.

Thank you again for any help


fahim - 02.04.08 9:31 pm

Great article! Thanks!

cor - 03.04.08 11:32 am

Rob, that's what I assumed for my solution! The code I gave you will do exactly that!

All you need to do now, is have your back-end create links with dashes. Can it do that?

As to the SEO aspect, Google doesn't care either way. Dashes have pretty much always been interpreted as spaces, spaces obviously always are, and now even underscores are seen the same way.

It's six and half a dozen - do whatever feels comfortable for you.

;o) Cor

Rob - 04.04.08 5:08 am

Hi Cor

Will use this in the PHP to change dynamic links

<?php  $artist=ereg_replace" ""%20"$artist );


Thanks again


cor - 04.04.08 5:12 pm

Rob, that seems a tad wonky, but I'm sure you know you're back-end better than I do!

All the best!

;o) Cor

Ros - 10.04.08 9:28 pm


I created a simple code to urls from domain(
to a subdomain.( which is a wordpress blog.

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]

I'm having trouble getting stats data.
The 'stats' folder and url( that is on the main domain. is unable to get accessed

Is there anyway not to redirect the stats?
I'm a newbie to all this coding. your advise and help is most appreciated!
Thanks in advance!

cor - 11.04.08 5:37 am

Hi Ros.

The problem is that all requests are being rewritten to You second line should probably read..

RewriteRule ^(.*)$$1 [R=301,NC,L]

Note the extra "L" in the flags. I say "probably" because I'm confused as to why you would first remove the "www" part, and then rewrite all non "www" URLs to Is this really what you want?

Anyway, if you add the "L" to the flags, a request for will be rewritten to and stop there (L meaning "Last Rule", or "do no more rewriting"), and you will see your stats.

I suggest you have another look at the whole thing. As it stands, in order to access the main domain, you have to add "www", which is then removed. If a user then bookmarks this new URL (with no "www"), they won't get back into the main site, but will instead be redirected to your blog!

Again I say, are you sure this is what you want?

;o) Cor

Lucie - 14.04.08 6:33 pm

Nice tutorial, Thanks dude smiley for :)

Emil - 14.04.08 8:20 pm

Hi everybody.
I have a website in php(smarty, FCKeditor) and everything works fine on localhost(using XAMPP, folder htdocs). I create a folder newsite under htdocs and move all content to this folder and now is not working anymore(I'm doing this because I want to have more websites on the same I need a folder for each website). I'm spending too many days looking for an answer and I hope you guys can help me. Please help me with suggestions.
Thanks in advance and this site is great.

php_value display_startup_errors On
php_value register_globals 0
php_value magic_quotes_gpc 0
RewriteEngine On
#flash xml:
RewriteRule header.xml index.php?vars=flash_xml
#general rewrite rule:
RewriteCond %{REQUEST_URI} !^/admin
RewriteCond %{REQUEST_URI} !^/include
RewriteRule ^(.+)\.html$ index.php?vars=$1 [L]

cor - 15.04.08 12:57 am

Emil, firstly, posting the same question on multiple pages isn't going to increase the likelihood of getting an answer; quite the opposite, in fact. It took sheer willpower not to delete this one, too.

And as far as I know, "not working anymore" is not an Apache error message. Is that from your error logs? Have you even looked at them? That's where you start when things break down, you know. You knew about the error logs, right? Actually, start here. THEN read your logs, and get the information you need to ask a decent question.

Multiple sites on one host. You mean Virtual Hosts? If you don't, you'd better head along here, and make some.

And this "htaccess:" you posted, is that in the root? Or the sub-folder? Have you tried things without it? In fact, have you done anything at all to troubleshoot this? You didn't say.

Lastly, perhaps you noticed the huge notes above these comments, entitled "Before you ask a question..". The idea is that you read that before you post. Skipping over text is probably how you've managed to waste days tackling a single tech problem. This isn't brain surgery, but you gotta RTFM.

A few suggestions for you!

;o) Cor

Ros - 15.04.08 10:14 pm

Hi Cor,
Thanks for the advise.

I see what you mean.
I want to just rewrite to and not have any requests for

Will add L to flags so essentially I just need to have:
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc,L]

Appreciate your advise!

AbdulGafoor - 16.04.08 6:24 am

Very useful information for web developers.

cor - 16.04.08 6:53 am

Yup, Rosa, that looks fine.

Requests for and will pass through unmolested, but requests for  will be redirected to your blog.

;o) Cor

SoupyC - 17.04.08 6:49 pm

Excellent explanations of htaccess, especially to someone like me who hasn't a clue! My problem is...

I have a domain, say

I also have 2 sub-domains, say and

I want to re-direct to but I want to be handled as normal.

When I try to write the htaccess file, I can get to re-direct to, but when I try it seems to re-direct to

Please help!

I'm currently using this...

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]
rewritecond %{http_host} ^ [nc]
rewriterule ^(.*)$$1 [r=301,nc]



cor - 18.04.08 1:01 am

SoupyC, a single ruleset should be enough..

RewriteCond %{http_host} ^ [nc]
RewriteRule ^(.*)$$1 [R=301,L]

No? Also note the "L" flag, so no further rules are processed. Your second ruleset is surely a big typo, anyway.

;o) Cor

SoupyC - 18.04.08 11:17 am

Thanks for the reply Cor. Logic would tell me that what you said should work, and I had previously tried that, based on what your actual article had said, however, maybe I didn't define my problem well enough.

On my hosting, I have my root folder, where the points to.

Within that, for my subdomains, I have 2 folders / and /

I think it's because these sub-folders are under my root folder, that it's causing the problem...but I can't be sure.

When I apply what you have said in the htaccess file, going to results in a 404 page not found (as there is no index.htm) and goes to the right place, as does sub2. It appears the .htaccess file makes no difference!

One question though, does my DNS affect this? If I change the .htaccess file but my DNS server has a record in the cache, would it make a difference or does .htaccess come after the DNS?

Many thanks,


cor - 18.04.08 11:37 am

Yes, .htaccess comes way after the DNS. But so long as the name servers are pointing all those domains at your site, you can do what you like after that.

As to your issue, it looks like you actually want to redirect users transparently; so you'll need to remove the R=301 business, and external targets (http://something). As I said in the article, NEVER use R=301 until AFTER you have everything working 100%. Your biggest problem now is going to be that you may fix the issue, and as the 301 is still in effect; you will still be redirected there. You might want to use a new browser for your next set of tests, after you remove the 301, that is.

My examples in the article are what you need..
RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^/one
RewriteRule ^(.*)$ one/$1 [l]
But actually, I'm not entirely sure, because, like you said, maybe you didn't define your problem well enough.

Think in terms of the browser request, the links on the pages, the real file system paths, and what the user sees in their address bar, e.g..

I want to put links on my site like "" and have them translated in the background to the "bar/" subfolder in the root of my site, while "" stays in the user's address bar.

or whatever. I'm confused by why you want to be redirected to at all, and yet still access directly. Are you using the www, or not? If not, why not remove it from the equation altogether. And if you do want it, why are you redirecting those requests to a different host name?

But like I say, I don't entirely understand what you are trying to do.

;o) Cor

SoupyC - 18.04.08 3:55 pm

Cor, thanks once again for your time. I'll try and explain what I want in those terms and hopefully all will make sense.

I do not use at all. I only want those users that happen to type in to be re-directed to and I'd like to be in their browser. That is because I do not use www at all and want anyone that happens to type that in, to be redirected to For that matter, I would also like that if they typed in their browser, it too would point to

In summary:

- User types it redirects to the / folder and displays in the address bar
- User types and hosting provider already handles it being redirected to / folder so nothing is needed in htacess (as far as I'm aware!)
- User types and like above, the hosting provider already handles it being redirected to / folder so nothing is needed in htacess for it either.

Does that specify it any better?

Thanks again,


cor - 18.04.08 4:29 pm

Hmm. This takes us right back to my first reply! It's basically a variation of the lose the "WWW" ruleset. And you can easily (theoretically!) redirect and to with only this..

RewriteCond %{http_host} ^(www\.)?abc\.com [nc]
RewriteRule ^(.*)$$1 [r=301,nc,l]

If that doesn't work, it probably means that the "hosting provider already handles it" is somehow messing with your rewriting. They are probably using mod_rewrite to create these subdomains, but unless we can see exactly what they are doing, it's difficult to know for sure. This may well explain why you are having so much difficulty getting things working.

It might be best to take it up with your system admins. They might even insert your own rewrite rules for you, directly into the vhost setup.

Many hosting panels enable you to do this yourself. I currently use Plesk for, and it allows you to choose to have domains with or without the www (personally, I have it with with www, to catch incorrectly typed URL's, and then redirect it myself to plain old with the rules in the article).

By the way, I've just noticed that the [pre] tags convert the flags to lower case. I'll need to look into that - something in the bbcode parser. I meant to use [R=301,NC,L], I prefer uppercase flags these days; more readable. Remember though, no "=301" until after it's working.

Anyways, I'd be interested in hearing how this turns out, along with more details about your hosting setup, type of control panel, etc.

Good luck!

;o) Cor

SoupyC - 18.04.08 5:46 pm

Had you not already guessed I'm a total n00b at this stuff, lol! With that said, I tried putting in the htaccess and it didn't work. I'm now thinking that you saying how my hosting provider is messing with it makes sense!

I'm using GoDaddy as my domain management, and hosting provider...not sure if that answers what hosting panel I'm using. From within there, I set up my subdomains, but can't see any options about www and non-www issues.

At the minute, I can live with how it is, as it's a small blog I'm running but it would just be nice if I could have that I like to learn new things and this whole process has taught me a lot I didn't know!

It now seems that where the .htaccess file WAS making a no longer is. When you say not to put in the R=301 until it's working, is that because it leaves a trace in the browser. I'm using Firefox now but I tried changing to IE (last used a couple months ago before I started fiddling with the htaccess) and it produces the same result (i.e. none!)

I'll keep digging and experimenting and let you know how I get on.

Thanks for all your help! smiley for :D


cor - 18.04.08 6:07 pm

Ahhh.. gogaddy! (insert muttering and swearing noises)

Being a n00b isn't a real obstacle, however godaddy hosting might well be. It's not real hosting, at least; I've heard enough horror stories about their .htaccess (and in particular, mod_rewrite) support to know it's not real enough. Basically, it's a "value add-on" for their domain packages. They (wrongly) assume that if you are noobish enough to pick them as your host, you won't have the savvy to even realize things like mod_rewrite exist.

You might want to consider a different host. I don't think mine is taking on new clients right now (it's like a wee family), but I do know that there are lots of really good deals out there, I mean like $10/year. Being small now, doesn't mean you always will be - it's never too early to get a decent web host.

Happy hunting!

;o) Cor

ps. if you need to use IE occasionally, Google: IETab.

Pete - 19.04.08 4:31 am

I goombled across this article and it is excellent - thanks..

I have hit an issue uploading 'generated' HTML files from a Visio chart and finding that it creates "\" not "/" in any links in the diagram. this works in IE, but breaks in firefox, firefox translates it to a "%5C" which breaks the link.

So I need to convert a "\" or a "%5C" into a "/" in the .htaccess, to assist firefox.. any ideas?

Thanks for any help

cor - 19.04.08 5:18 am

Weird. I'm guessing Visio is some Microsoft product. smiley for :roll:

Convert backslashes to forward slashes. Hmm. Something like this should work..
RewriteRule ^([^\\]*)\\(.*)$ $1/$2 [NC]
Though without more precise details about the nature of the links, full paths and such, I wouldn't bet money on it! This is a transparent rewrite, so you would still see the %5C in the browser. You could do it externally, too, though I'll leave that as an potentially interesting exercise for you!

;o) Cor

Hikari - 19.04.08 9:56 pm

Hello, very nice tutorial you have here

I'm trying to make a redirection here but I'm not having success at all. I have a wordpress blog and 2 domains, and Currently, is being 301 redirected to

I'd like that both domains could be used to show my blog content. I suppose that could be done with parked domains, but on my host service both domains are set as addon domains. And anyway, wordpress insists to redirect users to its main domain if it is accessed from any other domain.

So, what I wanted to implement with htaccess, is a trick to spoof wordpress, so that users can access from, keep shown on browser address bar, and wordpress thinks it is being accessed from

I tried this
RewriteRule ^(.*)mydomain\.net(.*)$ $1mydomain\.com$2

but it didn't work, it is like wordpress knew it was being accessed from and redirects to

Do you know if this can be done?

cor - 20.04.08 7:47 am

Almost anything can be done, but having two domains display the same content is SES (Search Engine Suicide).


;o) Cor

SoupyC - 21.04.08 4:03 pm


Thanks for the advice. GoDaddy is where I registered my first .com domain, so naturally it's where I registered my first hosting account. That is the only reason, though I will keep your advice in mind when renewal time comes (or before then if I'm getting particularly annoyed!). I already have IETab but wasn't sure how much of IE it uses (or maybe how much of Firefox it uses I suppose!)

I used IETab to view it, and then standalone IE to see if there was any difference. Sadly there was not!

Your site has been added to my bookmarks and I have no doubt I'll be visiting often!

Thanks once again,


cor - 23.04.08 3:21 pm

SoupyC, I registered my first domain with godaddy, too. A mistake*. But I've never had hosting with them. You don't need to host with your domain registrar. Most folk don't.

And IETab uses ALL of IE. Being the system browser, you can embed it inside things, but it's still IE. Lots of Windows web browsers are just IE in a new skin.

See ye around!

;o) Cor

*I eventually switched to - who are superior in every way.

Geeta - 24.04.08 8:17 am

I want a redirection such as
I have domain where all the files are kept suppose
Now I have another domain say
Now whatI want is when I type another domain name i.e.
the files execution should be from That means the url should be but the internally the site is shown.
Can we write mod re-write for it?
I tried in manier ways but I could not....
Kindly help me

cor - 24.04.08 12:13 pm

Geeta, what ways did you try, exactly?
(that means show me the code!)

Also, if you want help, you will need to supply all the information needed to help. I would probably have lots of questions, like.. Are the domains hosted on the same host? Are they on the same server? Or are they in the same folder? Or what? Does the DNS point the domains to the same location. Do you own both domains? Do you also want to be able to access directly?

And so on.

;o) Cor

Minty - 26.04.08 6:29 pm

Okay so here is the problem, in my site the following pages work with clean URLS (used to be a screen like x.php?screen=0)

But I cannot get the link: (1,2,3 etc)

I have an "avatar" section on my site were people can browse and choose the series they want to look at. However they can't change the pages because I keep on getting errors!
here is my code:

:Options +FollowSymLinks -MultiViews 

RewriteEngine On 

RewriteCond %{SCRIPT_FILENAME} -f [OR] 
RewriteCond %{SCRIPT_FILENAME} -d 
RewriteRule .* - [L] 
RewriteRule x/series/(.*[^/])/$ /x.php?series=$1  [L] 
RewriteRule ^(.+)/([0-9]+)/?$ /$1.php?screen=$2 [L] 
RewriteRule (.*)/(.*)/(.*)/$ /x.php?series=$1&screen=$2 [L] 
RewriteRule ^(.*[^/])/?$ /$1.php [L]  

dMan - 28.04.08 10:51 pm

Hi - Great site!

heres my current setup:
I have a database with sku ids which have corresponding links.
sku id in my database is: google
and its corresponding link is:

so when a vistor clicks:
they go to:

It would really be nice to accomplish the following:

(below is how my links are currently setup) (goes to)

(below is what I wish could be done) (goes to)

so basically take the sku id, then put .html on the end and wellah!

I really hope you can help. But if you can or can't, I'm still grateful for you takin' a look. =)

Thanks again,

cor - 29.04.08 11:38 pm

..back from my own tech issues..

Minty! What is THAT!?
The first error probably comes from the colon ":" in front of the Options statement. That's gotta be wrong.

Next are these crazy (.*[^/]) sections. Surely you mean.. ([^/]*) The bracketed conditions replace the "." character in the more usual (.*), you see.

Thanks dMan. Your desire is fairly trivial to achieve, something like this should do the trick..

RewriteRule ^(.+)\.html$ /go.php?sku=$1 [L]

;o) Cor

Flavio - 02.05.08 7:41 am

First of all, congratulations for this great article.

Back to the main theme... I've been wondering if this would be the best solution to deal with validation (W3C) when using PHP based url queries. The use of the ampersand is the main problem because it's a reserved character.
So I was planning something like redirecting the urls through .htaccess manipulation.

Do you believe this is a good solution for this problem?

Thank you,


cor - 02.05.08 8:46 am

The best solution would be to use..
&amp; your page links.

;o) Cor

Flavio - 02.05.08 5:47 pm

The thing is I've been a little confused when I read this article:
I used to don't care about web standarts and validation stuff and tableless, but now I'm seening how important is.

cor - 02.05.08 8:03 pm

You're right; all these things are important. And it's good that you care. However, this particular issue isn't of great importance because almost no one uses trans_id anymore, mainly because it's so insecure.

The article in question also gives solutions that you can use in your .htaccess, aka. "Apache directives". i.e..
php_value arg_separator.output "&amp;"
But by far the best solution is to disable trans_id altogether..

php_value session.use_trans_sid 0


php_flag session.use_trans_sid off

which is also shown in the article.

;o) Cor

ps. this now has nothing to do with rewriting, and so should probably be on page one! smiley for ;)

Faisal - 05.05.08 8:35 am

Thanks for sharing your knowledge with us. Here is my question after having done several tries.

This is the URL I want to get translated

After rewrite, it should look like this
(about_us is the cat title so it will change with every argument)

However, I have achieved the following.

I have used the following line of code to get this result.
RewriteRule ^detail/(.*)/(.*)$  /sitewonders/index.php?pg=detail&catId=$1&catTitle=$2 [nc]

What my requirement is that I dont want to show detail and 8 whereas detail is the page where my codes are stored and 8 is the product category.I have no clue how to get hold of this. the <a href> code used to call is as follows.

<a href="<?=$webPath?>detail/<?=$viewcat['pk_id']?>/<?=str_replace(' ', '_', $viewcat['cat_Title'])?>.html" class="b">

Please give me any clue or help to achieve this target.

Derick - 05.05.08 12:56 pm

Your article was very helpful.

I have a problem of creating url as following as

jouets-1er-age - means category name that is "r=37" in the url. So I have to get the category name from database

puericulture - means sub category name that is "sr=38" in the url. So I have to get the sub category name from database

can you please explain how should I use mod_rewrite to do that work.


cor - 05.05.08 1:59 pm

Faisal, if the parameters aren't in the original (flat) URL, they won't be available to your script, so you need to have them somewhere. Your rewrite is fine, and the flat link is probably as small as it can be.

Derick, everything you need is in the article. Have a read. If you still can't achieve your goal, get back here and post the actual code that isn't working, and I'll have a look at it.

;o) Cor

Derick - 06.05.08 5:23 am

Thanks cor. I read this article and I have developed the code. But I didn't get the correct file. It redirect to index.php always but the name is correct. as

My code of .htaccess is;

php_value register_globals off

RewriteEngine on
Options +FollowSymLinks

# RewriteBase /
# Rule for duplicate content removal : vs
RewriteCond %{HTTP_HOST} ^ludo [NC]
RewriteRule (.*) http://localhost/ludo/$1 [R=301,L,NC]

#RewriteCond %{REQUEST_URI} ^(/r/sr) [NC,OR] ##optional
RewriteCond %{REQUEST_URI} (/|\.htm|\.php|\.html|/[^.]*)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php

Please look at my code help me. I appriciate your kind help.

cor - 06.05.08 8:15 am

Sheesh! Derick, I didn't mean your entire site! <snipped> !

That .htaccess code is a mess. It's like you just threw characters into notepad and hoped for the best. I'm not gonna teach you the basics, dude! I already wrote a big article to do exactly that. Really, have a read, except this time; slowly.

Here's my advice: START AGAIN!

;o) Cor

ps. hints: you only put brackets around characters you want to capture. Look again at my examples in the article, and the many many good examples (my replies) in these comments, and you'll get the idea - there are many examples that are probably exactly what you need. Good luck!

Dman - 06.05.08 9:50 am

Hi Corz,
thank you for helping me in my last post.
It works GREAT! I've read through the comments page and it seems
like mod-rewrite only works with variables and not static filenames.

Here is what I'm trying to do now.
My page has about 6 different category links which go to their individual category page.

These category file names begin with go + (3-5 random numbers) + .html
Below are a few examples to give you a better idea:


These are all direct static links which represent specific categories.
And here is what I'm trying to do:

go245.html --> (rewritten to) --> cars.html
go1256.html --> (rewritten to) --> boats.html
go15460.html --> (rewritten to) --> trucks.html

Each link is static with none of that variable or wildcard stuff.
Below was my feeble attempt to make it work and both failed..

RewriteRule cars.html /go245.html [L] (didn't work)
RewriteRule ^cars.html$ go245.html [L] (didn't work)

you see - because these are static links I dont think using
variables like $1 or ^([^.]*). is going to work in this situation.
but what the heck do I know - I need an expert and
I sure would be grateful for your expertise.

Thanks again,

cor - 06.05.08 1:09 pm

Dman, mod_rewrite works with URL requests. Any part of it; dynamic parts, static parts, user agents, protocol version, you name it.

Anyway, are you sure this..

go245.html --> (rewritten to) --> cars.html

Isn't meant to be this..

cars.html --> (rewritten to) --> go245.html

That is, the link (or what the user types into their address bar) would be "cars.html", and the real, server-side page would be "go245.html". Right? Back-to-frontness is very common in mod_rewrite questions.

If so, there's no reason why your first example wouldn't work..

RewriteRule cars.html /go245.html [L]

Requests for "cars.html" would be redirected to a file called "go245.html" in the root of your site. Looks fine.

If it doesn't work, then perhaps another rule is catching it before it gets to that one.

;o) Cor

Dman - 07.05.08 9:44 am

thanks Corz,
wow, I think your "right on target" once again. I bet my first example (attempt) wasn't working because of what you said. Because I do have other lines in my .htaccess file. Heres what it looks like:

RewriteEngine On
RewriteRule ^go([^.]*).html /index.php?link_id=$1 [L]
RewriteRule ^([^.]*).html /index.php?search=2&query=$1 [L]
RewriteRule ^([^.]*).shtml /go.php?sku=$1 [L]

RewriteRule cars.html /go245.html [L]
ErrorDocument 400 /400.htm
ErrorDocument 401 /401.htm
ErrorDocument 403 /403.htm
ErrorDocument 404 /404.htm
ErrorDocument 500 /500.htm


The above example is what my htaccess file looked like which failed to work. Notice the 4th rule down. So could this be not working due to the other rules above it? Or what catches your eye? Thx again, D.

Praetor - 08.05.08 1:51 am

Great article....... learned a few things. Used the .htaccess in my includes folder. Works like a charm. Used the same in my css folder. No joy! Will have to leave that one alone. Now, if I can figure out how to do rel="nofollow" in the .htaccess, I will be in business.

Thanks for all the information.

Derick - 08.05.08 8:37 am

Dear Corz,

Thank you for your advice for the last post.

Still I am learning mod_rewrite. Now i got the things littlebit and now working my redirections.
But I have a two problem

1) Once I have create link as folders images are not loading and all paths taken from the current virtual folder.

RewriteRule ^jouets-.*-([0-9]+)/.*-([0-9]+)\.html$ /jouet-test.php?r=$1&sr=$2 [L]

2) I want to remove "r" value 37 and "sr" value 38 from the URL ( If I remove those the jouet-test.php loaded without data. That means "r" and "sr" not set. How can I do this?


I appriciate your comments and suggestions.

cor - 08.05.08 9:18 am

Notice the 2nd rule down.
smiley for ;) Wooosh!

Praetor, rel=nofollow is evil.

Well, okay, I guess it has its uses, but .htaccess-automatic? That's just Wrong! I only see a use for it in temporary situations, as in, before the webmaster reviews a public comment, personally. All other uses seem anti-web, to me.

I remember the buzz I got when I first spotted someone had dropped a Wikipedia link my way, and how my heart sunk when I read the source. rel=nofollow. Some kind of bandwidth-eating joke, and I fell for it! smiley for :erm: Still do…

Derick, if more than one page use either the phrase jouets-1er-age or puericulture in their flat-link, then you need those numbers in the flat-link.

In other words, unless you have a database of word->number mappings that equates jouets-1er-age -> 37, and jouets-something other phrase to 38, something else again to 39, and so on; which you don't appear to; then you cannot remove the numbers. You need them for the regex back-references.

If you want to re-use jouets-1er-age or puericulture in your flat links, then you need to keep the variable numbers inside the flat link, so mod_rewrite has something with which to populate the r and sr variables in th e target URI.

That's me said the same thing three different ways! And again, just in case..

If my flat link, the one the user sees, is foo.html, and I want the user to actually get bar.php?var=38, then I need to get the 38 from somewhere. It can either a) come cleanly from the flat-link, in the style of /foo/38.html, or foo-38.html, or foo38.html, or something like that. Or b) a file/database table/etc. exists somewhere, where bar.php could look to know that, for example..


and so on, and know that "foo" = "38", and the only time that I would use foo in a flat-link, is when I want to get the user to bar.php with var set to 38. Mod_rewrite is very like magic, but you can't just magic variables out of nowhere!

;o) Cor

cor - 08.05.08 9:37 am

I must add, and quite literally, to this page; a link to my php debug script, I might even do a proper section about it, in lieu of its own page one day, as all these sorts of things should have.

Inside the archive (McAfee reports all downloads at are 0 on the nuisance meter, Green for go!) are two files, a regular back-end version (which spits variables to a real file, and is mostly used to capture and display debug output from inside php scripts), and a "report" version, which is most handy for .htaccess.

What's it for? You ask. Simply, it spits out a big page of stuff; the entire $_SERVER[] array, variables available to the script (say that when you're drunk!), that is; your captured variables, I sometimes drop a link to it into tech-support emails, and invariably folk get back with some positive comment, often a plain old "Wow!". It is handy.

Usage is simple; you make it your target page, so in a rule like this..

RewriteRule ^(.*)\.html$ catch-all.php?var=$1

You would have a copy of debug-report.php renamed to catch-all.php, and type foobar.html into your address bar, and with yer mojo working, debug-report.php leaps into your browser with a shit-load of exactly the sort of information you need to figure out all this stuff. When I'm messing with mod_rewrite, it saves me lots of time. Read-out. And it's free.

I'll drop a link right here, too, by way of motivating myself to get the URL into the clipboard, and in the Style of Brian Tracey, handle every piece of paper only once..

for now..

;o) Cor

Derick - 08.05.08 10:10 am

Thanks Corz.

I got trick now.

I have another problem. When I create links as

RewriteRule ^jouets-.*-([0-9]+)/.*-([0-9]+)\.html$ /jouet-test.php?r=$1&sr=$2 [L]

But "jouets-1er-age-37" directory is not there. So the all images are not loading.

Can you please advice for me.

kmm - 09.05.08 2:05 pm

Great info been really helpful trying to get a handle on rewrite/redirects.

Ok before I pull what little hair I still have out please have a look at this for me.

I want to redirect http://www.domain/?p=about_us to http://www.domain/aboutUs2.php

My .htaccess:
RewriteEngine On

rewritecond %{http_host} ^domain
rewriteRule ^(.*) http://www.domain/$1 [R=301]
rewriteRule ^linkmachine/(.*)$ http://www.domain/?p=linkRedirect [R=301,L]
rewriteRule ^blog/(.*)$ [R=301,L]

rewriteRule ^about(.*)$ http://www.domain/aboutUs2.php [R,L]

IndexIgnore *

ErrorDocument 400 /a1Whoops.html
ErrorDocument 401 /a1Whoops.html
ErrorDocument 403 /a1Whoops.html
ErrorDocument 404 /a1Whoops.html
ErrorDocument 500 /a1Whoops.html

All the other rules work fine except this one and I cannot see why. I think it has something to do with the criteria being in the query string but heh I'm really out of my depth here
Thanks in anticipation of help!

Jamie - 13.05.08 1:23 pm

Thank you very much.. Finaly an understandable tutorial on .htaccess and Rewrite!

cor - 13.05.08 2:39 pm

Derick, that isn't an .htaccess problem, that's your back-end. If jouets-1er-age-37 isn't a real directory, you can't create "relative" links to images and such on page with a virtual URI. The user's browser has no idea you are using mod_rewrite.

You'll need to either use full links to the images, from the root of the server (i.e. begin <img src="/...), or else use more rewrites to redirect image requests to the correct folder. There are other solutions.

kmm, correct; you are incorrectly attempting to capture parts of the query string. Two things are wrong with your code..

Firstly, you do not understand the usage of anchors; that is, the "^" and "$" characters in the pattern part of the rules. Using code you don't understand is a recipe for disaster!

Along with some other improvement to that section, I have enlarged the regex special character descriptions, among these you'll find..

An anchor explicitly states that the character right next to it MUST be either the very first character ("^"), or the very last character ("$") of the URI string to match against the pattern …

In light of this information, you will see that the anchor in your first RewriteRule is completely superfluous, and the one in your last RewriteRule is what tells me you don't understand your code. A request for about.php?foo=bar would match your rule, as "about" is at the very start of the URI. See?

I'm assuming you are catching legacy inward links, or something - you can use Rewritecond, to check for the existence and value of the p variable..
RewriteCond %{QUERY_STRING} p=about_us
RewriteRule !aboutUs2\.php /aboutUs2.php [R,L]
Which matches all requests that have the p query variable set to about_us, that haven't already been redirected to aboutUs2.php

If you really need it to be an external redirect, simply tag the http://domain part back on.

By the way, you may be interested to know that I also recently added a new section about capturing variables. A good read for all! Feedback welcome.

Hey! Jamie, you finally got here!

;o) Cor

stein - 17.05.08 11:44 am

Hi Corz

i'm read your htaccess tutorial, and it so nice

i want to make my url so short and nice looking like this[this from DB artist name]/[this from song title]-[this id].html

and i'm using this rewrite:

RewriteRule ^lyrics/.*/.*-([0-9]+)\.html$ lyrics.php?liriklagu=$1 [NC,L]

but it doesn't work, can you help me please?

how about like this too:

where is the best look ? thanks


steve - 17.05.08 6:59 pm

Yellow text on a yellow background. Sweet.

cor - 17.05.08 9:01 pm

stein, you didn't state what form your back-end script expects the URLs to be in, so I can't be specific. However, I need to reply, because, looking at your code, it seems you have stumbled onto a nice Gotcha! One I haven't covered before.

Firstly, you need to decide on a format for the "flat" links. Either will work fine, but you gotta decide, or else you have confusion. I'm assuming all your script needs is the "id", and from that, it can produce the correct page. I'll assume also, that you have decided on the first type of flat link..

And that you are using this RewriteRule..

RewriteRule ^lyrics/.*/.*-([0-9]+)\.html$ lyrics.php?liriklagu=$1 [NC,L]

So why isn't it working? The code looks fine, right? You did good! BUT, what you didn't realize is that your requests are suffering from "Content Negotiation". Basically, because you have used the same word, "lyrics" at the start of your virtual path AND your real php script, Apache is trying to help you out by guiding the browser to the real file.

You have at least two choices. Firstly, use a different word, e.g..

Or else disable Apache's MultiViews capability..

Options -MultiViews

And your current .htaccess code will work just fine.

;o) Cor

ps. steve, if you are vision-impaired, I recommend you disable the styles, or use your own - you will find my pages are fully XHTML compliant, and look just fine even with all styles removed. If you use Firefox, and have trouble with your vision, I recommend "Read Easily", which I use a fair bit myself, particularly for white-on-black sites. A simple click toggles all the styles on a page..

mohsin - 20.05.08 11:35 am

ur given data about URL is for professionls
not for new user.•

Miz - 23.05.08 4:16 pm

I am suffering from being an .htaccess noob. I am trying to do a very simple mod rewrite of (*) to

* is any folder or file within that folder
1 is any folder name, doesn't matter

Everyone online has all these complicated php variable passing url's, and i just need something i think might be fairly simple.

Can you help?

I am pretty new to php and i need to change the folder names that people see, because i have thousands of files in the folder, but i need people to not see the real name of the folder, or the real name of the files eg. and needs to change to but show the real data that is on their respective index page. needs to change to and so on
i only have about 12 main folders

Miz - 23.05.08 8:16 pm

I thought of an even better way to explain what i am trying to do. Is this even possible?
When someone types in or clicks the URL
can mod_rewrite (or whatever) forward you (or disquise you) to
and have the same data show that is on

in this example, i have 12 folders that are like foldername, but 2500 folders that are like address

cor - 24.05.08 1:37 am

Miz, that isn't logical. Nor is it possible.

Think about it: "i need people to not see the real name of the folder". Fair enough, but how does the user get this link in the first place if you do not allow them to see it? They cannot click or type-in something that does not exist!

Yes, you can disguise the long URLs and present short /1 type URLs instead, but mod_rewrite doesn't know which page to send the user to, unless that information is somewhere in the URL in the first place.

mod_rewrite re-writes requests; it can't rewrite your back-end. You firstly need to create the short links in the first place (on your pages), and those links must, in one way or another, supply ALL the information required to recreate the target URLs.

In short, you could easily create twelve rules, one for each folder, and have users click links like, and have that rewritten transparently to; replacing apples with 1; but unless dumplings is somewhere in the original URL that the user sees and clicks, mod_rewrite can't use it in the target. Where would it get it from?

If it were possible to do %{ENV:MY_LINK} in a RewriteRule, then you could achieve what you want, but it's not (afaik), and anyway, the big question is; why would you want this?

In my opinion, what you are trying to do is Wrong for so many reasons. Your original URLs are clear and user-friendly, not to mention, very SEO-friendly; why would you want to use daft numeric URLs that only your back-end can understand? That's nuts!

Also, remember, you only need to do; assuming your DirectoryIndex directive is correctly setup, the index.php part would be would be handled automatically by Apache.

;o) Cor

ps. mohsin, the overwhelming consensus seems to be the exact opposite of what you suggest. I guess there is a language barrier at work here; one of the downsides of living in a multi-cultural world.

Miz - 24.05.08 2:34 am

You are so right, however, in this application, it is necessary or i have a lot of work on my hands. Let me explain further.

I am helping a friend with this project, and that is where this all started.

He is a photographer for a bunch of real estate companies and has setup folders
they are all flash movies(virtual tours) of his photography for the realtors. There are about 12 different realtors with about 2500ish addresses. The MLS in our area has just changed the rules that you cannot advertise the realtors name, nor an address in the url for a virtual tour. The problem is, to change the url for 2500ish mls entries is impossible (not impossible, but stupid)

So, this is not a search engine friendly issue, nor is it as crazy as you suggest. Maybe i am thinking about this backwards, but i am just trying to save ourselves a bunch of headaches. I appreciate your responses, and your help in any way.

Does the real application make more sense as to where this crazy idea came from?

cor - 24.05.08 3:07 am

Well, firstly, I have a limited understanding of what an MLS even is..

MLS®, Multiple Listing Service®: These are trademarks owned by The Canadian Real Estate Association. They are used in conjunction with a real estate database service, operated by local real estate boards, under which properties may be listed, purchased or sold. An MLS® listing means REALTORS® have agreed to work together for the marketing of a listing.

But from what I can tell, it seems unlikely that these rules would even apply to your friend's virtual tours - he isn't an actual realtor, is he?

And secondly, unless the address is somewhere, how can the user pick which virtual tour to view? I can understand not wanting to have the actual realtor's name displayed (we call them "estate agents" in the UK), as that is advertising of a sort, but without the address, there's no way for the potential viewer to differentiate between properties.

Obviously I'm missing something here, otherwise (once you comply to these rules) you have something like a list of thousands of links; 1,2,3,etc. and the clicker has no idea what he's getting into. Who buys property at random?

Is the user expected to just sit there and run through thousands of virtual tours until they find one that suits their needs? It all sounds completely insane! Surely there's some kind of menu or search, or something that enables users to select tours by type/cost/location/etc., and once they have made this selection, there needs to be a real link to the virtual tour.

Unless you are using some kind of php handler script, with a list of numeric=>realtor/address mappings, there is NO WAY you can present links that do not have this information in them.

Like I say, I'm obviously missing something. Either that, or the MSI rule is totally nuts.

;o) Cor

bilal - 25.05.08 12:21 pm

How can i do this


cor - 25.05.08 12:50 pm

Too easy.


;o) Cor

Saulie - 27.05.08 1:03 am


I have read through the tutorial and tried many ways but was wondering if you could show me how I make it possible for links like be accessed through It's quite different from the frist url and I'm having much difficulty getting it, was wondering if you could help me, or if it's even possible, if not maybee at least getting to work.

Thank you very much in advance, Saulie.

cor - 27.05.08 5:44 pm

RewriteRule ^user/(.) /forums/index.php?showuser=$1

;o) Cor

cuc - 27.05.08 8:34 pm

a question
how change by

zum - 27.05.08 10:02 pm

please a question who nobody knows:
you know if is possible escape ? at the pattern

redirect 301 /?page=1

not works

redirect 301 /\?page=1

not works

redirect 301 /\\?page=1

not works

? inside brackets, not works neither

any ideas?

cor - 27.05.08 11:03 pm

zum, I don't do mod_alias, only mod_rewrite. Have you considered mod_rewrite, instead? You will find RewriteRule directives much more flexible. See the article (above), and try it.

cuc, you didn't post your code, so I can't tell what's wrong with it.

Also note, you will need to post in English.

;o) Cor

Saulie - 28.05.08 12:33 am

Thanks for the help cor, would I have to put anything above that?

zum - 28.05.08 2:06 am

hi cor, thanks for answer
I try with RewriteRule, but I have the same problem

no brackets here because bbcode don't leave me post:

RewriteBase /
RewriteEngine On
RewriteRule ?page=1 NC,R=301
RewriteRule ^\?page=1$ NC,R=301
RewriteRule ^\\?page=1$ NC,R=301

dont works, I hate this '?'

cor - 28.05.08 7:50 am

I knew when I simply dropped an answer (for Saulie) without any effort on his part, that I was setting a dangerous president (Hey, I was pushed for time!), and I won't do it again. Lesson learned! This page is for people who want to learn about mod_rewrite. If you just want "solutions", then pay someone to do it!

zum, please do not post again until you a) read the article (above), b) read the HUGE notice right above this comment facility, and c) have tried some rules based on the code found here. For starters; where in my article does it describe the use of RewriteBase?

Also, in no less than THREE places, is the information you need to know how to use square brackets in your post; 1) the notice above these comments, 2) the help text below the comment form, and 3) the error message you got when your post wasn't being accepted. If you could be bothered to read any one of those three things, you could have posted without difficulty. If you can't understand how to operate a simple bbcode comments facility, you have no chance with mod_rewrite.

I realize that foreign language can be a barrier, but if you want to do take control of your web site, you will need to get to grips with English. That's just the way it is.

mod_rewrite isn't so hard, you simply have to read. After you read the article, slowly, you will understand the basics, and will be in a position to try some real code that may work. Particularly, pay particular attention to the section about capturing variables.

Saulie; only the usual stuff, the same as every example in the main article.

;o) Cor

zum - 28.05.08 11:44 am

Ok, solution is this:

RewriteEngine on
RewriteCond %{QUERY_STRING} ^page=1$
RewriteRule ^(/)?$ [R=301,L]

Thank you very much for your excellent article

cor - 28.05.08 11:57 am

Yes! You learn fast!

My only recommendation would be to use [R,L] while testing, then add the =301 only when you are certain it works as expected. It looks like it will work fine, though, good work!

By the way, unless you expect requests for multiple domain names that you need to redirect to that domain, you probably don't need the part of the target URL.

;o) Cor

Jay - 02.06.08 5:57 pm

I'm having trouble with my blog. It's installed under /blog. My htaccess file is in the main directory. I'm getting 403 forbidden errors when I try to access my blog at You can access my htaccess file here. Is there a way to make the /blog directory exempt from the htaccess file in the main directory? BTW, if I delete the htaccess file from the main directory then the blog works fine so I know that's the problem.

T - 04.06.08 2:39 pm


just wondering if you could answer my question. Basically i'm just doing some testing to get the hang of mod_rewrite.

I have assumed that my website has categories and products and i want to have urls like: i.e. i.e.

I have got to the point where my urls are coming out as however as i show above, i don't want to show "cat" or "1" for that matter i just want it to look like i have a folder called furniture, if you know what i mean. I am unsure of how to do this because from what i understand i need to have the id in the url for it to be passed to the actual page for me to then use in my scripts, i don't think its good practice to just use the category name in my script because its possible its not unique. am i making sense or just rambling?!

this is what i have:

RewriteRule ^cat/( <^/>+)-( <^/>+)$ /cat/$1-$2/ [R]
RewriteRule ^cat/( <^/>+)-( <^/>+)/$ /categoryinfo.php?catID=$1

i thought that this part: /cat/$1-$2/ [R] was showing what i wanted the URL to end up like but if i change it, it doesnt make a difference.

would really appreciate any help.


Joe B - 06.06.08 9:06 am

My problem is having apache authentication work if a rewrite occurs - it immediately goes to the 401 error. I have been all over the net, all over bunches of examples and there have been a couple of "solutions" which don't work. What you see is the result of various tests.

The last thing I tried was to get the request_uri to work - no go. I did a printenv to see that I was looking at the right stuff. I put $ ^ (.*) \ in just about every possible place <sigh>. Here is the .htaccess in my main directory. My last attempt was to have the request_uri filter out my password protected directory - so, I guess that could be a 2nd question because I just plain couldn't get it to hit on anything (trying ^/members24/ in various configurations to just see that I could get a match). However, my main concern is that I cannot consoldate website names (www and not-www) w/o breaking authentication for the .htpasswd protected member area.

If you could point to me something that I missed or give me a hint, I would greatly appreciate it. I'm just out of things to try except to build my own linux/apache so I can possibly see what a log would say. This has me stymied - but I guess I'm learning a lot just trying to fix this one little thing?? HA!

<Files ".ht*">
order allow,deny
deny from all

#bypass rewrite so it doesn't tangle with a password protected area
ErrorDocument 401 /errordocs/badpasswd.html

#instead of a no-no, eventually send them back to main page
ErrorDocument 403 /errordocs/badpasswd.html

ErrorDocument 404 /errordocs/filenotfound.html

# well, maybe someday I will get the rewrite to work -- geesh
Options +FollowSymlinks

#RewriteEngine On
#RewriteCond %{HTTP_HOST} ^mathdork\.com$ [NC]
#RewriteCond %{REQUEST_URI} !^/members24/
#RewriteRule ^(.*)$$1 [R=301,NC,L]

This is in my protected area (

<Files ".ht*">
order allow,deny
deny from all

#according to this fixes the
#rewrite and password tangle - we will see

#force password prompt instead of crazy rewrite mess
# needs to be done instead of rewrite above
#ErrorDocument 401 /errordocs/badpasswd.html

#after too many attempts, force the right response
#ErrorDocument 403 /onerror-null.html

AuthType Basic
AuthName "Member's Area"
AuthUserFile /home/royannel/pass/.htpasswd
AuthGroupFile /dev/null

<Limit GET POST>
  require valid-user

Any help would be very much appreciated. I just don't get it.. You can see parts of things I tried after getting "fixes" from elsewhere. (Oh yes, been over your stuff several times -- I just must be missing something fundamental, I guess..)

Thanks for any and all help.. -- Joe B.

marko - 07.06.08 10:17 am

Small question.

Is it possible the modrewrite won't cause a new requst for the sever?

How would you guys recommend to do something like this.
I have a sub domain and I want that if you type it will actually be the sub domain but the user will see the reguler domain

The problem is that it is a virtual subdomain and the domain itself has nothing in it ( it's a pointer ). Is that solveable as all?

Ben - 09.06.08 6:24 am

I used your htaccess tutorial to translate pages a few months ago and worked great, thanks. This no longer works so I checked your French translate link which no longer works either. I guess Google have done something (only loads top frame) and thought I'd point it out to you.


Mike Schinkel - 11.06.08 8:23 am

Hey cor,

GREAT post on mod_rewrite from someone who really appreciates well-designed URLs.

Anyway, I think I've read your post in its entirety and looked all over the net and still can't find (recognize?) and answer for this.

I've launched a new Drupal site that replaces an old Drupal site with much of the same content but I've changed the URL structure and Google still has lots of those old URLs in the following form:

The new site has changed the URLs to be this format:

I want to 301 redirect from the old format to the new format so Google will eventually clean up its index and not see duplicate content.

In addition, I have both a staging server on one domain and a live server on another and want the code to be identical between each. I want to be able to test the old URLs on the staging server and have them correctly redirect to the new style before I upload to the live server and have it all just work, all w/o changing anything in the .htaccess file.

The problem is I can't seem to figure out how to capture back references from each of two RewriteCond statements. Here's what I have that works but only for the live domain (not for the staging server):
RewriteCond %{QUERY_STRING} ^q=node/(.*)$
RewriteRule ^/?$ [L,R=301]

But here's what I want (but it doesn't work):
RewriteCond %{HTTP_HOST} ^(.*)$
RewriteCond %{QUERY_STRING} ^q=node/(.*)$
RewriteRule ^/?$ %1/node/%2? [L,R=301]

Can you figure out how to capture both the host and part of the query string into back reference variables?

Many thanks in advance for your help.

Mike Schinkel - 11.06.08 8:58 am

Well, I figured it out so I thought it only fair to give the solution:
# Implement Old Node Search URLs with a "q=node/nnnn" parameter
RewriteCond %{QUERY_STRING} ^q=node/(.*)$
RewriteRule ^/?$ http://%{HTTP_HOST}/node/%1?	 [L,R=301]
I swear I tried that earlier and it didn't work (instead giving me the path to the local file) but anyway, it is working now.

OTOH, I still didn't figure out how to access back references from multiple RewriteCond statements in the RewriteRule statement. Any thoughts for future reference? TIA.

Ziggy Stardust - 13.06.08 12:50 pm

Hello, i will start saying that i read the whole article and its comments, and i still haven't found a solution to my problem. Or maybe i don't understand very well the whole thing.

I have an already created web site with lots of crazy urls like

I read this week about the existence of this thing called mod_rewrite, and decided to make the urls smaller.

I made a lot of tests, and what i really dont understand is that it works if i write the url directly in the address bar, but when I click on any link on any page, it takes me to the real link (the big one). I thought this thing called mod_rewrite would automatically change the link into, for example

Do i need to do something more? Do I have to rewrite the whole code in my 200 pages to change the links ... i think this is madness.

Regards and thanks.

cor - 13.06.08 6:54 pm

Yikes! smiley for :eek:

Jay, yes, as stated in the article, use RewriteEngine off.

T, correct, the ID, etc., MUST be in the original URL in some form. If you don't want to use numbers and such, use php (or similar) to map numbers to real words, and use real words in your URLs.

marko, simply use a rewrite to redirect all requests transparently into the subfolder.

Ben, rats! Something has definitely changed. When I try my own cute auto-translation link (on this page) I get a frame within a frame within a frame within a frame... And I have to kill the page. Hmm. I'll need to look into this. Thanks for the heads-up.

Mike Schinkel, I love it when folk get back with their own solutions before I get a chance to post. Of course, leaving the replies for a week or so always helps!

As for your back-references, you simply increment the numbers, %2, %3, etc. You might also want to have a look at RewriteCond %{THE_REQUEST}.

Ziggy Stardust, mod_rewrite is only half of the story; the links on your pages are your own responsibility, mod_rewrite won't rewrite your pages, only requests from browsers (etc). Normally, people will code this dynamic->flat translation into their back-end (php, or whatever), so the new, flat links are generated automatically (or not, if it's optional).

Altering hundreds of links manually, is madness, yes. But as you are using variables (it's generally variables that people want to make flat) I have to assume that at least in part, your back-end is generated.

Whichever part generates the links, make your code changes there.

;o) Cor

cor - 13.06.08 8:48 pm

Oops! Apologies Joe B, I seem to have skipped right over your question! Perhaps that was because I subconsciously knew I had no good answer for you.

Firstly, thanks for bringing this to me, it's something I've not seen before. And although I can confirm it is a real issue, it's more like a real non-issue. Generally, www-> no-www translation is something that's used to catch dumb/uninformed users and legacy links; by the time they get to any member area, they should already be using the correct domain format, so it's not an issue.

If I add www. to my own "private" areas, I get the exact same result. But that's me doing it manually, to test your issue. In the real world, no one has ever done this, at least, no one has complained to me about not being able to access, for example, one of my beta test areas.

I wouldn't worry about it. Just create no-www links and be done with it. If any user is daft enough to add www manually, they deserve everything they get!

;o) Cor

skydiamond - 15.06.08 1:45 pm

I have to redirect this address

Here it's the code I made:
htaccess code
RewriteCond %{QUERY_STRING} id=1211181563
RewriteRule ^(.*) /blog/linux/debian/fare-il-downgrade-da-unstable-a-testing-in-debian/ [R,NC,L]

The problem is in the rewriterule. I want to erase completely the old URL for the new one, but it rewrites on this: /blog/linux/debian/fare-il-downgrade-da-unstable-a-testing-in-debian/?mod=read&id=1211181563.

I really don't understand why it stops on ?mod... How the regexp would be formatted to match this rule in perfect way? smiley for :ehh:

cor - 16.06.08 2:53 pm

Firstly, your question is poorly worded. I will assume English is not your first language, and also that what you are trying to to is simply remove the query string part from your target URL.

The answer is simple; add a "?" to the end of your target, e.g..

...ngrade-da-unstable-a-testing-in-debian/? [R,NC,L]

Of course, if you meant something else, then by all means, ask again.

;o) Cor

goosey - 16.06.08 3:27 pm


Firstly nice tut


i've been trying to do this for a while...

make it so that you can have custom file extensions for files. For example you could have all you files end in .goosey

e.g. index.goosey

but in reality you want these files to be executed by php

I have seen it somewhere else but i can't find it anymore, but i am sure it can be done through .htaccess

If you can help that would be awesome!

thanks goosey

cor - 16.06.08 3:43 pm

Yes goosey, both can be done, no problem. See part one of the article.
(link above comments)

;o) Cor

goosey - 16.06.08 4:01 pm

Awesome thanks so much,

I've got it working but i was just wondering, does this make it slower than having the file named .php in the first place or is it negligible.


cor - 16.06.08 5:36 pm

Nope, it's no slower than using a regular .php extension.
There may be other disadvantages, however.

;o) Cor

skydiamond - 19.06.08 11:03 am

Firstly, your question is poorly worded. I will assume English is not your first language, and also that what you are trying to to is simply remove the query string part from your target URL.
You understood perfectly what I mean. smiley for :cool:

I will try your solution. Thanks for all!

I'm italian.

Northie - 22.06.08 11:46 pm

I know there's not much chance of getting work done for me, but I'm really struggling with this. I am fairly tech-y but this htaccess and rewrite stuff is really not going in.

Anyway, I recently changed hosts and the set up I did have no longer works (every request failed and was picked up and processed by php in a cistom 404 page, no htaccess required).

I have two url formats that I want to re-write, these are


My .htaccess file looks like this

RewriteEngine On
RewriteRule (.*)/(.*)/ /index2.php5?category=$1&article=$2
ErrorDocument 404 /404.php
AddHandler php5-script .php

No, the later fo the two formats does work using this and I can see how and why.

However, the former does not (obviously at the moment) but whenever I add a line for the former format, eg

RewriteRule (.*)/ /index2.php5?category=$1

My php script doesn't get the right information. In fact, I don't know what it's getting.

I also tried a single rewrite rule for both situations, passing the whole request string as a query string, eg

RewriteRule (.*)/ /index2.php5?$1

But this just gave me a 500 error.

Any suggestions on how I can proceed will be greatly appreciated - many thanks in advance!

Firstly, remember, you can use conditions inside the pattern, eg. "([^/]+)" to first check for the shorter variant, and then allow the longer variant to pass to a second rule. And secondly, download my debug-report script and know *exactly* what's happening to your variables. Guessing + .htaccess = trouble! ;o)

iamnow - 24.06.08 5:40 pm

What a wonderful tutorial...The only way to go!

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_URI} !/index\.php
RewriteRule ^([^/]+)/? index.php?cid=$1 [L]

This seems simple enough but I'm totally befuddled...

The above is blows the graphics away and basically cripples the site.  It's supposed to turn this http://localhost/members/658  into this http://localhost/members/?cid=658.  

Your help would be greatly appreciated.  Many thanks in advance...

iamnow - 24.06.08 8:06 pm

After taking a break I came up with this and it worked:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^members/([0-9]+) http://localhost/members/?cid=$1 [NC]

I put it on my host server as:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^members/([0-9]+)$1 [NC]

Could that have to do with the httpt_conf being different?

DK - 25.06.08 1:58 pm

Dear Cor,

I have following problem. Can you please explain why is that happend?

RewriteRule ^jouets-.*-([0-9]+)-.*-([0-9]+)-.*-([0-9]+)\.php$ /jouet-sousrubrique.php?r=$1&sr=$2&ar=$3 [L]
RewriteRule ^jouets-.*-([0-9]+)-.*-([0-9]+)-.*-([0-9]+)\.php$ /jouet-sousrubrique.php?r=$1&sr=$2&arr=$3 [L]
RewriteRule ^jouets-.*-([0-9]+)-.*-([0-9]+)-.*-([0-9]+)\.php$ /jouet-sousrubrique.php?r=$1&sr=$2&pr=$3 [L]
RewriteRule ^jouets-.*-([0-9]+)-.*-([0-9]+)-.*-([0-9]+)\.php$ /jouet-sousrubrique.php?r=$1&sr=$2&prr=$3 [L]

but it always get the first one. if I come from other query strings it always get the first one.

Please explain.

Yeah! All the rules have identical patterns! The first rule will catch everything. You need to use the "ar", "arr", etc., in the pattern, too (left-hand bit) ;o)

AMIT - 02.07.08 12:05 pm

I have done this and its working fine
RewriteRule ^( <^/>*)/jobs$ job/search_result.php?keyword=$1

The problem is with this url
How will write the rule for this

check out the qsa flag. ;o)

simone - 07.07.08 9:22 am

Hi, tnx for this interesting article.

I have a problem with url rewriting, i need to use it to do deeplinking with SWFAddress,
so I want to rewrite


to something like


the rule i wrote is:

RewriteRule ^products/([A-Za-z]*)/$ /#/products/$1/ [R]

this seems to work nice except for a simple issue:
the #
is urlencoded by apache into

so the final address shown in the address bar is

instead of the desired

any hint on this issue?


Tom - 15.07.08 10:39 pm

WOW, thanks for the wicked examples!
Espicially happy with your languages translator!!
Wicked idea!

ashwani - 16.07.08 11:55 am

.htaccess provide comlete™

Dman - 18.07.08 9:17 pm

I have the hardest time getting mod rewrite to work with Tomcat.

Here is our situation. We run Apache2.2 and Tomcat5.5.2.3 together. Apache does nothing but forward requests to Tomcat instances via Mod JK workers.

Mod Rewrite is loaded and working on the Apache side. Example if I create 2 files: test1.html and test2.html and my simple rule are as followed.

I have a .htaccess at the root of Apache
RewriteEngine On
RewriteRule ^/?test1\.html$ test2.html

User type he gets the content of test2.html. Great!

I incorporated this in httpd.conf file and hoping that it would do the same but I am getting test1.html content only:

Example: If I type I just get the test1.html page instead of the test2.html content.

<VirtualHost *:80>
Options +FollowSymlinks
JkOptions +ForwardURICompat
JkLogFile logs/mod_jk.log
JkMount /* fadworker
ErrorLog logs/
#CustomLog logs/ common
LogLevel Error
JkUnMount /admin/* fadworker
JkUnMount /manager/* fadworker
JkUnMount /host-manager/* fadworker
JkUnMount /probe/* fadworker

RewriteEngine On

RewriteLog logs/mod_rewrite.log
RewriteLogLevel 4

RewriteRule ^/?test1\.html$ test2.html

My question is am I missing something here?

Mod JK is loaded before Mod Rewrite.

Dman, remember, for httpd.conf use, you need to add a slash to the start, e.g. /test2.html, or else you'll get a 400, Bad Request. As for Tomcat, I have zero experience. ;o)

Evan - 25.07.08 1:47 pm

Wicked cool article. Just starting messing with apache and this stuff, after a good explanation like the one above, really makes me happy. smiley for :D

micmac - 27.07.08 11:57 am

Neat approach and performance, sheding light in an dark area, typical cause of lots of frustrations. By this help I could improve a lot the security of my server.

But also here are examples, where a given code won't work in reality. It will be, because too fast the practitioner gains the impression, he understood the language systematics and thus creates on this base new varieties of options. I understand, that not any sample, presented in such a broad collection is tested first. Who likes 500 server error on his life system?

A typical sample, not covered here anymore (?) is the hiding of the .htaccess. Long survey finally gave, the given good codes only apply for .httpd server config and don't apply for the .htaccess itselfs (fine 500 disturbances...). The server provider (US) does not even understand, what the customer is asking, and falsly claims, the file is hidden already. That is valid so far any .ht is a hidden file, but it can be seen by any simple remote access via web.

My latest sample the simple RewriteRule. The given code to rewrite URL does not work, because the new URL contains a "?" for PHP POST command and that can't be masked by ESC, when the own server is set up for a certain ISO character set, for what are good reasons to stick with.

A limit of information is, that the given samples are only explained in short. Namely the definition of expressions like (^/y) in the samples is not satisfactorily covered by the table of valid forms. The same goes for Apache genuine web-manuals, written by machines for machines. Thus the reader here only can import given samples, to the utmost customizing them, but finally does not understand the rules. That a few minutes ago also brought good 500 errors to my readers or banned them from pages, now unintentionally restricted by authentication.

But such, it seems, is the server config world ...

Rob - 01.08.08 6:23 pm

You need to tell mod_rewrite not to urlencode your rewritten URL, you do that with the NE (noescape) flag. So you should use something like this:

RewriteRule ^products/([A-Za-z]*)/$ /#/products/$1/ [NE,R]

Michael - 05.08.08 5:57 pm

Thank you for a great article on .htaccess. I am a novice in this area and I really needed some help. I am running a demo video sharing website (I am just experimenting on how the script will work). After installing the script, I uploaded some test video to see if the script is functioning as it was intended by the script authors. The script is function very well as promised. Today I was playing around typing the url of that website on my browser and I was shocked on what I have just found out. All of my converted video files (flv) are saved by the script inside the folder called "uploads". If I type MyDomainDotCom/uploads on my browser, it will show all the files in that folder and I don't want other people to be viewing and downloading this files using their browser.

I was searching about the topics on how I can protect this folder, and I found one from other website that one can just throw in an .htaccess file inside the folder and it will disallow the access. It was easy I said to myself. I have created the suggested .htaccess file with the following code below. This is from one of the forum I visited this morning.

Order allow,deny
allow from myDomainDotCom

Now my problem with the code above is that the embed code coming from my site cannot play the video. I only want to restrict browsers from viewing the uploads folder, but at the same time the files inside it will be still accessible by my embed code, and by myDomainDotCom php files.

Can somebody please help, or guide me where to start.

Thank you very much for your time.


cor - 05.08.08 6:56 pm

Michael, the .htaccess code you have is wonky. I recommend you start at the correct page, and follow *my* examples, instead!

allow from myDomainDotCom a nonsense. Mainly because requests, even internal HTTP requests won't be coming from that domain (that's assuming Apache can even translate the domain name into an actual IP). If they are coming from anywhere, they are coming from, aka "localhost".

Having said all that, you need to keep in mind that if the user's browser needs to access the files directly, you MUST allow access to the folder. Only if your script accesses the media files via the file system (not HTTP request) and then serves them up to the users browser via some kind off "passthru" functionality, only then can you deny all direct access to the folder. If it does use a local HTTP request, then you can deny all except The former system is better, though.

But like I say, if you need more, go to part one, where I deal with all this (this page is about rewriting), and check out the examples there and in the comments.

Have fun!

;o) Cor

ps. thanks for all the flowers guys, you know that's just food for my funky new front-page random quote script! smiley for ;)

Predrag - 08.08.08 9:56 pm

Wow, you tutorial is amazing....

I have one problem.

I have a site on with all content.
And I have second site on who must when someone go on address to show all content from but in address line in browser must see
Everything must be like is two different sites but it is only one with two domain name.

Can you help me about this? How can I do this with .htaccess?


If they are on the same server, simply use regular internal redirects pointing to the file system. If they are on different servers, you can't use .htaccess to cloak the real URL, as an external redirect would be required. In that case, use a frame or similar construct. - OMG! I just recommended someone use a frame! smiley for :eek: I'll burn in hell for that! ;o)

Justin - 11.08.08 4:02 am

Okay, new problem.

My .txt files, .js files, and .flv files are all blocked now...and the .txt and are still usable in the way i want...but my .flv videos still aren't. And my .js file wont do what it's told on an .html page that accesses it...

And, on more of a side note, every time I upload a new .htaccess, close out of the ftp editor, and open it again, the .htaccess file is there, because i know it is, and because it's still in effect, but i can't find it in the ftp editor. I'm confused. It doesn't even ask me if I want to overwrite the file when I upload a new .htaccess . How can I fix this?


I'm sorry, I've forgotten what all that blocking stuff was about - don't be afraid to post code. As for the invisible .htaccess; you don't explain what you mean by "ftp editor", which is a term I'm not familiar with. "ftp client", yes, for moving files between your computer and an ftp server; and "text editor", for editing text, perhaps directly on another server using the ftp protocol; but "ftp editor" is new to me. Even that one question is actually more than one question.

It sounds like you need to have a good rake through the preferences of your ftp client (if that's what you mean). Or else switch to method B; use a text editor to edit .htaccess files directly, via ftp; works great. ;o) - 13.08.08 2:31 pm

Congrats on a very good comprehensive HTACCESS guide. Well done, was very helpful and structured well. I wish more websites would be like yours!

Ahh.. We are a dying breed; literally! ;o)

gulflee - 15.08.08 3:24 am

Hi I had re-direct the url

(category) -->
(sub-category) -->

but I dun want the subcategory i m thinking is it possible to rewrite the URL from -->

thanks in advance.

Yes, it's possible. ;o)

Taek - 19.08.08 5:31 am

I am looking to use url re-write rule and I'm not sure what I can use to do what I am looking for i will setup my httpd.conf accordingly but i would like to doing something like

also would like to do something like

I know this seems stupid but I plan on having a small image hosting system and this would help alot.

Sounds like a plan. Was there a question? ;o)

Jaunty Mellifluous - 19.08.08 3:39 pm


Thanks for the nice tutorial.

I'm using this code from your examples to run my site from a subfolder in my root hosting space.

..meaning I've placed my site in a folder inside my root folder. /root/roadsout/ << like that.

RewriteEngine on
Options +FollowSymlinks
RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^/roadsout
RewriteRule ^(.*)$ roadsout/$1 [L]

so that's the code. It works fine. But the problem is, when I browse to the links within my site, the url becomes something like this,

I want to url to look like all the time. So that it doesn't show the extra subfolder inside my hosting space.

Please help. Thanks.

The downside of blatant self-promotion ("" works well), is that I get to see what kind of site you have, and thereby ignore you intentionally. ;o)

AskApache - 20.08.08 11:41 am


Hi I just published an advanced mod_rewrite tutorial that you might find interesting. It shows some sick methods for viewing the variables available to the mod_rewrite engine by adding them to the REQUEST headers. Once set up, you simply request a debugging file like your "du" php file and variables that were once hidden from the php interpreter are now populated.

Love the site and I've been waiting for htaccess3.php for quite some time now...


ckyeu - 25.08.08 9:11 am

This article is very good. however, I have run into a problem when I want to rewrite this url yyy to maybe or I was able to rewrite for to It is a live site and I didnt foresee that people would register with names with spaces :(. (the name has a space i.e. xxx yyy)

Thank you guys in advance for your help..

Thanks for this tutorial too..smiley for :)

Just send them to memberprofile.php, and use php to grab the name (from REQUEST_URI, REDIRECT_URL, etc. ;o)

Peter - 26.08.08 3:54 am

Similar to this guy's question:

Wow, you tutorial is amazing....

I have one problem.

I have a site on with all content.
And I have second site on who must when someone go on address to show all content from but in address line in browser must see
Everything must be like is two different sites but it is only one with two domain name.

Can you help me about this? How can I do this with .htaccess?


My question is very similar except that I'm building a Joomla site that is absorbing two or three sites that have their own domain names.

Example, say I had a site called "" and I was rebuilding it, bringing into it sites like and, as they were going to be different "sections" within this site running on Joomla. The puzzle for me is this: I want those users who are going to to go to the detroit chevy "section" of and keep in the URL somehow. The same would hold true for Is this even possible?

Yes. ;o)

Andy - 28.08.08 3:46 pm


Excellent site; I have already used some of the ideas. I think you forgot to talk about switches [NC] etc - you said you would come onto those later.


In truth, I find it hard to get motivated about .htaccess - maybe one day! I'm guessing I probably used the word "probably". ;o)

doru - 29.08.08 6:01 pm

sorry to badder you
my site is php site
I own an web site and hire someone to make my links shorter.
but they made it in 9 folder

what I want is

and he said is not possible , is he right ?

No. ;o)

Rrryan - 02.09.08 7:48 am

Very Helpful page. Thank you!

I'd been looking for an elegant way to strip 'www' out of all requests and this does it simply and perfectly, though I had to hard code in the domain name and lose the '%1'. Thanks!

Like I said; not all servers allow the %1. But still a great trick! ;o)

unokpasbaxaki - 13.09.08 3:04 am

I'm Spanish and my English isn't perfect, so sorry if I make any mistakes.

I'm testing my website on a XAMPP on my computer (XAMPP is a tool which includes Apache, MySQL and some more things for making up a development mirror). I tried some rewriting code, but I got a 500 error. I tried several things to make it work, but the only thing that worked was commenting the all the rewrite lines.

Then I tried to copy those directives to the Apache configuration file, like this:
<Directory "C:/xampp/htdocs">
    RewriteEngine on

    [rewrite code]


And at restarting Apache, I got this error:
Syntax error on line 231 of C:/xampp/apache/conf/httpd.conf:
Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration

What can I do?

unokpasabaxaki - 13.09.08 5:14 pm

I've already found out what was wrong. In httpd.conf, the line to load the rewrite module was commented out.

If it doesn't work on your server, search for this line:
#LoadModule rewrite_module modules/
and remove the #.

Apache setup 101, m8! It's still a good catch, most Apache installs have it uncommented by default. By the way; I DO NOT recommend XAMP (or any one of the many similar packages), the basic installers from et al, are excellent these days, and working with the servers in that form gives you solid, transferable skills. It the long run, it usually ends up being a lot less work, hassle, and not to mention, just as "user-friendly" as these so-called "easy installs". ;o)

Nizzy - 21.09.08 12:38 pm

A challenging question!

Is there any way to generate a random string with .htaccess?

I like to accomplish this: will redirect to

.xyz123 is a random string generated by .htaccess.

thank you.

It can't be done entirely in .htaccess, but it would be trivial to do in php, so simply redirect to a php handler (or use php's auto_prepend_file in .htaccess), and use php to send a (random) location header. ;o)

simon - 22.09.08 12:40 pm

just looked you up when i had a little htacess question and found the answer on your page. thanks. simon.

banabcsee - 23.09.08 9:35 pm


my purpose is to pass the full request uri to index.php?q=..., and i tried this wonder on localhost.

the errordocument section was excellent, i could redirect it easy, but i found a lot of error messages in the log - because of the 404 errors although it was handled by my script (i sent a status 200 OK header, but no result)

now, i try to use RewriteCond, RewriteRule, etc, but it causes 500 server error.
in httpd.conf i set "LoadModule rewrite_module modules/", but the error message doesent change.

so, my question is: how can i solve my problem with mod_rewrite, or how can i use a 'silent' mode to hide error messages?

thanks a lot,


i found meanwhile the solution: i had to restart the apache smiley for :eek:
sorry (:

Michael - 05.10.08 11:25 am


Fantastic article, I'll be back to read the rest soon.

I think your bit on 'Inheritance' is something I'm needing to look into.

Do you know of a way using .htaccess to ignore a folder.
I have a sub-directory in my main root called 'zenphoto' and I don't want the .htaccess file in my main root to even look at this folder.
Any ideas?

Many thanks for this great resource!

.htaccess doesn't really look anywhere. Is it web browsers you are trying to deny access to? Or something else? Or did you want to disable rewriting in a sub-folder? For a better answer, I'll need more details; though I suspect when you come back to "read the rest soon", you'll probably find what you are looking for. ;o)

Paul - 15.10.08 8:11 pm

Hi! I'm trying to redirect using a similar style to what I have used in the past and use for other pages on our site. The first line shows what I am trying to do and the second the command I am trying to use to do it.

# =>
RedirectMatch (.*)(?i)product_category\.php?category_id=75a6fcc1df7dc77d1cd7ab39b7e45549

I tried it both with and without the \ in front of the .php and that did not seem to be the problem. Any suggestions?

That's mod_alias; try mod_rewrite (what this page is all about) and you might have more luck. ;o)

Torbjørn Torsvik - 20.10.08 2:26 pm

Hi. Is it possible to make a htaccessfile check for certain SESSIONS?

HTTP is a "stateless" protocol, a.k.a. "sessionless"; there is no such thing as an http session. If you are referring to sessions created by some server-side language (e.g. php), then you need to use that language to check for them.

Note: You can check for cookies with .htaccess. If you want to know more about that; drop a comment on the other page - this article is about mod_rewrite. ;o)

D. Rich - 22.10.08 3:56 am

I used the information you provided to solve my Joomla subdirectory problem.

I added a link back to this page. Great work & Thanks!

Jesse - 23.10.08 10:49 pm

Hi I'm trying to do a 'controlled' redirect..I've been searching everywhere for some answers I'm wondering if you might have an opinion.

I have (many) old links that are being displayed like they were before I implemented mod_rewrite.
I'd like for the user to be able to still click those links, and end up at the exact same place but see the rewritten url in the address bar...

I have:
RewriteRule songs/(.*)-(.*)\.html songs.php?page=$2&song=$1

ok, so:
http://localhost/songs/abc-22.html ends up at http://localhost/songs.php?page=22&song=abc

however I have thousands of links still showing songs.php?page=22&song=abc ...

I've tried many things, the best I can describe my guess for the solution is:
RewriteCond %{QUERY_STRING} . 
RewriteRule ^songs.php?song=(.*)-(.*)$ /songs/$1-$2\.html [R]

This bulletin looks like it's been recently used and answered by you so I'm leaving my question..
Thanks in advance,

cor - 24.10.08 1:54 pm

This is a very good question.

Firstly, I'm surprised you got your initial rewrite to work, having used "songs" as your virtual "directory", rewriting to an actual script called "songs.php". Many people attempting to replicate this would be left scratching their head, wondering why it didn't work.

I have to assume you either realized that Apache's content negotiation would mess it all up, and disabled Multiviews..

Options -MultiViews

.. or else you got lucky, and it was already disabled. Either way, it's a gotcha I had to mention, in case someone else reads your post and tries something similar.

So, you have your new flat links, and want to rewrite these, as well as existing dynamic links, so the the user sees only the new flat links in their address bar, while every request is rewritten to dynamic links in the background, regardless of its original form. I like your goal, which on the surface seems "elegant in its simplicity", as villains often say; but in practice, is thorny.

Personally, I would run sed over the entire site, and physically switch out all the old dynamic links for flat links, be done with it. However, I'll assume that's not possible or feasible, and continue with a purely .htaccess approach..

In your experimentation, you've likely discovered that getting both parts to work together is tricky; each individual rewrite works fine on its own, but together, put the browser into an infinite loop.

You probably also discovered that "L" flags (which instruct Apache to stop processing rules at that point), are not enough to prevent reprocessing on their own because in the per-directory scope (.htaccess, as opposed to httpd.conf), a redirect will re-inject the request at the server level, causing processing to begin again from the first RewriteRule; and there's that loop again. There is a solution.

The first part; catching the flat links, and transparently rewriting them to dynamic links; is simple enough..

RewriteRule songs/(.+)-(.+)\.html songs.php?page=$2&song=$1 [NC,L]

The thorns appear when you try to catch those pesky dynamic links on your old pages, rewrite them visibly into flat links in the browser's address bar, and then have them rewritten transparently back to dynamic links with the first rule (above). To accomplish this, we'll need to employ two "tricks". Here's some code..

RewriteCond %{THE_REQUEST} page= [NC]
RewriteCond %{QUERY_STRING} page=(.+)&song=(.+) [NC]
RewriteRule ^songs\.php /songs/%2-%1.html? [NC,L,R]

The first trick is the use of %{THE_REQUEST} in a RewriteCond, which matches only the original request (in its entirety), i.e. the actual link that was clicked, or typed into the user's browser. This prevents Apache applying the rules to requests that have already been rewritten. In this example, the page=, ensures that only requests with a query string containing that variable are affected. song= would work just as well.

The second trick is the use of the "?" at the end of the target (.html?), which essentially strips off the query string, again, preventing infinite reprocessing.

There are other ways to achieve a similar effect, but that code or something very like it will do the trick.

Have fun!

;o) Cor

In fact, the second [L] flag is redundant in this example, but I added it because it's generally a good, efficient practice.

aconana - 26.10.08 8:41 pm

Many thanks for this extended enlightenment on good htaccess usage! I hope you can tolerate another three questions - a typo (or not?!?), a basic misunderstanding, and something in between.

•First code snippet (after the 6th paragraph) is the second line missing the end-of-string delimiter, i.e. should it be
RewriteRule ^(.*)\.htm$ $1.php

instead of
RewriteRule ^(.*)\.htm $1.php

That would be "not". Anchors are completely optional. It should, in fact, read.. RewriteRule (.*)\.htm $1.php, because it would better suit the poem. ;o)

•When does / doesn't (.*) pick up the query string? For example, in the "shortening URLs" section, the sample URL appears to give
$1 = "?"

but the "QSA Overkill!" sample appears to give only
$1 = ""

(i.e. excluding the ?foo=bar stuff). Does the [QSA] flag have anything to do with it?

(.*) greedily catches everything in its path. In the first exmaple it catches everything after "grab", and in the second, everything after "grab/". The [QSA] flag is what tags the original variables; "level=5" and "foo=bar"; back on to the target URL. ;o)

•Stripping a query string from a URL (in the "Just a demo!" code snippet) - why is even the question mark ? necessary?

The "?" is the only thing which IS necessary. As mentioned, this is what strips the URL of its query string. Technically, it creates a URL with a single empty query variable, which is automatically stripped off when the URL is re-injected. ;o)

Thanks for any further patience you have with this nit-picking!

No problem! ;o)

Jesse - 27.10.08 5:36 pm

Thanks so much for your interesting response. It's enlightening to say the least. mod_rewrite is a tough module to learn, there's so much deep stuff going on.. It moreless becomes a matter of learning the internals of apache. You're right about just editing all of the old stuff into the new links. The links are actually in a database I believe, I'm a freelancer so it's not my site.
After I thought about it for a while, it became obvious that mod_rewrite is mostly made to make 'fake' stuff rather than work with 'real' stuff. For example redirecting on a file that exists will never work... and that's the dead end that needs to be realized I think. This site is awesome. Thanks for your input!

While it's true that mod_rewrite is mostly used to "fake" stuff, there is nothing to stop you rewriting from a file that exists. Why you might want to do this, is another matter. mod-rewrite provides almost limitless possibilities; being processed before the browser gets the page.

As for your links; a database, that's even easier; one simple command (in phpmyadmin, for example) would change them all, something like this..

UPDATE tablename SET tablefield = replace(tablefield,"oldstring","newstring");

You could also add a "WHERE" clause, for more specificity. Have fun! ;o)

martín - 28.10.08 8:11 pm

I've changed my "" to a new site ""
The oldsite was on php and the new on html.
Pages in google are listed as "" which I would like to redirect to "" or

installed this, but it only works if you enter the oldsite name, not with the .php pages

DirectoryIndex index.html index.htm index.php
IndexIgnore *
RewriteEngine On
RewriteCond %°HTTP_HOST° ^$
RewriteRule ^°.*°$$1 °R=301,L°
RewriteCond %°HTTP_HOST° ^$
RewriteRule ^°.*°$$1 °R=301,L°


If this post is some kind of joke, worry not, I'll be deleting it soon enough. If it's not a joke, then please a) frame a question that makes sense, giving as much detail as possible, and b) read the above article (including the huge notice above these comments) first. ;o)

Paul - 29.10.08 5:06 pm

I am trying to rewrite from:


Per your suggestion above I have stopped using mod_alias and started using mod_rewrite (because, after all, that is what this page is about). smiley for :evil:

But, it still is not quite right. Can you take a look at the commands below and help me?

RewriteCond %{HTTP_HOST} (.*)(?i)product_category\.php\?category_id=75a6fcc1df7dc77d1cd7ab39b7e45549
RewriteRule /product_category.php?cat_id=sheet-protectors 

Thanks again.

cor - 29.10.08 6:03 pm

Paul, you clearly don't understand how this works. Did you read the article at all? I mean, how on earth could the string (.*)(?i)product_category\.php\?category_id=75a6fcc1df7dc77d1cd7ab39b7e45549" match against your domain name? That's nuts! And the RewriteRule beginning with a forward slash; again, the article (above) explains why you would not do this inside an .htaccess file.

Och well, something like this will work..

RewriteCond %{QUERY_STRING} category_id=75a6fcc1df7dc77d1cd7ab39b7e45549 [NC]
RewriteRule ^product_category.php /product_category.php?cat_id=sheet-protectors [NC,R]

However, is that long category_id really necessary? If there are many such id's corresponding to many cat_id's, then fair enough; I guess you'll be writing lots of RewriteRules (in which case, add an "L" to the flags). If there is only one, then you can omit that long string from the RewriteCond, and simply check for the existence of category_id.

If there are lots of id's to map, it would be easier done in php (or similar), creating a mapping list somewhere, and rewriting all queries to the php handler.

;o) Cor

Daniel - 30.10.08 11:34 am

Hi, I wish to acheive something similar as Paul, I have a page, dealing with animals, and the get variable determins the id to sql out of the database to get all the info but I want to rewrite the url from this:

to this:

Is it possible to query a database to get the data I want to do the rewriting or must I make a map (?) with each id corresponding to a certain string of information I would use? I like the sound of Php handler, what does this consist in?

Paul - 30.10.08 4:49 pm

Thanks for your help. Of course what you suggested works. You were only half right on your points, though: You are right that I clearly don't understand how it works. I have read the article many times over the years and have spent many hours trying to understand it. In the end I can't tell my foo bar from my egg foo young.

Addressing your code (or my implementation):
RewriteCond %{QUERY_STRING} category_id=046216723ed2bab34a3dab9fd01fdb19 [NC]
RewriteRule ^product_category.php /product_category.php?cat_id=sheet-protectors [NC,R,L]

Is this what it is saying: If the string equals category_id=046216723ed2bab34a3dab9fd01fdb19 (no matter what the case) then rewrite it so that it uses everything before product_category.php and replaces it with everything before the string plus /product_category.php?cat_id=cleer-adheer-laminating-film (no matter what the case, redirects and ends the rule)?

Also, what is the difference between mod alias and mod rewrite?

By the way, the links in your conclusion don't work for me as they just go to http://localhost/manual/misc/rewriteguide.html

Again, thanks for your help.


cor - 30.10.08 9:26 pm

No problem, Paul. Of course what I suggested works! Half right? That means I must also have been half wrong. Tell me exactly what I was wrong about, and I'll give you the dang-diddley abc of exactly how the code works.

For the difference between the two Apache modules; see here. Also check out the useful links section below the article.

By the way, I might have been tempted to dive into a full explanation right away; but I know you aren't paying attention. For example; did it not occur to you that not one but three links in an article read by thousands of people every day, might be correct; and instead, you are in error. You're skipping! The paragraph begins, "If you have apache installed on your system..". localhost is your machine! If you're not Apache'd-up, of course the links won't work.

And where did the cleer-adheer-laminating-film come from? smiley for :eek:

Daniel, what goes on in your back-end is your own business! As for rewriting, at a minimum, simply rewrite all requests to species.php, creating a variable with the custom string, and let that script do all the work. species.php then, is your "php handler"; it handles the variables.

Somewhere; in a database, or a plain text ini-type file, even inside the handler itself, the string "common-toad-bufo-bufo" is translated to the integer, "18", which I assume means something to the script; an sql table id, or whatever. At any rate, "18", and its associated data are now available for processing by your script.

How much of all this is handled by .htaccess, and how much by your php script, depends on the number of transformations (mappings) you need. One or two would be simpler in .htaccess; one ruleset per mapping; but a longer list would be better handled by your server-side code; i.e. php.

Decide what you need, and try a few things.

;o) Cor

Jesse - 31.10.08 1:37 am

Just a quick note to some people posting on here. mod_rewrite is used best in making simple links that only involve 2 or 3 variables at the most. Take for instance

looks much better than

..ideally if everything is planned right from the beginning, then you can put all the info you would ever need to in the link without any &,=, or ?.

Thanks for the input! Also see here. ;o)

one more thing completely different but same topic is you can use php header("Location: somefile.php?stuff") to make up for anything that doesn't otherwise with mod_rewrite.. it's a dirty hack and i don't recommend it but it works..

Though DO read the manual for that. ;o)

Amin - 31.10.08 6:45 pm

If I want my url to look from this


How can I write the mod rewrite, I am new to php and linux.


Simple create a new plain text file called .htaccess in the root of your site, and put the rules in there. ;o)

Rohan - 02.11.08 12:04 pm

If you are familiar with regular expressionssmiley for :eek:, you can master URL rewriting under 2 minutes! smiley for :D

And if you put all the worms in the world end-to-end, they would reach from here to the Moon. Oh, no, wait a minute; the one in the middle would probably wriggle and spoil it. ;o)

Paul - 07.11.08 8:31 pm

The part where you were half wrong is where you imply I did not read the article. And I did not say the links did not work, I said they did not work for me...smiley for :evil:

Thanks for the links to the difference between alias and rewrite.


Exacitly my point! If you'd read the beginning of the paragraph, you would have known that the links only work when you have Apache installed; which is something I encourage all serious webmasters to do. ;o)

Andrew - 09.11.08 5:23 pm

Hi there,

Thanks for the guide. I'm in the situation of having two domains on the same host; I've been trying to use the htaccess file as you've outlined above, but with limited success. The links are pointing to the right files/folders, but the server seems to be 301 redirecting the URLs rather than rewriting them. The new URLs appear in the browser address bar, and the server seems to be sending a 301 redirect, according to

Anyway, if you've any ideas why my code isn't working, I'd be glad to hear them. Apologies in advance for any obvious errors.

RewriteCond %{HTTP_HOST} 
RewriteCond %{REQUEST_URI} !^/ga 
RewriteRule ^(.*)$ ga/$1 [L]  

RewriteCond %{HTTP_HOST} 
RewriteCond %{REQUEST_URI} !^sp 
RewriteRule ^(.*)$ sp/$1 [L]



A slash in front of the "sp" in the second ruleset's RewriteCond would be a good idea. Aside from that, it all looks fine; I can't see anything that would force a 301 external rewrite. Feel free to email me with your actual domain name and full .htaccess file - I'm curious. ;o)

Catherine - 13.11.08 7:26 am

Fanastic - after searching high and low your page fixed my problem. I could kiss you :-)

Hey, if you're local to Aberdeen, feel free! ;o)

evipbg - 18.11.08 5:48 am


Thank you, a lot.

Pratik Thakkar - 18.11.08 9:31 am


I am facing problems with multiple .htaccess files - one in parent and one in subfolder.

My parent .htaccess file
RewriteEngine on

RewriteRule ^(images|swf|includes|admin)(.*) - [L]
RewriteRule ^((.*).html|(.*).rss|^(\d+)$|(.*)/$) /index.php [L]

Now .htaccess in the folder "/admin"
RewriteEngine on

RewriteRule ^admin/(.*) /admin/index1.php [L]

I want all pages in the directory admin and its sub-folders to go to /admin/index1.php.

But I always get an error saying "Access Forbidden!" - You don't have permission to access the requested directory. There is either no index document or the directory is read-protected.

The only php file under /admin is index1.php.

How do I acheive this? Am I doing something wrong?

Any help will be highly appreciated.

Kind Regards,
Pratik Thakkar

Try.. RewriteRule .* index1.php [L] ;o)

reub - 21.11.08 5:28 am

oh course im a bloody human!

tech - 21.11.08 4:14 pm

An excellent tutorial, thank you! I still have one tricky problem, though:

I have one host with three domains pointing to it (, and I have Joomla running from the root on my server, and in Joomla the Joomfish multilanguage componenthandles the translations and a SEF-component handles the nice outlook of the url:s. A normal url with no translation looks like '' and gives the default language page. When I select another language it changes to '' (where nn is the language code). All three domains work identically, from the root.

My problem: I would like to redirect all people using to the english-language version of my content, and all people using to the german-language version. Would that be possible using rewrite, and if so - how? I have tried several solutions but usually get stuck in a loop... (Rewrite to sub-folders work fine, but I do not want to have three different installations of Joomla just for the different languages...)

smiley for :eek:

Matt H - 22.11.08 2:01 pm

Excellent write-up.
Just wanted to say thank you.

adri - 24.11.08 10:51 am

Hi, I'm trying to redirect

Another requests could be:
to be redirected to

to be redirected to
(and more requests...)
I was using something like this:
RewriteEngine On
RewriteRule ^mypage.php(.*) /$1&var3=3[QSA,R,L]

But it doesn't work, this redirect to:

Do you know what I could do to put that

Sure, adri. I'll assume you are rewriting to "index.php" (you have to be rewriting to something). You could do it like this..

RewriteCond %{REQUEST_URI} !index.php
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^mypage.php /?%1&var3=3 [R,L]


adri - 24.11.08 3:05 pm

Oh, it works!

If I don't want to rewrite mypage.php when request has not vars I suppose that it should be:

RewriteCond %{QUERY_STRING} (.+) 
Correct! ;o)

Thank you very much, you opened my eyes! (sorry my english )

Anthony - 24.11.08 5:44 pm


This is really a nice tutorial for .htaccess beginners like me. Any ways, i want to convert http://localhost/anto/about.php file to http://localhost/anto/about just removing the php extension. Any suggestions for me???

Thanks for time and help,

Happy coding smiley for :)

Suggestions? Yes. I suggest reading the article carefully, and then trying a few things. After this, you will be empowered, and won't need to ask anyone else to do this stuff for you. If you still have issues, come back and post the actual code that is troubling you. Also, you might want to load this page with all comments, and do a type-to-find for "extension". ;o)

Anthony - 24.11.08 7:13 pm


Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(about)$ about.php


Philip Arshe - 28.11.08 6:18 am

Hi! Here's the difficult one ever !
what about trying to do:
into only

Is that possible ?

Possible. Yes! Difficult? No. In fact it is so trivially easy, that even my dog could do it. ;o)

HAS - 30.11.08 6:18 am

nice tutorial.

do you have a way around missing the relative links for images and css files?

request url:

original url:

the problem faced here
that all images and CSS are missing.

will be great help if u have any guide. thanks

Load the page with all comments and do a type-to-find. I'm fairly sure the info you are after, is there. ;o)

Siteman - 01.12.08 6:27 am

Hi Cor,

After 6 mths of searching I finally "found" your site today - best practical info on doing useful stuff with .htaccess I have ever seen!

So now I think I have finally been able to resolve the issue of canonisation of my site, eg have all combinations of,,, etc. point to the same URL ( - which search engines really love... So here goes:

# Canonise all page URLs to start with "www."
RewriteCond %{HTTP_HOST} ^$ [NC]
RewriteRule ^(.*)$$1 [R=301]

# Convert all index.htm* to base URL (case independent)
RewriteCond %{HTTP_HOST} ^$ [NC]
RewriteRule ^index.htm [NC,R=301,L]

I hope I got it right? Have I missed anything?


Missed anything? Nope. In fact, you've done too much! The second RewriteCond is superfluous. Also, I suggest you use "NC" in the first RewriteCond (along with an "L" in the RewriteRule), so you also catch EXAMPLE.COM/etc.

And while you are still at the "unimplemented" stage of your canonization, consider not using the "www", it's deprecated. See here for more details.

Six months to find me? Crazy! Should have tried Google! I'm surely in the first page for any .htaccess-related search! ;o)

Siteman - 01.12.08 12:21 pm


Well, you are indeed in the Google top-10 for "htaccess", but I had always included "Apache" ... smiley for :erm: :blush:

When I tried your suggestions, I found:

1. If I delete the 2nd RewriteCond (= the last 3 lines), then is not canonised to

2. EXAMPLE.COM/index.htm is canonised to even without adding NC to the first RewriteCond (= on the 3rd line)

Not sure why this is - or have I misunderstood your comments? I use shared hosting, so maybe there are server-wide htaccess settings that affect my htaccess file?

Many thanks.


PS: I did read ... interesting points...

cor - 02.12.08 12:30 am


1. Yes, you misunderstand my comment. I said nothing about removing the second RewriteRule!

2. It's likely that your browser lowercases domain names, but unless you do it in .htaccess, you can't guarantee that it's happening on other browsers. In other words, that's a browser thing. In fact, you had that in already, unless I corrected it without realizing - wouldn't have been the first time!

I like your idea of converting hits for to plain old It's better SEO, and neater, too. But why stop at your root?

Here's some code similar to what I have in my site-wide init-file. It runs at the very beginning of request processing..

if (substr($_SERVER['REQUEST_URI'], -9) == 'index.php' and empty($_POST)) {
header('Location: http://'.$_SERVER['HTTP_HOST'].str_replace('index.php'''$_SERVER['REQUEST_URI']));
// this code could be easily improved!

I'm assuming you can run php scripts, and have somewhere to put this - if you don't have any init/header files, you can use php's auto_prepend_file to have a script run before all requests are handled, e.g. (in .htaccess)..

php_value auto_prepend_file "/var/sites/"

Obviously, for your site you would need to replace index.php with index.htm. Note that we check for $_POST variables, so as not to mess with form input (bots won't be using the forms, so there's no SEO impact).

for now..

;o) Cor

p.s. Top ten for just "htaccess" on its own! w00t! smiley for :D

chris - 02.12.08 8:22 pm

first off thank you very much for this tutorial, I've been designing webpages for a while but I'm pretty new to the admin side and this has been a great help

my company is going from coldfusion to plain html, and I tried writing a Rewrite rule as best I could per your examples, but it still seems to be ignoring everything after .cfm

so ex needs to become

my rule:
Options +FollowSymlinks
RewriteEngine on
RewriteRule /content\.cfm\?n\=(.*) /$1.html [R,NC]

still gives 404 "The requested URL /content.cfm was not found on this server"

I've tried variations with and without the escape char \, but everything still gives the exact same 404 error message... if you could point out where I'm going wrong, that would make life soo much easier.

Agreed. Once you see where you are going wrong, life becomes much easier. I can see where you are going wrong, because I've gone wrong in the exact same way myself, many times.

I would gobble up some information and dive into a "solution", and when that didn't work, try a variation, nope, curse, try another, and another, until I was so utterly frustrated that I either had to abandon the problem altogether, or try a completely different approach, sometimes following the exact same cycle with the alternative. What a drag.

The answer is simple; RTFM. While you were skipping over the above article, you missed the section entitled "capturing variables". It's my fault for only using an <h3> tag. Either read that, or for a sizeable donation, I will provide the exact code you need, simple as it is. Also, lose the forward slash. ;o)

chris - 03.12.08 9:40 am

lol I did actually did read the capturing variables part, and tried copying and substituting, but I had no luck so I thought I might be over complicating things... I'm a photo/video/design guy so the most scripting I've had is a semester of JavaScript. But after reading it about 6 more times and a few dozen attempts I appears to be working properly smiley for :D

RewriteCond %{QUERY_STRING} n=(.*)
RewriteRule ^content.cfm(.*)$ /%1.html? [r=301,NC]

The confusing part is that logically it seems the query string should be n== or escaped as n\== , 1st = as last character of the url, and a 2nd = for the equation itself.. and not realizing I didn't need ?n= in the RewriteRule

Thanks again!

No Problem! Note, in your RewriteRule, you don't need the anchors (^ & $) in the match string. Nor do you need the (.*), because you aren't capturing anything in the RewriteRule, only in the RewriteCond..

RewriteCond %{QUERY_STRING} ^n=(.+)
RewriteRule content\.cfm /%1.html? [R=301,NC]

And of course you used [R] until you had it working 100%, and then switched to [R=301]; as advised; or else you probably had a hellish time getting it to function. smiley for :lol: Nicely caught with the ? at the end of the target. All's well that ends well, eh! ;o)

Syam - 03.12.08 9:18 pm

I'm having headache with my .htaccess

here is my directory layout


I use mapping file for my vhost (assume: example.zf /www/example/zf)

and here is my .htaccess. The problem is whenever i use http://example.zf/?key=value it seems to read /www/example/zf/index.php(which i have now) but I want it to redirect to index.php in /webroot folder. Furthermore, /library will give 403 but /library/Zend/Acl/Router.php still can be accessed. How can I *lock* entire /library from viewers?


Options All -Indexes

RewriteEngine On
RewriteBase /

 RewriteCond %{REQUEST_FILENAME} library(/.*)
 RewriteRule ^library(.*) - [F]

 RewriteCond %{REQUEST_FILENAME} !^(/scripts|/images|/lang)
 RewriteRule ^(scripts|images|lang)(.*)$ /webroot/$1/$2 [L]

 RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[.*])$  [NC]

 RewriteCond %{REQUEST_FILENAME} !-s
 RewriteCond %{REQUEST_FILENAME} !-l
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d

 RewriteRule (.*) webroot/index.php
 RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

cor - 04.12.08 4:01 pm

I'm getting a headache just looking at it!

First thought is, "Is this some kind of joke?". Really, who designed this layout? Don't answer that. And what's with all the multiple file system calls? And how's any request supposed to get to the php-cgi-auth-workaround-thingie line? And why the the redundant regexp. Also, I have near-zero experience of working with mapping files.

My next thought, was, "Why not map directly into webroot/ ?". Which probably proves the previous statement!

"locking" library/ from viewers is easy; from part 1 of these articles..

deny from all

Have another look at your layout.

;o) Cor

jasmit - 07.12.08 2:45 pm

hi corz

hi read your article and comments and found a code that i needed for my site but not able to get it work.

i get an error 404 object not found.

i have mod_rewrite active.

i have url

and i want to change it to

i m using the below code
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{THE_REQUEST} dealer_id= [NC]
RewriteCond %{QUERY_STRING} dealer_id=(.+)&category_id=(.+) [NC]
RewriteRule ^products.php /products [NC,L,R]


Are you sure you don't mean you want to convert FROM jasmit/products TO jasmit/products.php?dealer_id=9&category_id=1, in other words, you want users to use and see the short URL, but in the background have it send these variables to your script, right? You are working back-to-front, or more correctly, ass-backwards.

Realize, these variables have to be somewhere within the "short" url, either literally (e.g. /products/9/1/), or mapped somewhere to longer variables (inside your php script, e.g. /procucts_a/ => "a" = "1"), then go read the sections above about shortening URL's and making flat links, and then try again. ;o)

willowdan - 11.12.08 2:59 pm

I'm very thankful for this guide... Fort time for me to apply url rewrite, and this has been very helpful.

What I simply did was to preserve the id's within the new url, example: or

... and simply made the category_name and ad subject be part of the new url.

Many thanks,

aman - 20.12.08 3:37 pm


i have a url like

i used rewrite to make it seo friendly
RewriteRule ^product([^/\.]+)?.html$ description.php?id=$1

it gives me

now i want to replace "product" word with dynamic word coming from database.
how can i do it.
if i manually replace "product" word with "nokia" in htacess
RewriteRule ^nokia([^/\.]+)?.html$ description.php?id=$1

then it works

what should i write in rewrite rule so that it accept dynamic word inplace of "product".
so that my url become


Your database can spit out whatever links you like. All you need to do is catch the string, along with the id, and feed it to your target/script, something like..

RewriteCond %{REQUEST_URI} !description.php [NC]
RewriteRule (.+)([0-9])\.html$ description.php?id=$2&product=$1
That rule could be improved, by the way, but it will get you started. ;o)

Pedro - 23.12.08 3:53 pm

Hi there,

Great tutorial, but a bit way to confusing for me at this point, and my question is this...
I want to monitor how much bandwidth is used when files (images) are called by the users so i have set a php script to do it, and with a RewriteRule, i thought it would do the trick, but i am probably missing something as it does not work.

all files i want to monitor are in www/images/upload/username and htaccess file is in www/ (where www is the web root for the site), and so is bandwidth control file
And the rule is this...
RewriteRule images/upload/([a-zA-Z0-9_-]{1,})/([a-zA-Z0-9_-]{1,}).(jpg|jpeg|gif|png)$ bandwidth.php?u=$1&i=$2.$3 [L]

how would it needed to be set to properly trigger the bandwidth.php?

The rule itself looks valid enough, though probably over complex, and that's what's tripping you up. For example, the {1,} sections are redundant (pseudo-copying from the ILoveJackDaniels Cheatsheet, eh?), and [a-z0-9_-] is probably just fine (you can use [NC,L], remember). In fact (.+) would probably work just as well, maybe ([^/]+).

And while we're here, (jpe?g|gif|png) is neater. In other words, simplify things. Also remember, to specify an actual dot in the RewriteRule, you need to do \.

Also, actually reading the article might be helpful to you. Give it a shot!


p.s. If you post more code here, it's best to use [pre] tags (this is mentioned in the big notice above these comments, as well as in the help underneath, and error message you received when you first tried to post) - I switched your code into these, you'll notice. Much easier than messing with double-brackets. smiley for ;)

Ravin - 23.12.08 5:10 pm


I have read this tutorial carefully n some posts have also answered my problem but still none of them solved it. Issue is very simple but i am not getting where i am going $%)(^%,. I want to convert http://localhost/Tasks/Login.php to http://localhost/Tasks (simply putting, i want to hide extension). Any suggestions for me???

Thanks for time and help.

Happy coding smiley for smiley for :)

code i am putting in my root folder.

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(tasks)$ *.php

smiley for :lol: That's got to be the wackiest RewriteRule I've seen all week! Your biggest trouble is that "Tasks" is an actual directory, and you are attempting to use it as a "virtual" path. Fortunately, while definitely not recommended, it is doable, try this..
RewriteCond %{REQUEST_URI} !Login.php
RewriteRule ^Tasks/? Tasks/Login.php [L]

Pedro - 23.12.08 7:45 pm

And you know... a set of fresh eyes make wonders. After all, a few minor tweaks were more than enough, and the missing \ was the mother of all troubles.

THANK YOU very much for it smiley for :)

RewriteRule images/upload/([a-z0-9_-]{1,})/([a-z0-9_-]{1,})\.(jpe?g|gif|png)$ bandwidth.php?u=$1&i=$2.$3 [NC,L]

Working as charm!

Now, all you need to do, is replace "{1,}" with "+", and you have a real RewriteRule! ;o)

Swapnilab - 26.12.08 2:12 pm


An excellent tutorial on .htaccess, thank you! smiley for :D
I am Practicing you code and some of it works for me. Now I am able understand proper use .htaccess file. earlier this i was thought .htaccess used for url rewrite and some ini setting. but its more than this.

Thank you again for this superb Tutorial.

have a great time and day.

Dennis - 26.12.08 8:00 pm

I just want to express my appreciation for your excellent standards-compliant site. Your htaccess examples quickly led me to a solution for my particular application, and the Html Validator extension I'm running in Firefox reports no errors or warnings---a very rare and much welcome occurrence. Thank you!

thomas alexander - 27.12.08 11:03 am

i have a url like this


i want to convert to


i could display http://server/harold/index.php to http://server/harold/index

when i put http://server/harold/index/ the images are not listed i used the below code

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^index$ index.php

can i write a single line code to rewrite all php pages in directory format or do i have specifu separately for each page

cor - 28.12.08 10:46 pm

Swapnilab. in truth, I keep looking at it and wondering how anyone can make heads or tails of it, and thinking of improvements, but there you have it; it seems somehow it gets the data into people's brain. Cheers!

Dennis; I absolutely adore it when folk notice+mention it; the usual reaction, in the 1% who do notice, is to scurry off, ashamed, to their text editor, in a frenzied gush of compliant code. At least, that's my fantasy. Thank you, I mean it. I could count, on one hand, the number of bona-fida comments I've had about the fact that every single single fucking page (expect the old OSX section, of course) is 100%, hell-yes Standards-compliant XHTML 1.0 Strict, with not even a whiff of a warning message; read, green tick all-the-way-baby! I'm guessing we both installed the very same extension (TIDY) - something I often recommend to web developers.

*deep breath*

*ahem* where was I. Oh, yeah, cheers, it actually took me 200+ hours to get the site compliant (3000+ files, you know!); another holiday I never got! smiley for :roll:

thomas alexander, yes, you can use a single line. (gets poked by conscience, continues..) But remember, if you are using relative links for the images, you will also need to rewrite those links.

;o) Cor

Dexter - 29.12.08 4:57 am

First of all, great site dude.

I know this seems easy but i haven't found a simple solution.
We know that the "^" when not used as an anchor serve us to exclude chars from a match but i want to allow a range of numbers between 1 and 9 but excluding the "5" digit. all the examples i've found have examples like this: [^1-9] excluding any digit of that range or a specific char like this ^5 but they don't have an example which excludes a single char or a range of chars from a previous range. i tried with this [1-9]^5 to get what i want but didn't work. any suggestion?

Sure, what about.. [1-46-9] ;o)

Dexter - 29.12.08 8:11 pm

Thanks for the quick reply.

That's gonna do the dirty job for sure but as far as i have messed around with this cool stuff, which is new for me, makes me wonder: there's no way to exclude characters from a range with "^" ? If so, i'll just have to do some little hacks to get it work like you did spliting the allowed numbers in two ranges to leave "5" digit out. the thing is that for each excluded digit i'll have to split the range once again. Well, i guess they have their reasons to make posix work that way.

Anyway. Thanks again man. I already have bookmarked your site in my frecuent websites folder.

By the way, while surfing the net i found a nice regex tester made in flash. I hope it can help others to experiment with strings to mess around with regex: right here

cor - 29.12.08 9:14 pm

Hey! I didn't say it couldn't be done! A double grouping is just the simplest approach, one that would suit most people's needs. But I can think of at least two ways you could specifically exclude the "5" digit, if you really need that.

The first and most obvious, is with a RewriteCond statement, something like..
RewriteCond %{REQUEST_URI} !images/5\.png$
You would, of course, make it specific to whatever resource you are trying to not rewrite, matching your RewriteRule, except with the 5 instead of the grouping.

The second way, though less obvious, is perhaps superior, and that is a "negative lookahead". Basically, if the lookahead matches, the ReWrite is bypassed, something like this would do what you want..
RewriteRule images/(?!5)(\d+)\.png$ index.php?foo=$1 [NC,L]
Note, I used \d; a short form for :digit:, which is the same as doing 0-9. I've used the fictional images/5.png as my resource to exclude, but you can, of course, use whatever you need. Oh Joy of POSIX!

Thanks for the link. I have a few of these types of things in my bookmarks; one of which may yet end up in the useful links section.

Have fun!

;o) Cor

kylemech - 29.12.08 10:05 pm

In the process of moving between content management systems, I'm trying to redirect users looking for old member profiles from their old location to the new format. I'm using the following rule:
RewriteRule ^/faculty_staff/profiles/(.*)\.asp$ /users/$1 [R,NC]
The request can come in different cases, but as I understand it [NC] takes care of that. I'm not having any luck with this rule, so I must be misunderstanding something. I suspected that my search string is incorrect, but I couldn't find any obvious reason.

Any ideas?

Yes. Read the article, and you'll know exactly why. ;o)

Dexter - 29.12.08 11:52 pm

Thanks again, i hope you're not getting bothered because of me coming back and asking again but negative lookahead stuff is kinda new for me, i thought i understood it but it seems i have not got it at all. what i'm trying to do is making friendly url's. the accepted strings go like this:

/mod/ver/any number (except 5) five times

so what i currently have is:

RewriteRule ^mod/ver/(\d{5})(?!5)$ /mod/index.php?id=$1

i thought that if i had mod/ver/12345 it would only match the string before "5" so the string wouldn't be valid because the number part would match until "1234", four numbers, not five, so it doesn't match;but no luck, it still accepts "5" as part of the string. i'm sure it's because i didn't know how to implement negative lookaheadsmiley for :roll: Been looking for a workaround but no luck finding similar examples.

Any suggestion is accepted. thank you very much

You could use a RewriteCond to do the actual capturing, and use the RewriteRule lookahead to check for the 5-not-5, e.g. ((?!5)\d){5}. Though perhaps less readable, you could also put the whole lot in the RewriteRule, like so.. (((?!5)\d){5}). There are other approaches, too. ;o)

rick - 30.12.08 5:34 pm

-Fixing paths that start with a forward slash-
A site I'm working on currently has no domain name. The only way to view it is in a sub-directory of an ip address.
Many images and links pathed are root relative I.E. "/images" since the preview of the site is in a sub-directory this breaks all of the images and links that begin with the forward slash. Is there a way to write a htaccess file to rewrite the root relative paths?(To many files to search and replace)
Something like "/images" to "preview/www/images/"

Thanks in advance.

Yes, there is a way. ;o)

This is what I have now.

RewriteBase /images/(.*)
RewriteRule ^/preview/mysite/files/images/(.*)$ /$1

Where did you get that?  No, don't answer that. The solution is quite simple. Read the article (above) and try a few things. You'll figure it out. ;o)

Dexter - 30.12.08 9:58 pm

You're the man!! Works perfectly. i also have some e-books of regex so i will check them out to get into the deep well of regex, and luckily i will come back to the surface knowing one or two tricks. Will be around. Thank you very much. i will contribute through paypal as soon as i can.

Heh, thanks. Truth is, although I've known about regexp lookahead for some time, I've not had an opportunity to actually use it for rewriting, so this was a fun head-scratcher. Good luck with the regexp learning (e-books are good, but many excellent tutorials and guides are available online for free); once you get your head around it, it sure is powerful stuff. ;o)

Sean McGilvray - 02.01.09 10:26 pm

I have the following problem.
I have my old domain that users were using to get to my site with a user name.


I am moving to RoR app and want to rewrite all incoming request like a above to the new address.


How do I make this happen with .htaccess. I have tried many different ways and none are working.

Thank you,

Sean McGilvray

Jason - 12.01.09 10:12 pm


I have read your article, and they have helped all but my final issue. Hopefully this example will help you to see what I mean without a ton of words.

I would like the URL

(really we're just focusing on anything after chemical as the base) to convert serverside to

The rules I am working on are as follows:
RewriteRule ^([^/]+)/([^/]+)/$ /kgcoe/chemical/index.php?section=$1&subsection=$2 [l]
RewriteRule ^([^/]+)/$ /kgcoe/chemical/index.php?section=$1 [pt]

On the server, I have a folder for each "section", but not for subsections, such that inside of the department folder there would be both department.php (the section) and mission.php (a subsection).

If i enter something a file that doesn't exist (/department/squiggly), it works fine. It is only when the subsection .php file exists that I have issues.

Thanks in advance!


Björn - 14.01.09 3:49 pm

Great Article and very helpful! smiley for :) Unfortunately it didn't help me with what I'm trying to do...

Basically I want my MAIN index-page to NEVER show "/index.htm" in the address-field but all OTHER index-pages to ALWAYS show it... To achieve the first I can use:
RewriteRule ^index\.(.*)$ [R,L] 

And to achieve the other:
RewriteRule ^(([^/]+/)*)$$1index.htm [R,L] 

Naturally I can't use those two at the same time as that would create a never-ending loop for "". Another part of this problem is changing folders from format "" to "" that is making sure there's always a "/" at the end...

Would be very thankful for any help!

Björn - 15.01.09 8:14 am

Hello again!
I managed to solve the problem on my own... Not sure if this will slow down my site in which case I will have to think of another way to do it. Anyway... Figured I'd put the code and what it does here in case someone else has similar problems... Here goes:

# Turning the magic on:
Options +FollowSymLinks
RewriteEngine On
RewriteBase / 

# Making sure the "www." is always shown:
RewriteCond %{HTTP_HOST} !^www\.(.*)$ 
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R,L]

# Removing /index.* from address field for startpage:
RewriteRule ^index\.(.*)$ http://%{HTTP_HOST}/ [R,L]

# Making sure foldernames end with "/":
RewriteCond %{REQUEST_URI} !\..+$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [R,L]

# Making sure "/index.htm" is always shown in "/folders/" (but not in the root or /tags/ folder):
RewriteCond %{REQUEST_URI} !^[/]$ 
RewriteCond %{REQUEST_URI} !/tags/(.*)/$ 
RewriteRule ^(([^/]+/)*)$ http://%{HTTP_HOST}/$1index.htm [R,L]

# Sending every visitor in "/folders/" to "page.php" and making exceptions for files my
# PHP-script will be calling. I can then write page.php to control
# what content to show depending on what is in the address-field:
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_URI} !img/(.*)\. 
RewriteCond %{REQUEST_URI} !swf/(.*)\. 
RewriteCond %{REQUEST_URI} !php/(.*)\.
RewriteCond %{REQUEST_URI} !pics/(.*)\.
RewriteCond %{REQUEST_URI} !page.php$
RewriteCond %{REQUEST_URI} !index.php$
RewriteRule ^(.+)$ page.php [NC] 

I hope this can be helpful to someone and I would be thankful for any improvements!

P.S. This should be really good to use for SERP-optimization but remember to change the [R,L] to [R=301,L] once you know everything works... D.S.

Bes - 17.01.09 2:34 pm


Fantastic article -read it all the way thru, but having an issue as follows:

RewriteRule ^test-(.*)-(.*)\.jpg render/imgEdit_jpg.php?an=$1&col=$2

I want to use this to get values for both an and col.However, the php script I am submitting to always reports col as blank.

The problem seems to be occurring with the ampersand, as this:

RewriteRule ^test-(.*)-(.*)\.jpg render/imgEdit_jpg.php?an=$1$2&col=

Allows me to see everything I am expecting (i.e. the value I inputted for col in my form appears in the PHP script

Any ideas?


cor - 17.01.09 9:05 pm


Jason, your question doesn't entirely make sense to me. I don't understand why there's a folder called "department", with anything in it; your rewriterules never point to there, only to /kgcoe/chemical/index.php. That index.php looks to be the handler, and /directory is a virtual path. So why does it really exist?

Sean McGilvray, I've no idea what RoR is, anyways, check out the section (above) about capturing variables. It has what you need.

Björn, I handle this with php, which I find superior. Here's a copy of some of my site's init.php script..

// redirect initial requests for folder/index.php to folder/ (neater, and better for SEO, too)
// better than using .htaccess (if you have $_POST forms, for example)..
if (substr($_SERVER['REQUEST_URI'], -9) == 'index.php' and empty($_POST)) {
header('Location: http://'.$_SERVER['HTTP_HOST'].str_replace('index.php'''$_SERVER['REQUEST_URI']));

It would be trivial to adapt to your exact requirements (root, not root, etc.)

Bes, Your code is fine (both statements). I would use a less hungry quantifiers (.+), but unless the supplied links are in the wrong format, it should work as expected.

Perhaps you might want to check your setting for php_value arg_separator.input.

;o) Cor

Jay - 21.01.09 8:11 am

How can I redirect my main domain 1 level down to a sub-folder but the sub-folder name should not show in the URL address bar?

e.g. which root @ /public_html pointed to /public_html/ABC/gallery but not showing in the URL bar?

Million thanks.

Jay, I recommend mod_rewrite. It can do exactly what you need. I have an article all about it, here. ;o)

eccentricegg - 31.01.09 8:32 am

Excellent site, although much of the subject matter is currently well beyond my comprehension. I stumbled my way here through myriad websites looking for an easy way to test hotlink redirection and after reading several pages I found not only the hotlink tester,but also a dynamic hotlink image creation script, and a wealth of .htaccess information. Thanks.

My next quest will be to find information on serving compressed content to browsers that support it and testing to ensure the changes work as expected. I'm unfamiliar with PHP or any other programming/scripting languages but have tried to use mod_deflate for gzip compression without any success.I used the following line:

Added to .htaccess
AddOutputFilterByType DEFLATE text/css text/html text/plain text/xml

After reading article from several times, I get a server generated error page (as opposed to my custom error page).

One note about the hotlink tester, when I ran the test my redirected image never finished loading (I waited 5 minutes over cable connection, it's under 2k in size), however I was able to right-click, copy the image address of the alt text, and it did, in fact, point to the desired redirect image. I'm not sure why the image never loaded but the test was otherwise successful.

cor - 31.01.09 9:52 am

Working back..

It sounds much more like the hot-link generator test was unsuccessful, and that, for some reason, the script failed to complete. This could be any number of reasons, though most likely, the test server did not meet the requirements of the script, which would be roughly php4.2 with GD library (or whatever it says at the top of the script). Check your error logs for the exact cause.

As for your compression tests and the server error (I'm assuming you meant a 500 error - didn't it specify a code?), it sounds like mod_deflate isn't enabled on your server. If you have access to the main configuration (this is your test server at home, right?), uncomment that line in the LoadModule commands, and restart Apache. Otherwise, you'll need to either pester the server admins, or better yet, try another approach. Or was it another error code?

Oh! And it's unlikely that you reading the Apache documentation caused the server error, much more likely something you did. smiley for :lol:

If you aren't using php to zip the output (read: the easy approach, as outlined in part one of these articles), then you may find this site useful. Another useful thing is the "View Response Headers" feature of Firefox's Web Developer Add-on; you can instantly see if the page arrived compressed, though note, it seems to cache the results, and I vaguely remember playing with this a while back, and having to make fresh copies of my test document for each test, to guarantee accurate results. Otherwise, it's excellent. Check it out.

As for all the web stumbling, why not simply Google: hot-link test   smiley for :ken:

Lastly, it's unlikely that any of the subject matter here is beyond your comprehension. Maybe your current comprehension, but that's easily fixed!

;o) Cor

eccentricegg - 02.02.09 7:57 am

Thanks for the tips.

I actually didn't test the hotlink generator. I merely tested the redirection using a static image. This was the image that was not displayed but was, in fact, the source of the image that never loaded.

When I added the line to .htaccess, it was as you suspected a server generated 500 error code(as opposed to my custom error page). Unfortunately, this is a hosted site. So that seems like I will need to "pester the server admins."

Does the PHP approach work with other filename extensions or is it dependent on filenames ending in .php? The site uses server side includes extensively and the host requires pages using such includes use .shtml extension. Are there any other options to compress output to browsers that support compressed content, that will work without mod_deflate (assuming my passionate pleas do not dissuade the host server adminssmiley for :erm: ) and without changing filename extensions?

It seems I may have to try Firefox again. I've been using Opera extensively for years and it will be a tough transition. I may have to use both for some time.

cor - 02.02.09 6:30 pm

This was the image that was not displayed but was, in fact, the source of the image that never loaded.

What? smiley for :eek:

As to your question.. Yes. The technique described here will work for any file extension you choose, so long as it's something php can handle, you can have the php engine serve it up, even if there's no actual php code in it.

Some would argue that it's not an efficient use of php, but unless you are hosting slashdot, it's probably not an issue, and anyway, getting small download sizes seems to be your main priority, so I'll expound..

First, setup zlib.output_compression, as described, here. Then output your .shtml files through php, as described here. There is a second code example in the text under the code box, which would probably fit your needs as-is.

I don't know of any other ways to compress files, that are guaranteed to work on any hosting setup. It's usually a case of trying one method, and then another, and if it's still not working, pipe it through php and use gzip. Whether or not this might interfere with any SSI you might have, is something you'll need to test.

As for Opera, I like it. It's a fun browser, with some nice features. But when you regularly develop for the web, Firefox is really the only choice. The ability to plug-in what you need, build whatever custom browser suits you, nothing comes close. A vast array of free tools are available as Firefox Add-ons.

Of course, Add-on development isn't always up-to-date with Firefox's development, and that is an issue when Firefox does a major upgrade - who knows when I'll get to use Firefox 3! But with FF3 not long out, this is definitely a good time to "get in".

for now..

;o) Cor

eccentricegg - 03.02.09 5:54 am

This was the image that was not displayed but was, in fact, the source of the image that never loaded.

What? "

I right-clicked the image place holder and copied the image address that it was pointing to and it was the address of the redirected leech image not the image I pointed the script to. So the redirection itself was relatively successful(of course it would have been nice if the image actually loaded)smiley for :ken:.

I added the following to my .htaccess and tested using "" and if said that the content was NOT compressed. I am beginning to wonder if the compression is worth the effort at this point. (I don't know if you've looked at the site in question but there's not much to look at so far.)
I think this is a point where my comprehension lacks behind my wishes. I feel totally cluelesssmiley for :ehh:

BTW my includes don't seem to be working fully either.


# begin zlib compression #
<ifModule mod_php4.c>
php_value zlib.output_compression 16386
# end zlib compression #

# begin handler for phpsuexec..#
<FilesMatch "\.(css|style)$">
SetHandler application/x-httpd-php
<FilesMatch "\.s?html$">
SetHandler application/x-httpd-php
# end handler #

I'm getting a bit frustrated with my lack of knowledge in this arena.

Thanks for all your help so far. I just wish I knew enough to apply your know-how with greater success.

cor - 03.02.09 6:08 am

Gotcha. Yeah, it looks like your mod_rewite code was doing rewriting, but for some reason, the auto-hotlink script isn't working as expected. Load the script on its own if you want to debug it. Remember to set your preferences (inside), first.

That's a handy gzip test tool, thanks for the link. I tested my front page; it's working fine (the tool, that is).

Looking at your code(box), I see you kept the old "php4.c".. Are you certain that your server uses php4? Try "php5.c", instead. Or simply omit the ifModule line (the worst that can happen is you get a 500 error if php isn't loaded, in which case, all this is futile, anyway)..
php_value zlib.output_compression 16386

<FilesMatch "\.s?html$">
  SetHandler application/x-httpd-php
Frustration comes with the turf. Once you get it working, that evaporates.

;o) Cor

MaRmAR - 13.02.09 10:51 am

Thanks! You just solved my problem smiley for ;)

No, I provided information in a form that was accessible. YOU solved the problem. ;o)

saiful haziq - 18.02.09 12:58 pm

you really made a nice job. thx smiley for :cool:

Isindim - 18.02.09 8:19 pm

Thanks for a very helpful site -- one problem I've been trying to solve (and hoped to find the solution here, maybe it is there but I can't get it working), is how to redirect a PHP site to a regular HTML one. Your examples show the other way round.

In other words, how would you use .htaccess to redirect

That would be really helpful if I can do that!

Thanks again.

..However, my flat-links examples show it just the way you want. In other words the solution is in the text of the above article. Only post here again if you have code. ;o)

jonesy - 19.02.09 7:19 pm

Hi all,

Just like to say thanks for the useful info you given us! A lot of this is way beyond me at the moment. Anyway, basically I need to remove .html extentions from all my pages, I'm guessing this is quite simple for you guys considering the complexity of some of the code i read. This is as far as I have got at the moment:

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{http_host} ^www\.domain\ [NC]
RewriteRule ^(.*)$$1 [R=301,NC]
RewriteRule ^index\.(.*)$ http://%{HTTP_HOST}/ [R,L]

I am completely clueless as what to do?? Any help would be much appreciated,


Seeing as how you are completely clueless anyway, allow me to recommend that you NOT remove .html extensions. The web is confusing enough as it is. ;o)

Beautiful Ways - 20.02.09 1:19 pm

First of all, thanks for the detailed guide! I've been looking for this kind of thing for ages and never seemed to find any good documentation until now smiley for :D

Anyway, I've been trying to set up some RewriteRule's, and have had success... with most of them. For some reason, two of them aren't working - even though they're based on the same code with only two parts changed =/

Here's some of the code:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^register /user.php?mode=register [NC]
RewriteRule ^user/([^/]+)/profile /user.php?mode=view&usern=$1 [NC]
RewriteRule ^fests /festivals.php [NC]
RewriteRule ^forum /board.php [NC]
RewriteRule ^links /links.php [NC]
RewriteRule ^contact /contact.php [NC] by typing this:
If should redirect to links.php but for some reason it doesn't, instead resulting in an "Internal Server Error"... I read about removing the +FollowSymLinks part in case the host disabled user-level settings, but all the files are in the same directory and the only rules that don't work are "links" and "contact"!

If anyone has any ideas, please let me know... I'm stumped!


I took out the '/' from in front of links.php and contact.php, and now it works... I have absolutely no idea why those two fail with the slash when the other rules work fine but meh, at least it works.

It looks like you threw mod_rewite into a crazy loop which it recognized as a configuration error, which it was. Your solution basically forces mod_rewrite to ignore subsequent rewrites and continue. A better solution would be to use an anchor, like so..

RewriteRule ^links$ /links.php [NC]

It is also less confusing. ;o)

Anton - 25.02.09 5:48 pm

Hi there, I got a problem here

I got a few pages that where links are directing to the page it self but with more and more GET variables each time

like next step is and so on
about 4 times or so

So how can i make a revrite rule to have flat links here?

say next and so on

any ideas?

The error is clearly on the first line of your code. Oh, wait a minute, you don't have any code! That will be what's causing the lack of functionality. See the flat links section, above, and try some stuff. ;o)

reutopya - 26.02.09 2:16 pm

i search to rewrite this url:
is this possible? if yes, what i have to put in .htaccess?
Thanks smiley for :)

Yes, it's possible. What you put in your .htaccess is RewriteRules. There's a big article all about them, right above these comments. Check it out! ;o)

reutopya - 27.02.09 4:57 pm

I searched but I found nothing that help me :(
can you tell me what i need to put into .htaccess? thanks

It will take you a lot less time to read the article, than it took me to write it in the first place. ;o)

Raghavendra - 01.03.09 3:33 pm


i have created .htaccess file with

Options +FollowSymLinks
RewriteEngine on
RewriteRule family-id-(.*).htm$ family.php?id=$1

but it is not opening any page in localhost and in server

the error is

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, admin@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.


i didn’t come to know hoe i need to do.


A.K.A "500 Error". This means there is an error in your configuration, most likely in your .htaccess file. Double-check every line. Also ensure there is a full blank line at the end. ;o)

sing - 04.03.09 8:13 pm


Have you enabled
"LoadModule rewrite_module modules/" in httpd.conf file?. I assume you use Apache Web server

Heh, actually that might be one httpd.conf gotcha worth adding to the article! smiley for :D  ;o)

Smartness - 07.03.09 10:02 pm

Hey, a little question here!

this is the url:

the page title of that page is example:
Hello - How Are you Doing!

How to rewrite to:

Is it possible?

Yes, it's possible. Examples above. ;o)

Ryan - 13.03.09 3:43 pm

I have been reading your htaccess guide and its brilliant.

Just a question, is there anyway to htaccess rewrite index.php#anythinghere to /#/anythinghere

? do it, but I don't know if thats htaccess or javascript.


smiley for :)

Firstly, mod_rewrite can't work with the part after the "#", because it's "a browser thing" which the server doesn't see; a page anchor; so if any site is redirecting with it, it's probably Javascript/Ajax of some sort. I've not seen any examples of this.

And secondly, I don't think that's what's going on at - none of their links, that I saw, have a hash in them, it's simply a part of the final URI path, in other words, /magazine >> /#/magazine/. ;o)

Ed - 15.03.09 4:25 pm

I am rather new to .htaccess and I don't fully grasp all the rules.
I have been racking my brain to come up with a solution.
I have this in my .htaccess and I am getting too many redirects in the browser.
RewriteEngine on
RewriteRule ^search-results/([^/]+)/?$ /results?Search=$1 [L]
RewriteCond %{QUERY_STRING} ^Search=([^/]+)
RewriteRule ^results /search-results/%1? [R=301,L]

But when I remove the $1 from the first line as below, the redirect works, but the search results are no longer being filtered returning all the results in the database.
RewriteEngine on
RewriteRule ^search-results/([^/]+)/?$ /results?Search= [L]
RewriteCond %{QUERY_STRING} ^Search=([^/]+)
RewriteRule ^results /search-results/%1? [R=301,L]

I am completely stumped. Any help, advice, direction would be "GREATLY" appreciated.

First, you create a loop. Then you remove one of the conditions of the loop so that it does not loop. Okay. It would be useful to know what you are trying to do. Let's see if I can decipher that...

Nope, nothing is coming to me. But my advice would at any rate be to keep the $1, and instead remove lines 2 and 3. ;o)

Czakalli - 16.03.09 9:06 am

Hi there,

congrats on the nice tutorial you have here.

i'm making a script for multiple domains (a few hundred).
I would like to make a redirect for domains without the www. (like into

if i write the domain it works, like this:

RewriteCond %{HTTP_HOST} ^$ [NC]
RewriteRule ^(.*)$ [R=301,L]

but i would like to have all domains redirected without writing one by one.
smth like this won't work:
RewriteCond %{HTTP_HOST} ^.*\..*$ [NC]
RewriteRule ^http://(.*)$ http://www.$1 [R=301,L]

any help would be apreciated.

As much as it pains me to help someone to ADD "www" into their domains, I'll give you a clue..

You need to capture the host, all of it. ;o)

John Wilson - 19.03.09 3:55 pm

I spent an hour or more looking for only a portion of what you provide here.

Others just talk a little and give no explanation or instruction so that a reader can go and create a rewrite.

Your presentation is excellent.

I was trying to understand redirection and use it to make search engine friendly links. Links that were cleaner looking.

While I haven't digested the entire article, I am confident that the answers to my questions are here.

Thanks so much for such an informative piece.


koorosh - 20.03.09 8:21 pm

hello could you please help me ?

i want to redirect this address for example :

to :

(/ insted of ? )

i have read your learning but really i cant use them for this issue...

Take a loop at the "PATH_INFO" server variable. ;o)

ma69 - 23.03.09 8:48 am

excellent information.


paulo - 26.03.09 7:57 pm

First, great info you are providing. Next, I might be stepping into areas not related, but I'm using Joomla 1.5.x for which there are modules with the Google translator.(and there is one which claims to solve the following problem, but it does not work for me.) A problem arises when trying to get Google to translate pages that are password protected (e.g. a member's profile). Depending on the module, it either kicks the user out of those password required pages, fails, or shows a blank page. I have tried a couple of variations for the rewrite rules but no success. Google apparently treats it as a bot and disallows. Not sure. Could this be handled in .htaccess? Anyway, thanks! (one aside and nobody ever mentions it: Is there a heirachy that lines must be entered in .htaccess?)

Unless Google has a membership (and knew to login!) this isn't gonna work. Remember, Google is grabbing the page for you.

As for "heirachy", no. .htaccess lines are simply read in order. ;o)

Peter Nichol - 29.03.09 6:21 pm

Love the mod rewrite's you've got here.

I used it to make my dynamic sitemap

Graham - 30.03.09 2:30 am


I'm having real trouble with this, I have an .htaccess file that I am using to send all requests to a control file "content.php", the current htaccess looks something like this:

RewriteEngine On
RewriteCond %{REQUEST_URI} "/google*" [OR]
RewriteCond %{REQUEST_URI} "/y_key*" [OR]
RewriteCond %{REQUEST_URI} "/ajax/*" [OR]
RewriteCond %{REQUEST_URI} "/resources/*" [OR]
RewriteCond %{REQUEST_URI} "/nav/*" [OR]
RewriteCond %{REQUEST_URI} "/sitemap*" [OR]
RewriteCond %{REQUEST_URI} "/style.css" [OR]
RewriteCond %{REQUEST_URI} "/travel-guide/*" [OR]
RewriteCond %{REQUEST_URI} "/js/*" [OR]
RewriteCond %{REQUEST_URI} "/content.php" [NC]
RewriteRule ^(.*)$ $1 [L]
RewriteRule ^(.*)$ /content.php?url=$1 [L,QSA]

All this seems to work fine but for some reason when I try to access a file e.g. /travel-guide/file.php it throws a 500 error.

It has been working properly for over a year but doesn't seem to like it??

Any help would be sweet.

Oh man! Where to start? Firstly, I can tell by the fact that you didn't use the [pre] tag to post your code, that you don't read the instructions. Maybe you think you do, but probably your eyes are moving too quickly over the words, and their meaning isn't getting to your brain.

Instead, you laboriously double-bracketed your entire code example.
I put that in a paragraph on its own in the hope that you will read it a dozen times, print it out, pin it to your fridge, make a T-shirt, and so on. Lessons for life. So, getting errors are we? ..

RewriteRule ^(.*)$ $1 .. is just plain hilarious. Thanks for that.

And why all the asterisks? Did you think this was a windows file search? I mean, what is the actual point of them? By which I mean, there is no point. "foo" matches "foobar".

And why all the double-quotes? Exactly who told you to use those? By "exactly", I mean please send me their email address so that I may abuse them, textually.

What else? Oh yeah! The whole shebang only works (assuming everything else was fixed!) if the REQUEST_URI is for content.php! Nice one! smiley for :lol: Of course you meant to specify that it not be for content.php..

RewriteCond %{REQUEST_URI} !content.php [NC]

Working properly for over a year? smiley for :lol: Right! Maybe the "RewriteEngine On" part! ;o)

R - 03.04.09 7:54 pm

Great article! I find it mildly amusing that despite the section on hotlinking and stealing content, your entire page has already been "borrowed" and placed on someone's blog:
http://th-e dot blogspot dot com/2007/09/htaccess-tips-and-tricks.html

Anyway, my question was that I can't figure out how you were able to have the google translator header disappear on the translated page? I can't seem to do this on my page, and I reviewed your source and didn't see anything that would point to a solution. Could you give me a hint? smiley for :) Thanks!

I remember when I found it mildly amusing. Now there are dozens of copies. There are even whole domains that are nothing but this page! smiley for :eek: What's annoying is that I do update even my oldest pages, and the "other" copies never reflect these changes. Mind you, since the wayback machine stopped indexing me a couple of years back for some reason, this might not be such a bad thing!

As to the "secret" of how I make the Google strip disappear. Well, that's not .htaccess. Check my page source for JavaScript includes, there's one called "breakout.js". What you are after is in there.

Be mindful if ripping it off for your own site. Lots of community bookmarking sites use frames to embed other sites, or add their own site frames, and breakout will render them completely ineffective, quite probably along with any ability the user may have had to vote on your site. I don't care for all that silly shit, but many do.

breakout.js provides an option to allow certain containers, but this, being my JavaScript, isn't 100% reliable. Google images, for example, can't contain one of my pages, even though I added Google to the allowed containers. As implied, it might be my JavaScript code, in which case, feel free to update that and return it to me working! smiley for :D

I guess it wouldn't be too difficult to write some JavaScript to only breakout of certain, specified containers. I've just not bothered. ;o)

Dr P - 07.04.09 7:18 am

Dynamic Fail

Hey, I've been playing with .htaccess for a little while and it's frustratingly not working the way I would want.

Really simple flat link setup.

I want to rewrite


Example1 works very well. I want it to be dynamic but Example2 fails with a 500 code.

Example 1 - works

Options +FollowSymlinks
RewriteEngine on

RewriteRule ^home$ /index.php?p=home [NC]

Example 2 - fails

Options +FollowSymlinks
RewriteEngine on

RewriteRule ^([^/]+)$ /index.php?p=$1 [NC]

I've tried all sorts of combinations within the parenthesis... without luck.

I'm running around in circles I think... smiley for :eek:


You could get by by simply removing the forward-flash before index.php, but it still wouldn't do what you want, because it would loop around and "p" would always be "index.php". You need to think outside the parenthesis..

Specifically, you need to specify a condition; that you only want to rewrite requests that aren't already pointing to your target. Something like this would work well enough..

RewriteEngine On
RewriteCond %{REQUEST_URI} !index.php 
RewriteRule ^([^/]*)$ index.php?p=$1 [NC]
There are other things you could check for to achieve the same goal, like whether or not a request has already been rewritten, or whether it already contains variables, and so on. Those three lines are the basics, though. ;o)

Bhagwat - 08.04.09 6:43 am

i have one site

when i try to type following in url

it is showing me 404page.

can u help me if user type aanything like (/kkk or /23222) it will not consider this and index page successfully show.

The easiest way forward is to use index.php, instead. You should find what you are trying to do works fine.

Alternatively, have .html files parsed as php..

<FilesMatch "\.html$">
  SetHandler application/x-httpd-php


cwd - 11.04.09 10:11 am

this is an excellent guide. i would love to see more info on the different switches (NC, R, R=301, L) and so on. Thanks!

Jason - 13.04.09 2:52 am

Thanks for writing this article. Mod-Rewrite is an intimidating beast, and you've managed to make it much easier to understand. That's talent, right there. Thanks!

nasal - 15.04.09 1:55 pm

Great blog post but..

*Splutter* WHAT? You cheeky bastard! If it weren't for the fact you go on to state you read the comment disclaimer; which almost no one does; that would have been instant deletion "right there!", as the previous poster puts it! smiley for :lol:

I'm sorry for asking, but I didn't come up with a solution on my own, so I was hoping to get a little help (I read your comment disclamer).
<- !!!

I have this code:

RewriteRule ^(.*)/$ ?$1 [NC,L]

RewriteCond %{REQUEST_URI} portfolio/(.*)/?
RewriteRule ^portfolio/(.*)/? ?portfolio=%1 [NC,L]

Aha! No [pre] tags! So what you meant was "I noticed that you had a comment disclaimer, and skipped over it." That's definitely not the same thing! But I'm committed now. Well, up to this point. smiley for :lol:

So everything after and between slashes (/(.*)/) will become ?$1,
and if there is something after portfolio it will become portfolio=%1.

What I don't understand is:
- how can I make the second / optional ( <- this one) so that if I ommit it it will still point to ?$1 and not give me a 404 (or maybe redirect to the url with / at the end)

Put a "?" after any character to make it optional.

i added this now

RewriteCond %{REQUEST_URI} !images/*
RewriteCond %{REQUEST_URI} !inc/*
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$$1/ [L,R=301]

so now everything exept files in those folders go redirected to the domain with the trailing slash.. is this a good way to do it?

No. Requests for /foo/ will, all by themselves, end up in /foo/. There is no need to include mod_rewrite in the process.

And... Again with the asterisks! wtf! Learn what they are for, and use them for that, nothing else! I'm bored with this post now. ;o)

(- how can I do the same for portfolio? why wasn't /? working? shouldn't it make the slash optional?)

- new question: why isn't portfolio/something/ pointing to portfolio=something but to portfolio/something ?

Thanks for all the help you are willing to offer :p and for writing this article, there rules became clearer now.

Kind regards,

Boris Vujicic - 16.04.09 1:17 pm

Really good text.
It is fluid and detailed, covering all the options.
Good Job man.
Really good job.

PS: i hope you dont mind but i am saving this, just in case this gets off the internet.

I don't mind, per se, but I would very much prefer if you didn't, because; 1) This page WILL still be here in 20-oatcake, and 2) I like it when you come back to visit! Actually, a better reason is that I do sometimes update this page, and your copy would then be out of date. See? ;o)

Adam - 24.04.09 8:47 pm

Great article and I've printed it for a closer reading later, but for now I haven't been able to find a solution from the sections I have read. Yes, I know, and I promise to read it all, but my problem has been one for two weeks now without any success.

I tried a couple of variations of the code you have shown here, with zero success so far. I have three needs that need to be met for my current site design:*)$ =>$1 [NC,L]

^www\.domain\.com/(.*)$ =>$1 [NC,L]

^([A-Za-z0-9-]+)\.domain\.com/$ =>
$$1 [NC,L]

^([A-Za-z0-9-]+)\.domain\.com/^([A-Za-z0-9-]+)/$ =>
$$1&VAR2=$2 [NC,L]

Those are the only four cases that I current have to worry about, but the fact that a sub-domain is a variable has been a major problem for me.

Also, is there a method to make any sub-domain, other than WWW and the NON-WWW, be automatically handled without the need to add another domain record? I have seen ^([A-Za-z0-9-]+)\.domain\.com/$ =>$1/ solutions, but none that keep the "fake" sub-domain. If I have to, I'll gladly add the individual sub-domain records, but the first four rules a must for the current design to work. smiley for :erm:

Thanks in advance for any help you can provide, even if it is already above, and I just missed it, or you know where I can read about a similar solution. Thank you. smiley for :D

That's not mod_rewrite code. As for your infinite sub-domains, Google: Wildcard Subdomains It's a DNS thing. ;o)

hankwatson - 25.04.09 7:05 pm

handy tutorial! Thank you!

seattle drupal user - 30.04.09 12:06 am

I was working on my htaccess redirect for an hour trying to get the regex right. And the answer was here all along!

Thanks so much for putting this page together. Now all my coworkers think I'm really S-M-R-T


Zach - 03.05.09 8:49 pm

Okay, so, I checked many different pages for a simple rewrite rule to lose the www and after trying like four that didn't work I finally found yours. Thanks!

Dha12oks - 05.05.09 7:56 am

Omg, i just have to say you saved my life! because i was looking around for a $_GET .htaccess that would obviously read w/e i would put in the link and now it works! smiley for :)

Thanks mate really, really appreciated

Panchu - 07.05.09 10:28 am

I have to convert all uppercase letters in the URL to lowercase automatically with .htaccess. For eg:- if a user types to automatically wit a 301 redirect, is it possible with .htaccess? If yes please help me how to do that...
Thanks in advance

I can't think of any elegant way to alter the case of a request with .htaccess. A better approach might be to use .htaccess to send ALL requests to a server-side handler (e.g. php) where they could have their case interrogated and altered, as well as 301 redirected, or whatever else you need. ;o)

Yatko - 12.05.09 11:24 pm

URL based language selection

Hi, and thanks for the above!

I have a site, and two domains pointing to it (both domains pointing to /home/public_html/ folder). What I am trying to achieve is language selection using .htaccess

The language selection works like this:
if the URL ends with /index.php?lang=ro or ⟨=ro -the site will use RO translation
if the URL ends with /index.php?lang=en or ⟨=en -the site will use EN(defa) translation

I am trying to redirect all requests that come both from and to

I managed to redirect to (without www), but I am stuck here. I am unable to redirect to and cannot add additional rule in case of a visit without www ( I am sure, my rule is OK, just not the right rule I should use in this case :(
RewriteCond %{HTTP_HOST} ^www\.domain\.ro$ [NC]
RewriteRule ^(.*)$$1 [R=301,L]

I started to experiment with the above, ...server error smiley for :)
#two domains served from one root..
RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^/one
RewriteRule ^(.*)$ one/$1 [L]

RewriteCond %{HTTP_HOST}
RewriteCond %{REQUEST_URI} !^two
RewriteRule ^(.*)$ two/$1 [L]

Please write an email if you can help. Thank you!

As you already have two different versions of your site; one for each language; all you need is the domain redirection. I do not see the point of adding all this extra stuff onto the end of the URI. Once the user is in the correct folder for the Russian domain, they get they Russian language site. What need is there of _GET Parameters? Keep it simple. ;o)

PH-MJS - 15.05.09 3:03 pm

Very easy explanationsmiley for :eek:

datta - 15.05.09 7:50 pm

I Have rewrite condition
RewriteCond %{THE_REQUEST} ^(.*)cid=1239374326385(.*)$ [NC]
RewriteCond %{THE_REQUEST} !^(.*)flash=noflash(.*)$ [NC]
RewriteCond %{THE_REQUEST} !^(.*)&s=(.*)$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/mobile? [R=301,L]
RewriteRule ^mobile([/])?$ /servlet/ContentServer?pagename=XM/Page&c=FlexContent&cid=1239374326385

Also I have a mobile folder in docroot /local/apache/docs/mobile
When I try to access it goes into a loop and returns a Page load Error
"Firefox has detected that the server is redirecting the request for this address in a way that will never complete."

How would I make apache mod_rewrite differentiate between a folder and
url and make them available based on condition if index.html does not exist in the mobile folder use the URL /servlet/ContentServer?pagename=XM/Page&c=FlexContent&cid=1239374326385 to redirect.


One step at a time, dude! Firstly, what is the point of capturing variables you don't intend to use? In other words, why "(.*)", when ".*" will do just fine. And why specify "^(.*)foobar", when "foobar" does exactly the same thing?

First you need to fix all that stuff - every single line suffers from these errors; ([/])? ?? Once you do that, the whole thing will be much simpler to understand, and fix.

Checking for a file's existence is trivial ({REQUEST_FILENAME}), but does produce some overhead. If the rewrite is in a place where it will be processed on every request, do consider an alternative approach. ;o)

NixGeek - 23.05.09 7:19 pm

Hi. It's a very good article, definitely worth bookmarking, but a couple things I would like to point out from experience.

First off, a high traffic website (and I mean HIGH traffic, as in 30K uniques/1M pageviews per day) is gonna seriously suffer with a large .htaccess (trust me on this, Ive seen it, experienced it, dealt with server constantly crashing under the heavy strain of processing the big file - someone was trying to block a geographic region using rewrite rules, 15,000 lines or so of rules... ouch!!! We removed the .htaccess rules and designed a shell script that created iptables firewall rules instead, to solve that issue. ) So, I would like to point out to please, be careful with the language where you state "Fortunately, mod_rewite can parse enormous lists of ban-lines in milliseconds, so feel free to be as specific and comprehensive as required." - It can, up to a point, but then it becomes a liability. - Most users may never see an issue, but it's something to keep in mind if you notice your website seems very slow and server seems to be heavily loaded... in which case renaming your .htaccess , if that is the cause, would show an almost instant improvement in performance..

Yes, you are right about that. But in my experience, anyone running a site with millions of visitors is going to be well aware of the limitations of .htaccess, and will be configuring on a per-server basis, anyway.

Interestingly, I only added that text a couple of weeks ago after running tests on some fairly massive .htaccess files here at the org, and being quite surprised by just how many rules you can get off with. Of course, I may seriously underestimate just how comprehensive some peple might get! As with all the text here, there will be edits, cheers!

Secondly- You mentioned Inheritance, and I thought "Oh! Great, someone who knows their sh*t, not just another blogger spouting off something they heard somewhere else.." But then I was disappointed. you never mentioned this:

RewriteOptions Inherit (*might* only work for Apache2/Apache2.2 though, I haven't run Apache 1.3 in years)

Saves the trouble of "but I'll need to reinsert the rules for it to work in this sub-folder "

So you could do :

RewriteEngine On
RewriteOptions Inherit
RewriteCond blahblah
RewriteRule blahblah

in a sub folder, and your rules from root folder's .htaccess will still work in the subfolder, unless they then match the new rewrite rules , obviously smiley for :)

You are absolutely correct to assume that THIS is exactly the sort of behaviour someone would want from mod_rewrite. However, fortunately, the behaviour you speak of is already the default, that is to say, it happens anyway, with no effort on our part, in Apache 1 and 2.

The option you are referring to is for something slightly different. Something which in the real world is rarely useful, and its results more often than not; very like RewriteBase; confuse and create more problems than they solve, hence its omission. In all the years this page has existed no one has ever asked me about it, and still hasn't. Good! ;o)

Other than that- Great article, well done rule sets (SO many other places give rewrite rules that might work for them, or just some stuff they read somewhere else and posted it as their own content without ever testing... but the rules cause issues for others, if not completely break outright.. yours are extremely well done, and obviously very well tested)

Henry - 28.05.09 5:15 am

This is a great turorial but I still can't find the solution to my problem.
I have a subdomain like this

And on the server-side, I'd like to point that to

Here's My code
RewriteEngine On

RewriteCond %{HTTP_HOST} ^(www\.)?([a-z]+)\.domain\.com$ [NC]
RewriteRule (.*) /try.php?url=%2

When I try or, it always says "Address Not Found" as if the url is wrong.

What is wrong here? Could you please help me? I really appreciate it.


This is a DNS issue. Check that you have enabled this subdomain in your hosting control panel (or else enabled wildcard ("*") subdomains) ;o) Cor

nEeNa-JoSE - 01.06.09 10:25 am

if i want to rewrite permalink

profil/?fullname=NoName&user=112233 (in

what codes should i put in my .htaccess??

thanks in advance for ur help
i'm little bit confuse

Just try something! It's not so hard. If you have any issues, post the code here. ;o) Cor

m4niac - 07.06.09 2:18 pm

i'm sure there is a problem in the code: in controller.class.php at this instruction
some code..
$this->$model =& new $model;

now, i've checked everything and im 100% sure that it's just like you said, everything works except this...
if i put an echo just after this line it will not be shown!
if i put it before, it shows...

i've tried
some code..
$this->_model =& new $model;

but the same thing happened...

finally i've commented this line and it echos what is next BUT i get this error:

some code..
Notice: Undefined property: ItemsController::$Item in /var/www/mvc1/application/controllers/itemscontroller.php on line 14 Fatal error: Call to a member function selectAll() on a non-object in /var/www/mvc1/application/controllers/itemscontroller.php on line 14

which makes perfect sense to me... so.. didn't you miss something?

smiley for :eek: Yeah! You missed the fact that you are on the wrong page! Dude, the wrong SITE! ;o) Cor

Manish - 20.06.09 11:45 am

My Problem is

1) the url in the browser does not redirect to the new url (though when i enter the new url myself , it works fine)
2) Do i need to change the links in the entire site for a particular url if i need to go for a url rewriting.

Help required .

1) Missing flag there is, big R somewhere (any way to the url , fine)

2) Perhaps, but in one line always such edits are, oh yes! And failing that, regexp. ;o) Cor

Sanjay - 22.06.09 3:01 pm

This is a nice tutorial abt the htaccess.I got the information from scratch to the high level

Chris - 26.06.09 9:39 pm

I was running into trouble with the hot-link prevention code... without an additional rewrite condition specifying RewriteCond %{REQUEST_URI} !hotlink.png won't it send the requester into an endless loop and never actually display the hotlink.png? or did I make a mistake?

Good catch, sir! Yeah, I forgot to add that line to the updated code here (I now link to my php auto-hotlink generator, which is .php!). smiley for :eek: Thanks! ;o) Cor

also in regards to Panchu's question about lowercase conversion, it is possible with 26 separate rules to cover each letter, ie A=>a, B=>b etc... (and another rule to start over again to look for additional capitalized letters as each rule only does the first capitalized instance of that letter) The 26 rule method is really slow and inefficient, its much better to use a rewrite map in httpd.conf, if you can... just Google "htaccess wheel of fortune" to find more details on 26 rule. The wheel of fortune makes it easier to find as the particular posting I'm thinking of showing the code has a reply showing the alphabet rearranged by most commonly used, helpful for wheel of fortune/hangman games..smiley for :geek:

Thanks again Corz for the great reference!

You're welcome! ;o) Cor

makeitup - 28.06.09 9:17 pm

On my site I put all my contents in a subfolder . So when I want to access my webpage I would type in There are other pages such as contactme.html, info.html, etc. The images and css are stored in /subfolder/css and /subfolder/images/

I made a rewriterule to hide the subfolder with the following:
DirectoryIndex index.html
RewriteRule ^(index|contactme|info)\.html$ /subfolder/html/$1.html [NC,L]

So instead of having to type in each html page name, I tried the following:
RewriteRule ^(.+)\.html$ /subfolder/html/$1.html [NC,L]

This gives me a internal 500 error.

Is there a reason the second rewriterule doesn't work?

Also since i'm using relative paths for images and css files, they are broken when i use the rewrite rule. In the html files they are accessed as "../images/image.jpg" or "../css/file.css". Ive tried a rewrite rule like:
RewriteRule /images/(.*)/(.*)\.(jpg|gif)$ /subfolder/images/$1/$2.$3 [NC] , but its still not finding the images.

Does rewriterule only work based on the url on the address bar?


mod_rewrite works with requests.

I see no reason why you would get a 500 error. Some other .htaccess content (that you didn't post) must be doing that (missing line break at the end of the file, perhaps).

Your big problem here, is basic design. All these extraneous subfolders are always gonna cause more headaches than anything else. If you put something in a subfolder, there really needs to be a reason for it. ;o) Cor

pp - 30.06.09 11:43 am

Hello.. I`m trying to have two condition in my htaccess.. one for hotlink protection and another one is to bypass the hotlink.. here is my htaccess looks like

RewriteEngine on 
#Block Hotlink
RewriteCond %{HTTP_REFERER} !^*$      [NC]
RewriteCond %{HTTP_REFERER} !^$      [NC]
RewriteCond %{HTTP_REFERER} !^*$      [NC]
RewriteCond %{HTTP_REFERER} !^$      [NC]
RewriteRule .*\.(jpg|jpeg|gif|png|bmp|php|html|mp3|mid|rm|ram)$ - [F,NC]

#Bypass HOTLINK for Iphone 
RewriteCond ${HTTP_USER_AGENT} iPhone
RewriteRule ^.*$ -

For the iphone it's not bypassing the HOTlink.. would you please tell me where exactly i`m doing wrong..


Re: PP - 02.07.09 6:38 pm

First off, your question does not make sense. Hotlinking is preventing another site from using your images as their own, so you don't need a bypass for your iphone unless you were somehow hosting a website from it!

as for your hotlink code, it's unnecessarily complicated - you could easily condense your 4 HTTP_REFERER conditions using the style in Corz's example

also ${HTTP_USER_AGENT} should be %{HTTP_USER_AGENT}, and you could have combined the 2 rules by adding !phone condition to the hotlink, like this:

RewriteEngine on
#Block Hotlink
RewriteCond %{HTTP_REFERER} !^http://(www.)? [NC]
RewriteCond %{HTTP_USER_AGENT} !iPhone
RewriteRule .*\.(jpg|jpeg|gif|png|bmp|php|html|mp3|mid|rm|ram)$ - [F,NC]

but all that would do is prevent a site from using your images when viewed from any browser except an iphone, and with iphone your images would suddenly appear on their site (if iphone were even the correct user agent name, more likely it shows up as Safari)

FYI its a wasted effort to block filetypes you don't actually use on your site, so unless you actually host .bmp, .mid or .rm files, no point in including them. Also html|php are unnecessary, and might actually interfere with anyone linking to your site, which could drive visitors away...

Ronny - 05.07.09 5:06 pm

What rule do I need to use if I want to access all kinds of rewrites in a PHP script to do all the work for me?

Simply send everything to your php handler with "." or "(.*)". And use the [QSA] flag, to ensure all variables are intact. ;o) Cor

momosa - 09.07.09 9:21 pm

hi corz, meet again

i have a question about redirecting index.php to to root folder

see this:
people can access my site from:

and i want from those url above should be redirect to (without index.php)

i've been already done to remove www from domain with your htaccess trick (thanks very much)

and now i want to ask u what is the best htaccess expression to remove(redirect 301) index.php while user access my site from and should be redirect permanently (301) to

once again, mmm,, sometime i'm develop my site in localhost, so how should this htaccess method to remove index.php is working too when i'm access my project with http://localhost/mysite/index.php should redirect to http://localhost/mysite/

and there is a possibility to redirect all index.php in other subfolder likes =>

thank for the reply, i really appreciate for your answer smiley for :D

Removing index.php is best handled in php, perhaps in some included init script. I go into more detail earlier in the comments. Something like this..

// redirect initial requests for folder/index.php to folder/ (neater, and better for SEO, too)
// better than using .htaccess (if you have $_POST forms, for example)..
if (substr($_SERVER['REQUEST_URI'], -9) == 'index.php' and empty($_POST)) {
    header('Location: http://'.$_SERVER['HTTP_HOST'].str_replace('index.php', '', $_SERVER['REQUEST_URI']));
;o) Cor

steve circeo - 10.07.09 3:04 am

thanks for the help. dunno if i will have any questions, but i threw a little cash your way, anyway. 'preciate it.

Woah! After so many millions of hits... a donation! w00t! ;o) Cor

zaphod - 14.07.09 7:55 am

there's a lot of really useful information here but i'm going blind trying to read it. more contrast between the text and background colors would make this page infinitely more readable

See here.

thank you for taking the time to post this information

i want to redirect from 'filename.js?var=1' to 'filename.php?var=1'. any thoughts? i tried a variation on one of your examples but it created a server error and took my site offline

any thoughts are appreciated


It's those variations that get you every time! You didn't post code, so no further comment required. Aside from... You are playing with mod_rewrite on your LIVE site?? Are you mental? You must have skipped the part where I recommend strongly that you test test test on a local development mirror. ;o) Cor

Joe - 23.07.09 11:20 am

Thanks for the great insight I to mod rewrite.
Like you say there are to many posts that give rewrite rules without explaining them very simply to people.

They make things complex when half the time they are not its just the description need to be put in to words people can understand that know nothing about mod rewrite and regex.

Regex = regular expression for the people that do not know.

Very intuitive and well done will be saving for another day to read when I have more time and for referencing. smiley for :D

Bentow - 29.07.09 4:13 pm


I have a host in a domain and I've pointed the www and forum to my host.

I have the following folder structure:

--- www
--- forum

I wanted that when the user types: he gets redirected to the www folder, and when the URL is he goes to the forum folder.

I tryed the following way

Rewriteengine on
%{REQUEST_URI} !^/www
^(.*)$ www/$[L]

RewriteCond %{HTTP_HOST}
%{REQUEST_URI} !^forum
^(.*)$ forum/$[L]

When I remove the second block of rewrites, it rewrites correctly to the www folder, but when I add the forum section it doesn't work anymore.

I followed the multiple domains tip.

Could you please help me?


For starters, you need to specify the domain name in the RewriteCond! Also, try and keep sets of rules like this consistent, makes it easier to track down errors. ;o) Cor

Delirious - 02.08.09 10:06 pm

I'm having a bit of difficulty with a rewrite rule:
The Aim: To have users/index.php?un=username to display as users/username

The Current Code:
Options +FollowSymLinks
RewriteEngine On
RewriteBase "/users//"
RewriteRule ^.*$ index.php?un=$1

There are at least three reasons why I won't be responding to this. Answers on a postcard! ;o) Cor

Javacode - 02.08.09 11:31 pm

Hi, I am having such a hard time with a themes on my website someone made me where the creator must have made a mistake in making it. Every time someone trys to navigate the site I get logs of 404 Errors for spacer.gif I was wondering if you could help me to point all request for spacer.gif to 1 file instead of having to put one in each and every folder on the website (200+)

This is webmastering 101, mate! And absolutely nothing to do with .htaccess or mod_rewrite, not even close! smiley for :lol:   I'm here anyway, so..

LOOK AT THE SOURCE! Better yet, run a regexp search and replace over the entire site, switching in the valid link. Better yet, get rid of that daft old-school spacer altogether! ;o) Cor

arpit - 20.08.09 9:47 am

i really liked d clearness in your description
its a fine blog

naganata - 21.08.09 10:22 pm

Excellent blog. I now have ReWrites making the site look much more professional. Many thanks!!

Referring to this article, and the hundreds of hours of work involved in it, as a "blog", will not get you into my Christmas list! ;o) Cor

Michael Griffin - 22.08.09 2:33 am

Ok, so I think that I have perused your article and the comments enough to find that this particular situation has not been brought up. Of course I could be mistaken, but I hope not. I want a relatively secure system for protecting a number of files in a directory. I had hoped to deny all access to the directory using an .htaccess file with the
deny from all
piece of code. Then I wanted to use php to open up the directory for access for an authenticated user. I say this for two reasons. First is that I want to prevent direct linking to the file with a .htaccess as it is the most simplistic method I have found so far. Second is that I want to use php so that I can provide appealing login logout sessions and the added benefit of storing user and password information in a database. Is this possible? If it is I would be forever grateful (and I would make it clear with my donation befitting my current status of college student). Thank you so much! smiley for :D

Michael Griffin

Oh and I have tried to use php to open the directory but that seems to not work:

$dir = 'downloads';

See this. ;o) Cor

steve - 28.08.09 4:13 pm

very clear site.

Geeta - 10.09.09 7:46 am

I want domain redirection.
I have written a rule as by reading the above contents
RewriteRule   ^(.*)something(.*)$$2 [NC]

This is not working since servers are different or I am not able to figure out what exactly is the problem.
the rule is like something is a word which I am searching in url which may be say or and if that word occurs then redirect to mydomain's display_test.php
Any help regarding this would be appriciated.

Add an "R" to your switches (for an external rewrite, aka, "redirection", as explained in the article), so it's [NC,R] ;o) Cor

Jesmo - 18.09.09 7:44 am

Hello from Denmark

I have this problem with my 301 redirect:

The last part of the url is where the redirect come from.

It show´s an extra url in the redirect - i am trying to avoid duplicant content but the extra url can be searched also. so when i remove 1 risk i just made another ??

Anyone who can help me please .

Best regards smiley for :eek:


The string in my .htacces looks like this:
redirect 301 /tiffany-lamper-32

Try again with mod_rewrite! ;o) Cor

netsnake - 18.09.09 7:56 pm


Wonderful tutorial! I've been looking for something like that for quite a while.
Now I happen to be German, so I couldn't resist translating this page using your nice -de ending like that: but what happened, is that it just got stuck in a loop, I don't know why, but it did. Just try it yourself. You'll see.

I guess you really don't have any non-English readers, or not any more smiley for :D

Great Blog, great site, keep it up!

It's a JavaScript Issue With Firefox 3 (my frames breakout code). I get thousands of hits in my logs every day with it, which is annoying. It's now disabled, until I can get around to a workaround.

make it up ! :D - 19.09.09 10:33 am

Hey, i just a have a quick question.

I have a folder, lets call it FolderAA

So i want to redirect all access of FolderAA to /
This is easy to do ....

the problem is that when i create a folder FolderBBB that will simply redirect to FolderAA.

But since i wrote my redirect there, how can i make it go to FolderAA if it is only access from FolderBBB ?

Any suggestion would be helpful, since i cant seem to get it to work !

This makes my head hurt! You didn't supply enough information to give anything but a silly answer. ;o) Cor

chris - 24.09.09 11:52 am

Hi, i need to add to each called url the parameter

for example. i have:


and it should redirect (so also i see it in the browser url


i tried something like:

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{QUERY_STRING} ctitle=(.*)
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} (.*)
RewriteRule allchats.php %1/?ctitle=%2&ctitle2=Singles [R=301,L]

but that comes in a loop :()

hope you have an idea


THIS is why I ask (quite clearly) that folk post code inside [pre] tags. I basically don't have the time to decipher that to even begin thinking about what issues you want to leech my time to fix. Life is to precious to waste chasing after people who can't even read the article first.

Unless you learn to pay attention to the details, you will not have any success with mod_rewtite. ;o) Cor

jignesh - 26.09.09 10:17 am

I want to make URL like using .htaccess file.

When i have select any city or state then URL make like

Please help me to make URL like this

You need mod_rewrite for this. See that big article above the comments! That will help you. ;o) Cor

Shonn - 28.09.09 3:15 pm

I am taking over hosting and managing an existing site that uses .htm as suffix for SEF urls.

My system (joomla) is using .html

I am using mod_rewrite and was hoping it could convert all .htm suffix and point them .html instead.

Is this possible please with .htaccess file?

I've no idea what SEF is, but the very first example on this page (repeated later, with details) sound like what you are after, switching out the different extension, of course. ;o) Cor

francesco - 09.10.09 2:17 pm

Hi there,
Great article!!!
thank YOU very very much.
you guide (after apache one) is the best over the net!

I just have some more problem now about more than one attribute managment..

If you had the time it would be great to had an example about transform more than one attribute to a complete seo-friendly path


thank you again! You really help me!

There is an example of this in the article! ;o) Cor

Jim Jackson - 16.10.09 12:11 am

I've really been struggling with RewriteRules and all the other on-line documentation wasn't making it any easier.

Your info was by far the best tutorial, it really got me out of a hole.


james - 20.10.09 11:53 pm

I've been searching for something that would explain what exactly can .htaccess do and I'm telling you ... this post is the most comprehensive resource I could find.

Rahul - 26.10.09 10:52 am

This tutorial about .htaccess is really gr8.

Mom Bunheng - 28.10.09 2:54 pm


I have create fake url like this by using .htaccess rewriterule as below

#mod_rewrite in use
Options +FollowSymlinks
RewriteEngine On

RewriteRule services/(.*)\.html mainpag.php?page=$1

Only thing giving me problem is all images, css and, javascript request could not find because looking into services/images/, services/css/, services/js/ actually all my images, css and javascript virtually store at (, ( and (mydomain/js/), I would like to know is there any way within .htaccess to solve this problem.

Once again thank you for your contribution in this blog.


Yup. Check previous comments. ;o) Cor

Worried - 29.10.09 8:02 pm

I am wondering if I can use htaccess to block a 301 referral from another website. Here's the situation. Someone registers embarrassing.url and with htaccess redirects this to niceperson.url. Now whistle blower points this out to the world and embarrasses niceperson. As there doesn't seem to be an http_referer record I can't see how to stop this coming in. Any suggestions?

The referer header is a browser (web client) thing. Some don't send it, but most do. Surely there is ONE inward link from this supposedly-evil domain that has referrer information!? Check your logs, find out the domain name, and then contact the the registrar, get something done.

And if there isn't a single inward link with a referer header, then clearly it's no issue at all, because no one is visiting that domain, whatever it is, or else it does not exist. ;o) Cor

CraftyGeek - 03.11.09 6:59 pm

Great easy to understand article - its been a while since I last looked at using htaccess....the last time it was a tad scary - this is a whole lot more approachable & actually makes sense!

Good job & nice writing - shame about the peeps asking basic web questions, but hey, I guess we were all there once.

Thanks, this has been a real time saver smiley for :cool:


Robert - 04.11.09 12:52 am

Thank you for your time and energy that went into making this. You have saved me a tremendous amount of trouble. I just wish I found this post this morning! Great work.

just made up - 04.11.09 3:18 pm

there is an example somewhere... but even that i can't follow...

how to mod_rewrite from /site/index.php?p=picture 1.jpg to /site/picture 1.jpg? or for that matter any filename that ends with jpg or png or bmp or gif? tnx.

Mike - 07.11.09 5:40 pm


Thanks for all the info you posted here.

I'm still struggling with one thing though and it has to do with .htaccess file.

I want my password rules to apply to every file except for my index.php file.

I can not get this to work and have scoured many pages.

Here's what I still prompts for user/pass when you hit the site

AuthType Basic
AuthName "AWAT Restricted Access"
AuthUserFile D:\Web\secure\
require valid-user

<FilesMatch "index.php">
Order deny,allow
Allow from all

I have also tried something similar to this (thinking I would FilesMatch would return true for all files but index.php) but that don't work either:

<FilesMatch "!index.php">
AuthType Basic
AuthName "AWAT Restricted Access"
AuthUserFile D:\Web\secure\
require valid-user

This seems like it should be trivial but its turning out to be a major pain.

Any help is greatly appreciated.



josh - 09.11.09 1:11 am

Hi, I just came across your site when trying to learn basic URL rewriting. I just want to use a simple URL to point to a complicated RSS feed address. Here is the command I used

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^g2albumrss$ gallery2/main.php?g2_view=rss.Render&g2_name=New+Albums

The result I want is that

gets mapped to

Should this work as I have written it, or am I doing something wrong. My hosting company says any changes to .htaccess should be visible immediately. Thanks for any help you might be able to give.


Andrew B. - 17.11.09 2:23 am

Thanks for the good info on htaccess. Even though it's still arcane to me, you've put made it much less so!

Now, is it possible with just htaccess to do redirection, but retain the originally entered URL in the user's browser window?

thomas crown - 19.11.09 7:46 pm

hey the link has been updated to please change it. Thanks for providing this tutorial it has really helped me out

Greg - 20.11.09 2:59 am


This is a great site,and I have a couple questions that I was wondering if you or someone more knowledgeable that I could answer. Let me explain my setup. I have 2 domains called and I have Joomla installed in different folders on and want all traffic to go to there.

This is what I want to do:
1. Anyone going to will be re-directed to I have accomplished this part, but I want the URL in the browser to only show "" with no folders listed. I have problems with this part.

2. Anyone going to will be re-directed to while only showing "" in the browsers URL, again, no folders shown. I have a feeling that if I can get the answer to the first question, it would solve this problem as well.

Is this possible using .htaccess? And if so, I would appreciate anything that can help me accomplish this goal.

Thank you,

Boris Vujicic - 24.11.09 12:28 pm

Ok smiley for :)

The Hotest Girl in my Space :) - 24.11.09 3:56 pm

Thanks a lot! I have really modified my htaccess now!

A caveat though, you say that you have another version of debug_report.php in the archive. I didn't find it *humpf*

So I downloaded the one shown on your eminent page 2.

I guess that's the one I should use?

would appreciate if you e-mailed me

Thanks for a great site!smiley for :ken:

Alex - 30.11.09 11:17 am

Hi i have a problem with mod rewrite

(it work)
RewriteRule ^music/( <^/>+)$ music.php?artist=$1

(don't work)
RewriteRule ^( <^/>+)$ music.php?artist=$1

pls help me smiley for :ehh:

Chris - 30.11.09 5:21 pm


RewriteRule ^([^\/]+)\/?$ music.php?artist=$1

Should allow both:

To go where you want...

Sam - 02.12.09 6:32 pm

Hi there,

I am trying to remove the www from the URL. I am developing my app in Codeigniter and the code above doesn’t help me :( Do you guys have any idea how to get the Codeigniter working with it?

RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/index.php/$1 [R=301,NC,L]

The url should work as but it dosen't like it :(

My working code to achive the above url format in Codeigniter for both with www prefix and without it is

    RewriteCond $1 !^(index\.php|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]

Any you guys know how to get raid of the www and keep the Codeigniter happy?


NiAlMa - 03.12.09 5:38 am

i have a .htaccess with the following rules

RewriteEngine on
RewriteRule ^(.+)\/$ index.php?show_page=$1
RewriteRule ^([^/.]+)/?$ index.php?show_page=$1 [L]
RewriteRule ^([^/.]+)/([^/.]+)/?$ index.php?show_page=$1&extra=$2 [L]
RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)/?$ index.php?show_page=$1&extra=$2&extra_2=$3 [L]
ErrorDocument 404 /404/

/404/404 is created but when i click an link that should be display my 404-page i get the normal 404-page from the server....

Could anyone tell me what the misstake is?

I can grant a demotestversion for testing.

Greetings from Germany

esjabe - 05.12.09 4:39 am

First off... outstanding.

Secondly, I have a question regarding HTTPS rewrites and I did not see anything in the article mentioning this.

I have SSL set up on the root domain , and a subdomain setup in a folder on the root. I would like to rewrite the HTTPS requests to not include the domain. In other words, I want the main domain transparent to the user so they are not confused when the domain shows up all of a sudden when the go to check out.

http://subdomain/unsecure_foo.php (this is good)


Is this possible? I ask because I would like to use a single SSL cert to secure several subdomains.

Thanks again for sharing your expertise...

stefan - 05.12.09 3:00 pm

This article is
, BUT...

1. I still dont know what ! means
2. and how to get $_POST variables while the page is redirected

thanks a lot for this article

SINTAX - 05.12.09 3:14 pm

First off, great article. I have read through it a couple times and am using a few of your examples in my current .htaccess file. I am having one problem that I can't seem to figure out. It is in regards to the rewriting with variables deal.

What I'm trying to accomplish:$login

... and rewrite it to:$login

(much like you find on sites like Twitter where your username appears to be a directory.

My current RewriteRule looks like this:
RewriteRule ^(.*) view.php?login=$1 [NC]

... but it's not doing the trick.

Thanks for any assistance you can send my way.

muppetman - 06.12.09 7:11 am

Hi, I just wanted to say out of all the sites I've been to trying to figure out this code this is by far the BEST. You make it so even I can understand it (

I've purchased a SSL and am currently trying to make site so that only certain pages are secure. I'm having great difficulty figuring this out but after reading through your site I think I may be able to figure it out. Hope I haven't jinxed myself.

Thanks again!

George - 07.12.09 3:11 pm

I need to be able to make a folder access case insensitive.



I want is accessible from the following urls


Please advise.

hussain - 10.12.09 9:50 am

Hi i need a little bit of help. my requirement is to fix the page name with extension and variable name and the www because i want to make my URL more short
like below url

NEW URL (Required):

Please guide me,

ILikeToWhoop - 20.12.09 12:40 am

Awesome ... Awesome ...

jordan - 20.12.09 3:32 am


i have a problem with .htaccess for main directory


RewriteRule ^list/([^/]*)$ details.php?type=video&pname=$1 [L] 

in url show as
but how do i remove list(1st directory) like without (list) ?

this will work but will affect all other page
 RewriteRule ^([^/]*)$ details.php?type=video&pname=$1 [L] 

please advise,

thanks man

JD - 21.12.09 6:46 pm

Thanks for all your work on this site. It's been very helpful to me. I'm wondering if the following is possible using htaccess.

I'd like to send users to different webpages after they click one link based on their credentials. In other words,

User 1, clicks link "a" and goes to User 1 photo page.
User 2, clicks link "a" and goes to User 2 photo page.
User 3, clicks link "a" and goes to User 3 photo page.

Is this even possible. If it is, would you be able to point me in the right direction?


some webmaster - 22.12.09 10:58 pm

I have been trying to make a redirector that drops log entries on my server for outbound links.

The ideal format would be

should redirect to

while at the same time leaving a log entry on my access logs showing the 301 redirect.

I would also like this redirection to work for https:// urls.

So far, the best I have come up with this:

RewriteCond %{REQUEST_URI} ^/link
RewriteCond %{QUERY_STRING} !^$
RewriteRule .* http://%{QUERY_STRING}? [R=301,L]

That will redirect, for example to

This is sub-optimal because:
1) I can't pass query strings in the links
2) It has the "http://" hard coded and therefore won't work with https:// links.

Does anyone have any suggestions?

danilo - 23.12.09 4:25 pm

Hello, I'm making a server-side rewrite that reads foo=1 when user puts, thats my code:
Rewriterule ^category/ /?foo=1 [L]

rewrite mod works, its simple
But if exists a file called category.php, then rewrite mod doesn't work

I tried do this:
RewriteCond %{REQUEST_FILENAME} !-f
Rewriterule ^category/ /?foo=1 [L]

and this:
Rewriterule ^category/$ /?foo=1 [L]

and also I tried this:
Rewriterule ^category([^\.php])/$ /?foo=1 [L]

But doesn't work. I need help smiley for :erm: Is possible this rewrite?? or i have to delete category.php file?

Ajay - 25.12.09 1:42 am

Hi, very nice examples easy to understand most of it. But still I couldn't achieve what i was trying to do with one of my project.

i have a dynamic url Guit

and want to display as

Can you please help me with this. I tried all i could find but still not able to get it.

thanks a lot for the article with self explanatory examples.

Casemon - 28.12.09 1:49 pm

Awesome page. Really does help break down mod_rewrite, and with clear and easy to understand examples.

Have a current issue, that might be inline with your examples.

Basically have a database driven site & have added a database driven forum. The site appears in the root, and the forum is hosted out of a child directory of root. Nav links on the site have the forum in 5th position (5th link from home), and a blog is in 2nd position.

Everything is working, save for 1 thing; the "current_page" markup is showing all the forum pages as being part of the blog. Basically the forum offers up 2nd order pages (from the forum subdir) and the navlinks are interpreting this as being from the blog.

Does that make sense? I really have no clue as to how to resolve this. Thought it might be a common mod_rewrite issue, given many people integrate forums into their sites, but haven't found any useful info on the matter.

Any ideas? Would it be worth addition to your already stellar mod_write...

Thanks in any case smiley for :)

email - 06.01.10 5:59 pm

This code works on my local server xampp php5+ but does not work on remote server (1and1) php4+.

Would like to rewrite

Options +FollowSymLinks

<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{REQUEST_FILENAME} -f [OR]
	RewriteCond %{REQUEST_FILENAME} -d
	RewriteRule ^(.+) - [PT,L]
	RewriteRule ^(.*)$ index.php?/$1 [QSA,L]

Thanks just something to work on if you have time.
Thanks Email

email - 06.01.10 8:45 pm

Thanks to anyone who started to help but
I found the answer. For those who love(me) or hate 1and1 all that was needed was a little time digging around the net (.75 hours) and experimentation.

Fix: 'AddType x-mapp-php5 .php' and 'RewriteBase /subdir' to .htaccess in subdirectory

AddType x-mapp-php5 .php
Options +FollowSymLinks

<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteBase /subdir
	RewriteCond %{REQUEST_FILENAME} -f [OR]
	RewriteCond %{REQUEST_FILENAME} -d
	RewriteRule ^(.+) - [PT,L]
	RewriteRule ^(.*)$ index.php?/$1 [QSA,L]


George - 09.01.10 8:21 am

Nice page ! I managed to do a few rewrites based on what you have here, however, I'm stuck with 1...
I've changed my old picture-gallery to a new gallery.

Old links:

New site:

The image_id can be ignored as the new site works different with images, but we did manage to use the same category/album numbers. On the old site this was the "cat_id", on the new site it's "aid".

So it's the part where I put "750" that's important. Also, the new site works with 4 chars, so there needs to be an extra "0" for the aid..

I hope it's not asking too much... :P
In advance, thank you very very much !

Stevens - 13.01.10 2:34 am


I am facing a problem... I would like to send an HTML with my domain name "in the link", but while clicking the link I want it to be redirected to another website.... --------------- Click ------------ "another website"

Is there anybody can help, it will be really appreciated...

fairuz - 13.01.10 3:15 am

i like to change my MLM script into simple referral url.

for example, instead of

can somebody help me with the complete code??

i u know, please email to

thanks in advance..

Martin - 15.01.10 8:14 pm

After days of seeking a good htaccess tutorial I found your page.
In a few hours I read and test a few scripts on my server.

Thank you very much!!
I will read more of your great written tech!


jesse - 20.01.10 7:40 am

Hello, thanks for the tut. I refer to this page often.

I am having a problem with a recent .htaccess that I would appreciate some help with. I have read the page several times, as well as other pages.

Here is what I am trying to do. 1 page on this site is secure for example

but all other pages are not supposed to be secure. for example should re-direct to http://..../purchase.

I have tried many variations, but this is the one I think should work and does not.

# only for https pages.
RewriteCond %{HTTPS} =on

# only for pages that do not end in pay-cc
RewriteCond %{REQUEST_URL} !pay-cc$

# re-write the url to a not https
RewriteRule ^(.*)$ http:\/\/\/$1 [R=301,L]

The result of this is all request are re-written to http version of the url.

My understanding was that if a request like /purchase/view does not match pay-cc$ the re-write would stop evaluating and no re-write would happen.

Thanks in advance

Brian - 27.01.10 6:17 am

I did two htaccess 301 redirects, both sucessful, both pointing to one domain. The problem is with my Joomla site. The second redirect was from the index.php to keep everything on .com for SEO reasons. The moment I messed with php, I was not able to use the plugin's on my Joomla site such as "client login" or send an email directly from the site. Yes, removing the second redirect fixed all.

I was able to add a line to use the administration when the php redirect was up, but when I tried others to access my plugins, they did not work.

Question? Does anyone know a htaccess code that enables these plugins while at the same time using the 301 php redirect?


madeupname - 27.01.10 6:35 am

The best I have seen for htaccess tutorial. Kudos!

My only negative comment probably has to do more with regex, and my lack of understanding. But it is hard to decipher not knowing where the regex starts and where the htaccess syntax ends. You delved into it somewhat, but it would really help for some of the examples to be broken down char by char. ie

{HTTP_REFERRER} = php variable for anonymous requests from another domain.. or whatever it actually means.

(.*) = idk?

I guess what I'm saying is a step through of the syntax, not necessarily a regex tutorial.
I'm still not sure what the ^ does exactly.

As I say it is still very good information for getting my head wrapped around htaccess. Thanks for your time and effort.smiley for :cool:

TAJ - 27.01.10 6:46 am

Trying to figure out some rewrite rules to add short URLs on my domain. However everything I do is unsuccessful -- either the new code is not working or I have redirection issues.

The existing code in my htaccess file (
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^trans-americas\.com
RewriteRule ^(.*)$$1 [R=301,L] 
Redirect 301 /wordpress
AddType x-mapp-php5 .php 

The code that is supposed to be added for
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^[a-zA-Z0-9]{4}$ supr.php?supr=$0
RewriteRule ^supr_settings.json$ supr.php?check_install=$0

No matter where I place this code it won't work.
Any help would be appreciated.


Uday Chatterjee - 04.02.10 6:03 pm

Hi all,
How do i redirect my site to a folder with .htaccess(i.e. if i type it is redirect to Plez Help.Its urgent.

Eva - 11.02.10 4:09 am

my site is <> can't use rewrite from php to html

I use .htaccess this below rule.

Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*)\.html $1.php

It's still error 500

Please, suggestion to me.

Thank you.

Sam - 12.02.10 11:54 am

Just to say that this is a very informative and easy to follow tutorial- thank you!

RMWChaos - 16.02.10 11:13 pm

Excellent work here, Cor! I think I've dnld'd most of your code now. smiley for :evil: Seriously tempted to press that "donate" button, too, which NEVER happens. I blame the economy.

One comment, and it's more of a philosophical choice, I suppose - passive-aggressive vs. just plain ol' passive...

When using redirects on 400/401/403 errors some prefer to to respond with some snotty message like "can't hack this, da-na-na-nah" etc. However, doing such passive-aggressive things tends to egg on those who are out to cause havoc and chaos.

So why not just (passively) redirect back to the main index page without any fuss like with 404 errors?? Hopefully, they just get bored and move on.

As my dear ol' Da used to say (still does, actually), "Don't get in a pissin' match with a skunk." Good advice. Will Smith says it better, "Don't start nuttin', won't be nuttin'."

As for your Auto Hotlink code ... sooooo loooove it!!!! This is one case where I'm more than willing to leverage off the bad behavior of others for my own benefit. It's all good ... or bad ... whatever. smiley for :evil:

Just my two-point-five cents.



Gabe - 24.02.10 7:19 am

Awesome htaccess tutorial page smiley for :D!!!
Thank you so much for sharing your tips (and twicks)!!!
Bookmarked your page smiley for ;)!

binu - 04.03.10 6:15 am

i have a website url like this

I want to rewrite above url as follows, Please help me

RewriteRule ^packages/ packages.php
RewriteRule ^/packages/(.*) package_list.php?pid=$1

first rule is working .

YW - 09.03.10 1:55 pm

I have a domain that I want to redirect to another site that I own.

I want people to go to:


and redirect it to:


CK - 09.03.10 11:14 pm

my website is facing script injection attack for a month which comes at the end of head my site hosted in linux..created with simple html..If I change the .htaccess file will it do?

CK - 09.03.10 11:18 pm

script injected just after the end of head tag or after the completion of html tag(at the end of the page)..what precisely can I do to stop this?

Ayo - 17.03.10 3:35 pm

Thanks, very helpful

gvs - 22.03.10 9:50 am

sdvsfb gf

Lau - 25.03.10 5:22 am

Excellent article ... the best I've found on htaccess ... well done ... much appreciated.


prashant - 27.03.10 11:33 am

this link is not working and it still present. please update it to recent version

thank you.

Syphon - 05.04.10 7:31 am


Works for me!

Nick - 07.04.10 3:43 pm

I've been at this for two days now. At one time we had it set up where we could type in fog and it would be redirected to This is no longer working for us. Any ideas/suggestions would be greatly appreciated. I've tried everything except for what works.

Bruce - 10.04.10 2:53 am

Hey Cor you saved my ass man (and probably my job too).

My specific problem was interfacing ExtJS to CodeIgniter.

The ExtJS client code wants to send URLs with parameters as query strings but the CodeIgniter MVC on the server side expects them as search friendly URL parameters or as CI call them "segmented URLS". As an option you can enable query strings within CI but you lose some of the functionality in the helper classes that rely on URL parameters. I really didn't want to have to resort to query strings.

There are so many tutorials out there on how to achieve the reverse; how to input friendly URLs on the client side in say a browser and have mod_rewrite converted the embedded parameters to a query string based URL for the server to consume.

After an hour of searching this is the only tutorial I found that helped with my problem.

Cheers dude!

dr3w - 10.04.10 9:44 am

Great tutorial! indeed very helpful.
thx a lot

CH ASIF MEHMOOD - 14.04.10 2:05 pm

I will be great full if you write the whole story in a simple way so it might be useful for some one.

eric - 14.04.10 11:31 pm

Sweet post, thanks! I've definitely put some of this to use..

Any chance of an example .htaccess that will redirect to when the .htaccess is loaded from but ignore the rewrite rule when the domain that's being loaded is

Tithi - 16.04.10 11:08 am

i have uloaded my website & it includes .htaceess file in it but when i see this on browser then it comes as index of/

i want to see home.php just written the url...
the .htaccess file is uploaded in public_html
help me in

Julien - 16.04.10 2:56 pm

Excellent, best tutorial accessible from 1st page result in google, well done.

Gepar - 22.04.10 10:09 pm

Cor, wonderful work!

I wanted to ask how to get rid of one inner dir, f.e.

to form

How can I get rid of vmchk/ in this case?

Dez - 23.04.10 6:26 pm

Thanks for the help. I used the no www non-hardcoded version to make my dedicated server work correctly with multiple domains.

vivek - 26.04.10 8:06 pm


Ed7991 - 26.04.10 9:09 pm

i dont have a clue where to put my .htaccess file!
my file system is like so
=>files e.t.c

i want to be able to redirect

this is my htaccess so far
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^folder1/( <^/>+) /folder1/index.php?s=$1
RewriteRule ^folder2/( <^/>+) /folder2/index.php?s=$1

but it doesn't work
any help will be appreciated

Jig Patel - 28.04.10 7:58 am


I have url like

and i want to rewrite this url as

is there any one has idea how to do that?

Please help me its very urgent..

ed7991 - 28.04.10 5:03 pm

the way to do this is
call a file index.php (note you must have php enabled and installed)
	header('location: http://'.$_GET['username'].'');

and it works!!

note: replace "" with your domain name

juanune - 02.05.10 3:19 am

There's no reason to do a PHP redirect here. You're better off with an actual rewrite because you can/should mark it is as a 301 request.

That being said, if you're going to do this, you'd better have an A name record set up for the users, which pretty much means running your own dynamic nameserver.

I expect that if you can't figure out how to do the URL rewrite though, that this will be beyond you. If you need it in a hurry, my recommendation would be to call a professional.

kjv1611 - 06.05.10 12:52 pm

Just wanted to drop a thank you for this page - .htaccess 2..

One piece of it helped me more than all the other .htaccess stuff I've read so far. Given that info, I plan on doing more reading across your site to see what else I can learn.

Thanks, and keep up the good work!

TheMuffin - 06.05.10 10:58 pm

You are NOW officially my GOD of the net!!! I thought I could teach myself enough to make things ok..I missed a whole bunch and lost one of the domains on a host with 3, thanks to my crappy addition to the .htaccess file...

THEn by the grace of all things webby... I found you and now all things make sense and work like a charm... I have even managed to have the links in the emailer redirect nicely!! (I had, like a fool, changed some file names,when i flipped the full site to php

Thanks again to you and your very clear article it all is as it should be .. and I no longer seem to be having so many blonde moments!!

You rock...
xoxosmiley for :roll:

Thankful reader - 07.05.10 2:44 pm

What an amazing write-up. I rarely come across well written articles like this one. Thank a lot!

Jan - 10.05.10 12:09 pm

what's the rewriterule for changing



meszoltan - 13.05.10 6:09 pm


I want to send some parameters from image to database, and my idea was this:
Visitors can see images with links on the site, like ''
With apache config file i can redirect request to a php file, with parameters of the image.
After saving parameters to the database, php file is reading the image source, and user can't see anything from this, just a loaded image.

('Content-type: image/jpeg');
$folder urldecode($_GET["folder"]);
$file urldecode($_GET["file"]);
$url "anyfolder/".$folder."/".$file;
$header "filename=image.jpg";

I think my problem is to know, how can i do a condition in apache config file:
just if script filename is NOT '/visit.php', then do next row, something like this:

Options +FollowSymlinks
RewriteEngine on

RewriteCond %{SCRIPT_FILENAME} !^visit.php$
RewriteRule ^( <^/>+)/( <^/>+).jpg /visit.php?folder=$1&file=$2.jpg

Can anyone help to resolve this problem?
Sorry for bad english!

Mark - 23.05.10 11:06 pm

I like the information here , but the site seems very hard to read the code based on the color schemes used for the code. I hope you think about changing this. Some of us are getting old!

I have searched high and low for rewrite rules. I need to do 2 things

I need to load a different favicon if the user comes to rather than or I think I can do this in the .htaccess but can not find out how when it relates to only a specific file. for instance if they go to they will get (transparently to them) othericon.ico, and all the rest will see the normal favicon.ico

Additionally, I want to know if it is possible to redirect a subdomain via the ht access file so that if I go to the server loads

Any help on these is appreciated.

markosjal OVER AT gmail WITH A com

Musta - 01.06.10 9:05 am

First of all thanks a lot for this useful information to get started with the painlful world of htaccess. I have checked high and low for a solution to enable .htaccess files on my Macbook pro but in vain. Apart from the apache that is built in my machaine I have installed a Mamp server to have a local server for testing. Everything works fine but the problems arise when I tried to implement SEO friendly urls by using .htaccess files. When I include this latter in the root of my sites (MAMP/htdocs/Mysite/.htaccess) it does not work and cause the following error.
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log.
Apache/2.0.63 (Unix) PHP/5.3.2 DAV/2 Server at localhost Port 8888

and in my Mamp apache log file I get the following error:
[Tue Jun 01 09:46:40 2010] [alert] [client ::1] /Applications/MAMP/htdocs/Mysite/.htaccess: Invalid command '{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf480', perhaps mis-spelled or defined by a module not included in the server configuration, referer: http://localhost:8888/Mysite/index.php?DepartmentId=2&CategoryId=4&Page=4

These are the errors that I always get even when inserting an empty .htaccess file. I have changed the AllowOverride line from None to All in both the Mamp and the httpd.conf that ships with the machine but in vain. I have also made sure that the following lines: AccessFileName .htaccess andLoadModule rewrite_module modules/ are uncommented but in vain. I just do not know wht is going wrong with my local testing server. I hope that you could help me ride of this nightmare that I have been fighting for more than 5 days.

Any help would be greatly apreciated, And many thanks in advance

Mohamed Ali - 02.06.10 12:53 pm

Many thanks for such info, i have been working on improving my site's seo, and your article helped me allot on improving my site's indexing.

Eamonn - 08.06.10 11:57 pm

thanks man for all the research and for sharing.

The www. to non-www. redirect is excellent


Zahi - 18.06.10 1:07 pm

Author, Expalinex each and every case in the post and very easy to understand and i also found the dubug example by the end of page and hopes it will give lot of new things to me

Thanks admin

shay - 18.06.10 9:33 pm

this work

Arun Gautam - 23.06.10 4:17 pm

RewriteRule  images/(.*)  images.php?url=$1 [NC]

i have this but this does not work for url containing special character
like: images/gallery/thumb/black&white.jpg

i only get: images/gallery/thumb/black in $_GET['url']

please help.

Hungry Mind - 06.07.10 8:53 pm

Awesome Tutorial... Im Sure This Is The Only One Best Tutorial About .htacces, Gr8 Job =)

Hungry Mind - 06.07.10 8:56 pm

@Arun Gautam:

Can U Plz Explain What U Wanna Do Actually?

Do U Wanna Block This Image On Direct Hitting It's URL?

Bobby Ong - 09.07.10 5:32 pm

You saved my life! I've been looking dead hard for this guide.

Thanks a million!

yoyoman - 11.07.10 11:06 am

Thanks man, you are a very smart dude. Saved the day smiley for :D

Paul - 17.07.10 3:10 pm

I have a nail biter. I have solved in part, but are missing 2 out of 3 parts, lol.

I am trying to use Scandinavian characters åäö in the URL but get stuck on that the .htaccess doesn't want to cooperate. I'll explain:

I have a Q&A (frågor och svar) link so I start with:
RewriteEngine on
RewriteBase /[L]

then this is a normal URL rewrite, pretty straight forward, loading index.php?id=10:
RewriteRule ^/?fragor-och-svar/$ index.php?id=10 [L]
No problems. Above rule works perfect.

But what if I prefer "frågor" (that means questions) in my URL before "fragor" (that doesn't mean anything):
RewriteRule ^/?frågor-och-svar/$ index.php?id=10 [L]
lead to a 404 error.

I know that å is translated to %c3%a5 or %C3%A5, so I test:
RewriteRule ^/?fr%c3%a5gor-och-svar/$ index.php?id=10 [L]
RewriteRule ^/?fr\%c3\%a5gor-och-svar/$ index.php?id=10 [L]
RewriteRule ^/?fr%C3%A5gor-och-svar/$ index.php?id=10 [L]
RewriteRule ^/?fr\%C3\%A5gor-och-svar/$ index.php?id=10 [L]
that all lead to a 404 error.

I am curious on what code there really is that å is translated to so I find after some elaboration that it is supposed to be EXACTLY 2 characters, although it comes out as index.php?id=%c3%a5 after using following code to [R]edirect me. Strange...
RewriteRule ^/?fr(.{2})gor-och-svar/$ index.php?id=$1 [R]
Above rule does NOT give me a 404. But it says that 2 characters equals %c3%a5 ???

RewriteRule ^/?fr(.{2})gor-och-svar/$ index.php?id=10 [L]
takes me to the right place! Problem solved! Almost... because I can't let it go! I am curious on what å really is supposed to be. And after looking around on many many pages I find that someone got a messed up code for å in his URL: Ã¥

Now I test it:
RewriteRule ^/?frågor-och-svar/$ index.php?id=10 [L]
It works like a charm!!! If I use Ã¥ for å.
Question is what strange code is this???
If I can figure that out then maybe I can do the same trick with ä and ö.
I think it has something to do with differences between UTF-8 and iso-8859-1.

Grateful for any insights.

Matthew R. Kee - 19.07.10 4:21 am

How can we direct request for to and have show in the browser while using domain alias. is a domain alias of to reduce hosting but it won't change in the browser.

Eric - 20.07.10 10:44 am

Thanks a lot. Really nice work.

chrisw - 20.07.10 12:50 pm

Thanks so much for this excellent page. I've always struggled to understand htaccess and have mostly thrown plausible bits and pieces together by trial and error. But this actually gave me a pretty good understanding, for once, and thanks to your examples I was able to write exactly the htaccess file I wanted within literally a couple of minutes of leaving your page and have it work first time. Excellent job!

vijay sharma - 23.07.10 12:32 pm

but where is the .htaccess file ?????? plz tell me

DarkNight - 27.07.10 12:17 pm

I have one .htaccess file, which i have to use in one of my project.
But I don't know what exactly it has, Can any body explain me what my .htaccess file can do?
my .htaccess file code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php

Thanks in advance,


Jithin - 30.07.10 11:02 am

Nice write-up!!

Tommy - 02.08.10 6:11 pm

Here is my current HTACCESS file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.php [L,QSA]

It is setup to remove function with/without a ".php" extension. What I want to try to emulate is how MVC handles URLs. I just need one more parameter added to the end so if I do:

Where "projects" is actually a page, projects.php, and "add" is a function I can automatically load if my web app finds that it is present. So, the basic problem is, how to add the "/add" to the end of the URL without causing an error and making it possible for my web app to view it.

An additional problem I am having is that if I point the domain name to (With trailing slash), I get a 500 Error.

Any help would be greatly appreciated! Thanks so much.

Rajesh Singh Tomar - 06.08.10 12:30 pm


I want to write the htacess rule like this. . (

For the english string i have write the rule:-

(xyz is utf-8 string . Ex:- this will be in russian languages also)

Please help me how to write the rewrite rule for this.

Thanks in Advance.

Prof.Yeow - 09.08.10 9:16 pm

great guide! smiley for :D
now i can have my profile page and my project in the same server!

flablog - 11.08.10 11:29 am

Hi there
thanks for this useful guide !

But i'm facing a little issue.
I've my own tinyurl domain, and I would like to add the option that if you add the domain at the beginning of an url it will made a tiny url automatically.
So everything is working but some special characters, like the // are rewrite just like that : /
became :
and.. it doesnt work..

Here is my htaccess 
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !$
RewriteRule ^(.*)$\?u=$1 [L]

What can I do?

Thanks smiley for :)

Sanjay - 12.08.10 2:34 am

Hi there

I had created a new sub-directory and using .htaccess file redirected from root to new sub-directory. However, I see that the root/forum is also redirected.

I am using root/forum on the new web address in wrapper. Could you please help me in excluding root/forum from being redirected.



DrunkMunki - 16.08.10 7:19 am

@Arun Gautam: you should never use & in file names, just remove them and the url should work, because & is used in the link for scripts and such you should not use ? and & in file/folder names.

Bipul - 18.08.10 8:10 am

good writeup but a little confusion for me here:
I have a website (developed in wordpress) with a lot of dynamic pages. we added some 350 posts to it (inserted to database directly) and have URLs-rewritten. However, google webmaster is showing these new pages as "NOT-FOUND" while all the URLs are actually working.

one of such URL's is - (using tinyurl to avoid my competitors able to find it).

we are starting to lose a lot of traffic :( please advice.

Thanks, Bipul

Snacky - 18.08.10 6:32 pm

You had just what I needed. TY!

Steve P - 18.08.10 10:03 pm


Regarding your comment to Arun, what should you do when your URL is based on PHP parameters and one possible value for the parameter contains a special character like an ampersand?

For instance, if you are talking about college basketball teams, your parameter for the school/team might be "William & Mary" or "Texas A&M". In these cases, the rewrite rule breaks down and treats the parms as "William " and "Texas A".

What to do then? Anyone? Anyone?

Joao - 19.08.10 6:30 pm

Thanks for this article!

CoYaN - 21.08.10 2:04 pm


How can I get the redirect to


Thank you in advance



Comment faire pour avoir la redirection pour que

devienne :

Merci d'avance

Bogdan - 21.08.10 3:54 pm

I usually don't comment on posts, even if them helped me. But this article is great ! Very good job smiley for ;)

raj - 27.08.10 5:09 pm


I have problem with hyperlink, when I try to insert, it takes
only index.php?........
But the url won't open unless has :
is included.

please assist .


K - 01.09.10 3:42 pm

Hi Corz,

could this be a typo in the "simple rewriting" section:

Handy for anyone updating a site from static htm (you could use .html, or .htm(.*), .htm?, etc) to dynamic php pages;

Should it read:

Handy for anyone updating a site from static htm (you could use .html, or .htm(.*), .html?, etc) to dynamic php pages;

Maybe I got that extra "l" wrong?


Ragha - 02.09.10 1:15 pm

I want user to access only .php files and others (like .js) should be accessed inside php files. So how to prevent direct access to a file like .js or .css? Please help me...

praveen - 03.09.10 3:50 pm

HI this is nice script for freshers to implement this

ramesh - 03.09.10 7:16 pm

no comment
information is use full

Vanessa - 14.09.10 8:43 am

Hello. I would like to redirect so that it turns to

I don't know how to write the rule. I've tried several times, but it doesn't work for me.

Could anyone please help me?

Thank you very much smiley for ;)

Larry - 14.09.10 9:38 pm

I have three rules in my .htaccess and only one of them seems to work:

RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&id=$2
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&cat=$2
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&sort=$2

So in essence if I have, say, this will translate correctly to but the latter two rules won't work - why?

Here's my whole .htaccess file if it helps any. Everything up until the "cat" and "sort" translations works beautifully.

RewriteEngine On
Options -Indexes
Options +FollowSymLinks
RewriteRule ^admin/$ /admin/index.php
RewriteRule ^(.*)/$ index.php?p=$1
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&id=$2
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&cat=$2
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$ index.php?p=$1&sort=$2

WILLIE - 16.09.10 10:07 am

Thnak you very much for this. It was very very useful. I resolved lots or problems I have been having with my website. Keep up the good work.smiley for :lol:

angelverde - 16.09.10 10:47 am

smiley for :eek: OMG work!

sandeep - 17.09.10 5:31 pm

i must tell that u have done very great and good research on .htaccess and all its peek uses.and i like the way u mention the things by using technical words and phrases.

thanks a lot for this

Neil - 21.09.10 12:56 am


I can't quite get the hang of it yet, could you help me please?

How do I change requests for:

To request:

On the server side?

Any help would be great smiley for :)

So I want to remove index.cgi? and change .jpg .jpeg .gif to .htm


Jarek - 22.09.10 5:02 pm

Keep up the good job!

Nano - 23.09.10 10:22 am

How to redirect this url:


Please advice me

Daniel - 25.09.10 3:30 pm

Hi everyone! I have problem with this .htaccess url rewrite

may site: <<< HIDE and cant accetp this this link.

so I wan to be soft link and hide the original link

I want it to be <<< show this only so how can I do that?

I have 3 folders in user

I want like this 3 diff name and folder < for < for < for

tae - 29.09.10 4:55 am

hi everybody, i have some problems.

I want to redirect the "404 page not found" to my homepage.
How can i do that?

If somebody know, help me please. Thank you.

rafal - 30.09.10 8:44 pm


I have a problem with my url's as well.

Here is how it looks now :,499245/

What kind of rule should I apply to get hyphens between words to have it look like this:

Any help will be appreciated.


C-the-best - 04.10.10 2:31 pm

Ragha look, if you need to restrict access to js and css.. use something like this...

Options +FollowSymlinks
RewriteEngine on
RewriteRule (.*)\.css [NC]
RewriteRule (.*)\.js [NC]

now to use that css without other people are able to download it ...

this is index.php ....

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<style><?php include('ttt.css'); ?></style>

and this is ttt.css:


the same trick with .js

<SCRIPT LANGUAGE="javascript"><?php include('script.js'); ?></SCRIPT>

with this trick the people will able to download with the browser the style/the js code but the spiders,special downloaders to grab html code(html spider,httrack website downloader , free download manager and other download sh*ts) will not ..smiley for :lol:

cheese!!! any questions :

johnny - 07.10.10 3:51 pm

Hi, i want to redirect all links in the form off sitename/word .. to sitename/word/ . Please help me. It's really important. Thanx!

juneD - 16.10.10 8:33 am

hellow.,., can u help me to shorten my url example: To be like this

IMadeItUp - 20.10.10 6:23 am

Thank you very match!
I've been on many sites learning about httaccess, and this is the best.
I will try everithing I can!!!

Sascha - 27.10.10 6:29 pm

Hi All,
thought I was pretty good in .htaccess, but learned a lot now how to shorten a URL just certain folders easily. Very ... powerfull thing.
But you should be carefull with that, or do a lot of comments in case you start having a large .htaccess, like huge lines of PHP with some MySQL, for me smiley for :D

Twitt - 27.10.10 8:51 pm

Good material. Thanks a lot.

Sohail - 28.10.10 11:33 am

I am looking for something different approach with htaccess

1) validate incoming url
2) if incorrect redirect the visitor to some other url...

For example:
I have a domain...

if a visitor is coming as...

... then Redirect the visitor to...

ElseIf a visitor is coming as...

... then let visitor gets the actual page

Can someone figure out on how to do with this?

Ray - 28.10.10 7:15 pm

Very nice article, absolutely worth to read.

Rinto George - 04.11.10 2:03 pm

Great article , ever I met. This helps me so much I started my new website

ssjimmyx - 13.11.10 11:44 am

I wanted to say " Thank You very much, for putting so many hours of research and testing scripts for a web sites 1st level of access system, and the 1st level of security access in a Web Sites Pages and Security files, being the .htaccess file(s)." I know from personal experience you have many many weeks and probably months of learning and experimenting on this platform level.... TY!!!!
very appreciated from a fellow web hosting and designer tech... :-) smiley for :lol:smiley for :D

Marks - 17.11.10 5:28 pm

1st of all ty for the research and the sharing.

What's happening to me is that when I click on the "customized" link, the new page opens correctly with the "different" url, with the right contents, BUT with no images nor CSS.

This happens when in .htaccess I don't specify the full address in the 2nd part, as in:

RewriteRule ^this/that(someParameter)$ index.php?go=$1

While if I specify the full address, I get the right page with images and CSS BUT no customized url

RewriteRule ^this/that(someParameter)$$1

Any help?

Marks - 17.11.10 8:32 pm

...about my above post, I've found that the problems is in relative links. The solution is to use RewriteRule to consider them in the right way.

For example:

RewriteRule ^.+(/img/.+)$ $1

will look for anything resembling "whatever/img/whatever" and serve it as "/img/whatever".

Hope it helps.

Mohit - 19.11.10 6:42 pm

Hey!.. I was trying to create virtual subdomain on my website.
I was able to redirect Url's like- to
Now if I want to point to a master page master.php, I get 404 when I try to access
How can I do this type of redirection using .htaccess

Mike Shafer - 20.11.10 4:04 pm

Excellent bit of coverage on a powerful but often confusing aspect of using Apache server.
Thanks for the work that went into this!


bobross - 22.11.10 5:44 am

Great site. I am having a problem with the hot linking to site code in https. The code works perfectly in http but when I go to my secure https pages, all of the images on those pages are using my "Keep out" hotlink gif. Is there a way that I can add an exception or work around? Thanks.

Chuck - 24.11.10 8:16 am

Thanks for the writeup, I have never read any htaccess info that has made this much sense..

mynsac - 26.11.10 7:25 am

Great Article! Very useful to me.

Randy - 27.11.10 6:13 pm

Just wanted to thank you for the great article. For some reason all the other mod_rewrite articles didn't make sense, yours made it clear for me.

Thank you

andoy - 28.11.10 4:35 am

Thank you for this wonderful article..

This article is very helpful to all beginners like me.

John - 28.11.10 7:18 pm

don't know how much time you spent to write this article but it's fantastic, thanks smiley for :ken:

Ryan - 01.12.10 4:05 am

Thanks for the great post.

I'm having issues redirecting the following to an external site. Is this even possible?

I want this URL:

To Go To:

Thanks for any help!

Yes, it's possible. ;o) Cor

sylehc - 17.12.10 9:42 am

First of all thank you for sharing the information.
I've modified my .htaccess to restrict the access to one local host.
ReWriteEngine On
Options +FollowSymlinks
RewriteCond %{REMOTE_ADDR} !
ReWriteRule ^(.*)$ [L]

But it works only partially: the host can access the site root ( while the folders are not accessible (
Not Found
The requested URL /about/ was not found on this server.

Do you know how to modify the rules to solve the problem?
Thank you in advance.

You don't need rewriting for this (which is like using a TE-72 to crack a nut). Check out part 1 of this article; believe it or not, the original purpose of .htaccess was to control access. ;o)

sylehc - 17.12.10 10:19 pm

Thank you for your quick reply smiley for :)
Sorry but I've found you site using google and now I'm starting to read many of your articles. WOW you have done an incredible work!!!

I modified the .htaccess in this way:
order deny,allow
deny from all
allow from

ErrorDocument 403

Still the same problem. When I try to access some folder ( I receive the message "Not Found".
Well, the folders are logical. They are generated by Wordpress as permalinks but I don't known why it happens because the host is allowed.

sylehc - 20.12.10 10:20 am

Found the problem. This part of the file was missing.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Second version of .htaccess works like a charm smiley for :)
Thank you again.

Amar Yash - 21.12.10 11:50 am

the code of .htaccess is very good and vary useful. Thanks for the code.

laotse90 - 21.12.10 7:25 pm

indeed complex... though a great complication

I missed however some information how to
exclude a particular directory/URL-path from rewriting
while all other directories should be rewritten.

help is greatly appreciated !!! thanks

Maybe read more slowly next time. ;o) Cor

Hong Duc - 27.12.10 5:12 pm

this is such a great article about .htaccess configurations and regular expression examples, I've read many other sites and I find this one is the best !!! I'll bookmark this one to read it again and again

Remi - 29.12.10 3:20 am

Is it possible to redirect a file such as


Yes, it's possible.

I've got multiple (49) random urls to forward from/to

What would be the best way to work this?

Thanks for your help, this post has been helpful already!

You don't give enough information for me to determine the best way. ;o) Cor

Ben C - 01.01.11 8:09 pm

Hi, you mention being paid, which is fine by me! I need some help rewriting URLs such as:


Can you email me before I try someone else?

How about I just ignore you, instead. ;o) Cor

Gaurav Kumar Arya - 03.01.11 7:42 pm


really this is a very good tutorial for .htacess urlrewriting.thanks for this great tutorial.

jeppy - 06.01.11 1:04 pm

Thanks for this page very well explained and completed. smiley for :D

Let me ask a question.
Is there any global method to deny access to some websites which permit to convert web pages into pdf files.

There are so many websites that it seems fastidious to enter each rewrite_cond
( and it's always possible to forget one or many ) smiley for :eek:

There is no such method. ;o) Cor

Joe - 09.01.11 1:34 pm

Hi thanks for all the info but I am having issues with a redirect I am working on and wondered if you could advise pls pls with sugar?

What I want to do is have the .htaccess file get the URL (HTTP_HOST/SERVER_ADDR) and use that URL for redirections etc.

I have 5 sites that are all mapped to the same html_directory as they all use the same layout and some of the data is shared between them.

What I need is something that will allow the .htaccess file to do redirects to the URL in the address bar and if errors happen they are redirected to the URL shown and not the manual URL written in the .htaccess file.

Example One of two

Manually written

ErrorDocument 404 (http://)
ErrorDocument 500 (http://)
ErrorDocument 403 (http://)

RewriteEngine on
RewriteCond %{HTTP_HOST} ^$ [NC]
RewriteRule ^(.*)$$1 [R=301,L]

Example Two

ErrorDocument 404 http://((GET HTTP_HOST))/faq/unavailable
ErrorDocument 500 http://((GET HTTP_HOST))/faq/unavailable
ErrorDocument 403 http://((GET HTTP_HOST))/faq/unavailable

RewriteEngine on
RewriteCond %{HTTP_HOST} ^HTTP_HOST$ [NC]
RewriteRule ^(.*)$ http://HTTP_HOST/$1 [R=301,L]

Joe smiley for :D

Htaccess Redirect - 17.01.11 1:16 am

It may seem like a super stupid bit of information, but a lot of tutorials forget to mention that htaccess files are set to "invisible" by default. In my own meanderings into needing to do an htaccess redirect quickly - on a deadline - support tickets submitted to two different hosting providers never came back with this important piece of information. I received lots of tips about what code to add to the file and how to set up an http: to www. redirect, but nobody told me how to access the darned file! It's amazing how small details often escape the "super geeks" and us "non geeks" are left feeling frustrated and, um, stupid!

Paul - 17.01.11 10:06 am


I'm trying to make an bilingual website with MODx, and the problem is that TinyMCE outputs the links for the assets like this: http://localhost/modx/(language)/assets/etc....

How can I rewrite the links to be output as: http://modx/assets/etc... without the (language), because I want to have "assets" accessible from the root.

Your help would be greatly appreciated!


Simply capture the language part, and remove it. Otherwise get inside MODx's php and change it. ;o) Cor

BEN - 17.01.11 11:19 pm

i need a url rewrite to do this.

if $2 has less than 5 characters, using script1 to rewrite, if more than 4 characters, using script2 to rewrite, and the output of the rewrite are looks exactly the same.

RewriteRule ^( <^/>+)/( <^/>+)\.htm$ script1.php?p=$1&q=$2

RewriteRule ^( <^/>+)/( <^/>+)\.htm$ script2.php?p=$1&q=$2

i am new to this. thank you for your help. please email too.

Cata - 18.01.11 11:37 am


I want to rewrite a URL like this to without parameters ,or better if it possible

In php script i use _GET to read those 2 parameters and of course this must work for rewrited URL

Can you help me?

Ashu - 21.01.11 6:35 am

Thanks for the great post.
I have learned so many things about htaccess. You done really a fantastic job by writing this useful post.

Ashusmiley for :)

Zri - 28.01.11 12:47 am

Thank you very very very much for this site, made my life a lot easier!

Michael - 30.01.11 8:51 am

When I use:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ /public/wu.login [NC]

All my links go to the /public/wu.login page

I want to redirect something like

When I use:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^/([0-9][0-9])/$ /public/wu.login [NC]

It just says 404 not found...
Any ideas?

Thank you in advance -

Extra slashes can be a problem, yes. ;o) Cor

bwald - 01.02.11 2:46 am

I've been doing a lot of searching and I came across another site ( that seems to be copying your content. The stylesheet is slightly different, and there's a blinking "(in progress)" near the top, but other than that pretty much exactly the same.

This probably seems like a good candidate for spamming. I found it by doing a Google search on "htaccess request_filename -d", 2nd result. It seems like a really odd domain name for the content, so if you don't find it maybe it's just something weird...?

Just thought you might want to know.

There are a lot of copies out there and yes, even entire domains devoted to (old) copies of my content! Google knows where the originals are, though. Thanks for caring! ;o) Cor

Michael - 02.02.11 5:46 am

I got it to work!

I'm using the pre-packaged Apache that comes with Oracle.

I changed my .htaccess file to:

RewriteRule ^(.*\.htm)$ /public/wu.login?id=$1 [NC]

And the $1 showed up as /domains/fst/test.htm ... which is exactly where it was, because my files aren't stored directly in the /htdocs/ "root". Each of my virtual hosts has it's own root further down the directory tree.

If you're getting nothing but 404 errors, you might be able to use the code above to diagnose where your files are, and make this work!

IKRA - 07.02.11 2:26 pm


Thanks for post. It's very nice ans usefull but I can't solve my problem.

Here is my situation:

In root folder I have 2 files and 1 folder.

File 1 - ser.php
File 2 - serv.php
Folder - TEST

1: I want, if in url is: http://localhost/something

Rewrite to http://localhost/ser.php?action=something

2: But if in url is: http://localhost/something/somethingelse

Rewrite to http://localhost/serv.php?action=something&subaction=somethingelse

3: This is most difficult for me:

If I have: http://localhost/TEST

NO REWRITE -> go to TEST folder

PLS, Help me

I see no .htaccess code to help you with. ;o) Cor

anadolugezgini - 09.02.11 12:09 am

Hey there smiley for :)

Thanks for great tips..i've been crawling for the correct htaccess file and found it here and yes its working charm smiley for ;)

kartik maniyar - 09.02.11 5:17 am

About Rewriting URL in .htaccess file.

I want to rewrite the module. Your Post is very good but It is not help me so i have to ask u one Question about the .htacces file rewriting URL.

At this time my URL is look like this "" but

I want to write url like this "".

because i have one module is "Shop by Design". This module is already uploaded in another Website and in that website it is work properly but in this means above mentioned site.(i have changed the name of site).

if u have any idea then tell me please it is very important for me please help me.

Here's an idea; try writing some .htaccess code, along the lines described in the above article. Have fun! ;o) Cor

Bluesp - 09.02.11 10:44 am

I am trying to alter a part of an url. The url I am trying to alter is this one:

index.php?case=subcategories&nc=33&nb=(any number here)

to this one:

index.php?case=subcategories&nc=204&nb=(matching number here)

Can't seem to figure it out so far.


It could be your lack of actual .htaccess code. ;o) Cor

PHP Developers - 12.02.11 11:02 am

Hey thank you so much for this tutorial... I loved it!

Kyle - 14.02.11 5:00 pm

I am trying to force urls to lowercase. for example I need to be directed to I am using godaddy on linux and I have tried this code in my .htaccess file with and without the Virtual host tags(found somewhere in godaddy's help that I should try it:
RewriteMap lowercase int:tolower
Options +FollowSymlinks
RewriteEngine On
RewriteCond $1 [A-Z]
RewriteRule ^/(.*)$${lowercase:$1} [R=301,L]

I keep getting a 500 Internal Server Error

Thank you!

GoDaddy don't allow .htaccess. Also, their CEO, Bob Parasite, thinks killing Elephants is a Fun Thing To Do; so much it swells him like a fat balloon. Try another host, and domain registrar soon, please. ;o) Cor

Alan Lawson - 19.02.11 4:56 pm

Thank you. Your notes on lose the www were a real time saver and worked first time.

keepout - 02.03.11 12:36 pm

i would like to restrict one page on my website for viewing by one ip address. for instance i would like
to only be available to one ip address i.e. 902.313.14.1
but i would like
available to viewer. i would really like to just lock the root folder keepout to only ip address and anything else leave it open
is there anyway to do that. thanks

Yes, see part 1 of this article. ;o) Cor

techknow - 03.03.11 6:01 am

I want to set redirection of any page of a website to another website.

like if someone access it shoule be redirected to

Please help....

sam - 03.03.11 1:56 pm

Am currently migrating my site content from an old way of forming URLs to the new order of things, mainly for SEO purposes. The old URLs looked something like any of the following: OR OR

I dont want to lose track of my previous content that google has already indexed using the old ULR formation as above. Instead, I would like these URLs to be redirected to the new URL formations as below (based on the above URLs content):

When a visitor hits on the URLs from google that are in the old format, they are automatically redirected to the new URL format, pointing to the same content.

I'd appreciate anyone's help on this. Rgds.

So long as you use [R=301], you will be just fine. ;o) Cor

g1smd - 08.03.11 10:05 pm

Heh, great tutorial.

I have read a LOT of tutorials over the years and I knew only a few paragraphs in, that it was going to be a good one.

You cleverly avoided the common errors most people make when they try to explain this stuff.

Two comments on syntax:
- don't forget to escape literal periods in patterns,
- every RewriteRule needs the (L) flag unless you know of a really good reason to omit it (such as when the (F) or (G) flag are used - it isn't needed then).

The stream of "How do I do this?" questions will never dry up. This isn't simple stuff!

Many thanks! *Arrgh*! That [L] again! It's not required for every rule (or for teaching general rewriting) but it is darned important and needs more explanation. I have a stash, draft copies of sections for this page along the lines of "To [L] and back.." where I explain in clear terms, just how to get that flag to work the way you expect. None of them look like they make sense to anyone but me, yet. Thanks for another kick. I'll get on it ASAP. And.. Unescaped literal periods?? Aw shite! smiley for :lol: ;o) Cor

Arif - 09.03.11 8:41 pm

Hello, is my current URL and I want to make this URL as

I want to use this in Magento.


Wonderful news! ;o) Cor

Peter J - 12.03.11 10:09 am

Is there any way that you can use the .htaccess file to redirect image (*.jpg) downloads to a certain image-file as well as if someone links to this image from an external page it should redirect the link to the same image.

Yes. ;o) Cor

Hope to get som help

Hendrik - 23.03.11 11:59 am

Thank you for this site! I have to admit that rewriting is still like rocket science to me...

I used one of your examples and changed it a little bit. Maybe this is helpful for others as well.

My goal was to change
(exactly the other way round as in your example).

My solution I found after some trial and error was this:
RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,NC,L]

I hope this is the correct way to do it. It seems to work though. If there is a better way, please comment.


The (.*) in the RewriteCond is redundant (unless you want to replace %{HTTP_HOST} with what you captured), but aside from that, it looks functional enough. Just, WHY? smiley for :roll: ;o) Cor

Patricio - 24.03.11 1:40 pm

Hi, i have a problem with modrewrite

if i use does not work but if i use this works fine

RewriteEngine on
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?id=$1 [L]


It's probably because that's precisely what your rule tells mod_rewrite to do. Only one "/" is allowed in the URI, for a start, and it must be at the end of the URI. Change those things. Remember, the "?1" part of your second example URI, is the query string. ;o) Cor

PHP Developer mavris - 25.03.11 4:04 pm

Thank you very much for your tutorial.
I have read many others but yours made me understand
most things about .htaccess files and i added S.E.O.
to my sites with very good results.

Thanks for giving very valuable information for free.
You helped me very much and i think lots of other people.

Continue the good work
Cheers smiley for :lol:

Prosenjeet - 27.03.11 5:08 pm

Great tutorial!

Mohammad - 29.03.11 6:41 pm

at first I have to give you a big thanks for sharing these tricks!
I have two questions:
1- What is the language of these htaccess codes?!!! they are really confusing!smiley for :roll:

it is ".htaccess code", learn to love it.

2-I have a download website and I put the links in the main site and when the user clicks on the link, he redirects to another site which is just for downloading. So user goes to "" then clicks on a link like this one: "" and after going to this site, he clicks on download links which are like this one: ""
I want to set a limitation that have these factors:

1- If a user typed download page address (""), he sees a forbidden page.
2-If a user clicked download page link ("") on other websites, he sees a forbidden page. So the only way the download site could be loaded is that the user be referred from the main site. (
3- Just like number 1 and 2 but this time for the file link.("") the limitations must be.

And it may be important that I mention these sites (main site and download site) are on different hosts!
I used these codes but the server load went high! (I think a looping was happend
!)smiley for :ehh:

#redirect users to
ErrorDocument 403
ErrorDocument 404
catch the thief!
RewriteEngine On
Options +FollowSymlinks
RewriteCond %{HTTP_REFERER} !^https?://.* [NC]
RewriteCond %{HTTP_REFERER} !^https?://.* [NC]
RewriteCond %{HTTP_REFERER} !^https?://.* [NC]
RewriteRule .*$ - [NC,F]

Why are you sending 404 and 403 errors to non-error documents? That's nuts.
Use something like this..
RewriteCond %{HTTP_REFERER} somedomain\. [NC,OR]
RewriteCond %{HTTP_REFERER} someotherdomain\. [NC]
RewriteRule . abuse.txt [L]
Note use of [OR]

I'll be really grateful if you help me solve this problem!

No you won't! ;o) Cor

with best regards


Brandon - 01.04.11 10:28 pm

I love people like you that put together excellent tutorials. I owe you big time.

This gave me a great starting point for learning how to configure a .htaccess file.

stranger - 02.04.11 11:09 am


Thanks for so great guid...But unfortunately I'm newbie about htaccess.. So I couldn't figure out how to make solution for my case.. Here it is:

I had moved all pages from to
Now I can't just redirect all pages from folder to direct homedir
Any body suggest please, how can I make it..

mod_rewrite is what you need. See above. ;o) Cor

Diva - 08.04.11 10:14 am

I must say that this is a wonderful tutorial. It help me a great deal with what I thought would be an overly complicated problem. Thank you for this lesson. I was wondering how I can create folders within my main folder that go from to Thank you for your help. Diva

See here, it's the same principle. Remember, you need to have this setup in the DNS, which I assume you can get to from your hosting panel, creating subdomains and such.. ;o) Cor

Zeko - 11.04.11 12:19 am

Hye. Is it possible to use

"deny for all" in combination with some "ErrorDocument 401 /index.html"

to make it go to index page? And how would you do it? Thank you!

See here ;o) Cor

luca - 11.04.11 2:41 pm

Hi! There is my problem:
i have a forum in mysite/forum
i would that request for example mysite/forum/index.php?par1=1&par2=2&ecc....
become mysite/index.php?par1=1&par2=2&ecc....

There is a way to do with mod_rewrite?
i want only to copy name and value of parameters and "append" to another page...

Sorry for my bad english smiley for ;)

I've solved in this way (this .htaccess is in
RewriteEngine On
RewriteCond %{QUERY_STRING} (.+)
RewriteRule ^index.php(.*)$1 [QSA]



Thank you

Toga - 12.04.11 11:20 am


At first by following your guide, I got to a part where I managed to eliminate the variables in my url, like so:
RewriteEngine on
RewriteRule ^idea/([a-z]+) /include/idea.php?id=$1 [NC]

But my intention in the end, was to be able to drop the "folder" in the front too, in this case

Couldn't figure this out by messing about with the above examples, so I went for a search through the Internet.

RewriteEngine on
RewriteBase /
RewriteRule ^([0-9a-z]+)/?$ /include/idea.php?i=$1 [nc]

This is what I found and it works fine, but I was wondering if you could shed some light on what's happening there.

I thought the "+" part on the left was replaced by the "$" stuff on the right, but now there is a "?$" on the left part as well. Also I'm guessing the base thing there sets the root? Seems to work fine without it, but the example code had it in, so not sure if I should get rid of it, even if it works.

Best Regards

The "$" has a different meaning in each context. On the left it's regular Regexp, on the right, mod_rewrite trickery. As for RewriteBase; a can of worms I guess one day I'll open fully here; I'd leave it out unless you know you need it. ;o) Cor

Chris - 16.04.11 1:30 am

Excellent work!!
I want to know how to do this:
http://localhost/variable #variable maybe contained / character
if (request is from file in my server*) then
show http://localhost/variable elseif (variable=admincp|variable=admicp/)
show me http://localhost/admincp elseif (variable!="")
show me http://localhost/php/index.php?key=something else
show me http://localhost/php/index.php?key=index

In any condition the browser url bar doesn't change.

*Explain first if: index.php with <img src="../img/image.png"/>will return the image but if i put http://localhost/img/image.png in browser adress bar will return http://localhost/php/index.php?key=img/image.png --->This file will catch and show me an 404 error page
Is something like this is achievable??
It's SEO friendly (i believe)!

Mark Iliff - 20.04.11 2:43 am

Huge thanks for this. I've ploughed through loads of other stuff on .htaccess rewriting and none is as lucid as this.

Now I've begun to master your tricks, I might understand the lengthier documentation...


Mark - 21.04.11 3:21 pm

Big thank you!
Been looking for something that explains 'the why' and not just 'the how' for htaccess (which is all new to me)
Entertainingly written too.

Will drop a little something in the box next payday

Many thanks!!!

Crazy Uncle - 22.04.11 6:34 am

Thanks for the tutorial. allowed me to reduce the number of files with the exact same content (php / smarty) yet the url looks like the file is there.

xXx - 29.04.11 9:24 am

Hi, thanks so much.
I really learned a lot from your site.
Recently, I meet a problem which I have no idea to solve it.
Please help me, thanks.

The code has been shown below is what I am using.
RewriteEngine on
RewriteCond $1 !^(index\.php|images\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

I uploaded this part of code into my server.
It looked fine, but I noticed I couldn't access to other folders which are in the same server with images folder.

And there are a lot of folders in this server, I think it's stupid to type all folder's name follow by images.
So, is there any way which can let me access all the folders?

If I knew what you were trying to achieve, I would guess it was easier without the back-references. ;o) Cor

Administer - 02.05.11 11:43 am

can you help me? :(

i want Rewrite this address:


link= showthred.php, member.php, and etc

please help me

seb - 03.05.11 1:34 pm

I need help. I want rewrite this adress:

I have three additional redirect commands and an ErrorDocument command. I also would like to know who I position the RewriteRule command then have to write?

My idea is now as follows:

ErrorDocument ...
Redirect ...
Redirect ...
Redirect ...

Options + FollowSymLinks
RewriteEngine on

RewriteRule ^([:digit:]{6})$ shortlink.php?id=$1 [NC]

That'll work, but for the rewrite something like this..
RewriteRule ^([0-9]{6})$ shortlink.php?id=$1 [NC]
;o) Cor

jokar - 05.05.11 2:23 pm

Thank you for this wonderful lesson

But I want to. htaccess

To prevent certain words from appearing on the site


sexy to *******
Pussy to ******


This is best handled inside your site code (i.e.php CMS, or whatever). ;o) Cor

kiro - 15.05.11 7:44 pm

how do i hide port 8080 from url.

example. to to

I don't know of a way to do that with purely mod_rewrite. Perhaps with mod_proxy and mod_rewrite's [p] flag... ;o) Cor

AndyiBM - 19.05.11 11:45 am

You beauty! Fixed my "multiple domains in one root" issue brilliantly.smiley for :D

Me (and loads of others) are so grateful for resources like yours. Thank you.

Alfie Punnoose - 20.05.11 7:08 am

Hi, I think the line
e.g. (.+)\.html? matches foo.htm and foo.html
must be
e.g. (.+)\.htm? matches foo.htm and foo.html


isn't it?

Nope. ;o) Cor

Salman - 27.05.11 12:39 pm

I'll never understand why the [L] flag does not work the way it is supposed to. Every now an then I end up sending the rewrite module or the browser into an infinite loop. Can you shed some light on how the [L] flag works (and why it does not work the way I expect). Or more simply, why does not this work:

RewriteRule ^foo.php$ / [R,L]
RewriteRule ^$ /foo.php [L]

It doesn't work (as you expect) because the [L] flag only applies to THIS RUN through the directives. After processing is complete, Apache must check the .htaccess rules against the new request.. Either way, it matches.

Unless you are working with httpd.conf, it's smart to be specific with your [L]'s, using RewriteCond statements to match against Apache's THE_REQUEST variable, which contains the browser's original request.

Here's a fun solution for you..
RewriteCond %{THE_REQUEST} !/
RewriteRule ^foo.php$ / [R,L]

RewriteCond %{THE_REQUEST} !/foo.php
RewriteRule ^$ /foo.php [L]

THE_REQUEST is a "special" Apache variable, something of a phantom in testing, yet generally behaving as expected when in place and working. Perhaps I should say, something of a photon, then...

;o) Cor

Eric - 03.06.11 1:34 am

Cannot seem to properly configure my 301 redirect.

I have a lot of incoming links from file extensions ending in .php. I have recently re-created my site and it no longer has a file extention.

For example went from to

All of my web pages are created through a CMS so I'm not sure if that is why everything i've tried so far doesnt seem to work or not (essentially all my pages are categories in a database.)

Tried a few of your example and didnt seem to work for me, any ideas?

Thanks for the help!

You did well enough to describe your situation, but "Cannot seem to properly configure my 301 redirect" does not at all describe your problem. ;o) Cor

Collin - 05.06.11 6:17 am

Cool post. Helped me out a lot. Thanks! smiley for :)

Mondor - 18.06.11 6:29 pm

I don`t know if i am in right place but i put this question.
i had in my httacces this rule

RewriteRule ^detalii/.*/([0-9]+)/?$ index.php?module=products&action=details&prod_id=$1 [L,NC]

and need to keep it and redirect to new rule as
RewriteRule ^detalii/([0-9]+)/.*/?$ index.php?module=products&action=details&prod_id=$1 [L,NC]

for google purpose do not need for reindex.
Need old format to be redirect to new format.

Thanks in advance

Boggy - 19.06.11 6:37 am

I have a multi-user site and I wrote my own script for creating subdomains via cPanel at registration time. Everything is nice and dandy but now I need to implement a rewrite rule in order to display the right web address for my members. What I mean is this - member1 will have a folder created with the same name and also a subdomain allocated (called member1 too). When typing in the address bar the redirect will take the user to the location of "member1" folder inside my site - something like What kind of rewrite rule should I implement in order to keep the address bar displaying Remember I have numerous subdomains so I can not create a rewrite rule for every single one of them. I need a general one to deal with a generic subdomain. My host does not allow for wild card subdomains so that is why I chose to dynamically create them through cPanel, but i have access to htaccess file. Any help will be much appreciated.

Thank you,

Clearercape - 22.06.11 8:55 am

Great tutorial. Really helped. I need help with this one. I cannot get the rewrite to work on this string:


What am I doing wrong?


Manoj Thomas - 22.06.11 5:52 pm

Useful info, thanks!

Shaun Janssens - 07.07.11 10:40 am


I have a problem with a blog and a URL shortener in the same folder.
My short url make them URL's like: or 2 and so on.
But that conflict with mine. Htaccess.

For my blog:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^. + $ Index.php [L]
</ IfModule>

For my url shortener:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule (.*) index.php? Token = $ 1 [QSA, L]
</ IfModule>

As you can see the rewrites. Htaccess each url. Can it be adapted so only as a URL from a maximum of 4 digits long and is then rewrite but which may be carried out?


shravan - 08.07.11 10:31 pm

i read only half of the second part.
i want thank you for this article. this is rally helpful article.
i learnt little regular expression also from this article.
overall wonderful article. thanks a lot.

Rob - 11.07.11 4:44 pm


Very interesting article and I think I get most of it but not enough to solve a problem I am having.
I tried to redirect some files with the htaccess but so far did not succeed.
I want to redirect all files in my main folder like article_articlename.html
to articles/articlename.php
so basically I am trying to redirect all files starting with "article_" to the folder "articles"

This is what I tried:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^article_([a-z]+).htm$ /articles/$1.php [R,NC]

If I don't want the file extension to be specific (i.e. could be anything .html, .htm, .php) would it become easier?
I probably have to redirect to to make it more fool proof right?

Anyhow, I hope you can help me with this

Cheers... Rob

I see no reason why it wouldn't work, assuming..

* rewrites are working on your system (this is not redirection!)

* The requests are actually for, which is to say, files in the root of the site with an .htm extension.

* The target files are in a directory in the root named "articles", and the corresponding .htm file namess now have .php extensions.

If this is all true, and it's not working, exactly what is happening? What errors are you getting? Where is Apache sending the browser? etc.

Making the extension a wildcard doesn't make anything easier, it simply makes the rule more loose. If that's what you need, do it. But I'm guessing the htm > php conversion is enough.

;o) Cor

Ray - 12.07.11 6:58 am

Hey thanks for this, I've been scouring the web for this info, but all I've found are snippets here and there. Some of it out of date too. I was considering writing about it myself, but I'm just an amateur. No way could I have put together a comprehensive and entertaining article as interesting as yours.

Cheers! smiley for :lol:

yaniv - 14.07.11 4:48 am

Wow, amazing guide smiley for :) and I went over many guides for mod_rewrite smiley for :)
big thanks!

Rob - 14.07.11 11:05 pm


Thanks for the comment on my question before.
Where I went wrong was that I tried to redirect(oops, rewrite) .htm files and the files are all .html, so by adding a simple l after .htm it worked.
It is all in the details...


Rob - 15.07.11 3:31 am

Forgot to ask something else,

Can I actually put a second rule in?
I need to rewrite all files starting with newsletter_ to /news/*.php as well.
Can I just put another RewriteRule under the first one?

Thanks a bunch.


Sure, some people have thousands. ;o) Cor

Ali - 20.07.11 11:57 am

i need to rewrite a URL in .htaccess file ,it is something like this,
the problem with this url its too long ,and also space character is also %20 there in the URL,
can you please help me how to shorten the url and also to remove %20,as well,like how i define rule in .htaccess file ,what expression should
i write to first match this type of url and how to rewrite new url,
i will be thankful to you.

The normal pattern matching method will work fine. As for removing the space, from where? ;o) Cor

nik - 25.07.11 9:44 am

httpd.conf  - linuxsuse 11 and apache2

ProxyPass /X1/
ProxyPassReverse /X1/
RewriteRule ^/X1$ /X1/ [R]

When I write in my computer URL I see that apex/f%3Fp=220:1 is not allowed.  - because the url is not OK. 
Apache make ? to %3F

How to repair that 

I've added AddDefaultCharset utf-8 in httpd.conf. but it doesn't work or I don't know how to use it.

There's no obvious reason why it would do that. I use the [p] flag, instead of ProxyPass, wherever possible. Then, if required, check out the [NE] flag, also. ;o) Cor

WHATEVER - 26.07.11 10:47 am

Capisce, capisci, or capito. not capiche.

thx for the article btw

It's a joke, as in a spaghetti western. If you were to hover your mouse over the word, you would have seen the real version. Thanks for the laugh, btw. ;o) Cor

Sajin - 26.07.11 4:29 pm

Can anyone help me to write a rewrite rule?

I already did, in the main article. ;o) Cor

Sknz - 27.07.11 1:46 am

Hi! your site is better!

Well, i can use <Files> or <FilesMatch> to Deny All "except" file1, file2, file3 and file4 ?

For example, i want deny access to all files like> php|htm|html|shtml|xml but i need free access to files> 404.html, sys.php and work.htm

How i can do this? if possible..

Follow the examples in the main article. ;o) Cor

edward - 11.08.11 7:38 am

Do you know of a rewrite that works if only some variables are present?
RewriteRule ^location/([^/]+)/([^/]+)/([^/]+)? /store.php?state=$1&category=$2&rating=$3 [QSA]     will yield:       works fine     will yield:              doesn't work!  404 Error

any suggestions?

Use RewriteCond to check for it. ;o) Cor

Anand - 26.08.11 10:19 am

I got a queriy and wanted your help in this regard.
When people access my domain it is redirected to file using php code.I used
RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L] 

to redirect people from non www to www but its not working. Still user can access

Rewriting is NOT redirecting. The latter uses mod_alias, not mod_rewrite. Secondly, OF COURSE they can, unless you use some mechanism to prevent it. ;o) Cor

Idham - 01.09.11 9:15 pm

Thanks a lot, your tutorial very helpful smiley for :)

Niko - 02.09.11 10:33 am

Hi there!

Great tutorial, well documented and with actual examples... thanks man.

I'm stuck with that redirect through 301 to my where stuff is hosted.
Is there any way to maintain in the URL browser box, putting some rewrite magic inside the folder ?

Can I do that with rewrite mode ?

Thanks and keep up the good work

Of course you mean REWRITE with R=301, so NO, the 301 code specifically instructs the browser to go to the new location, aka "External" rewrite. instead, consider an internal rewrite or use [p] ProxyPass to handle the request. ;o) Cor

sayali - 06.09.11 10:29 am


Its very nice tutorial. Thanks for sharing....

Also need some help for creating URL Like,

currently I am having url like,


Very nice! ;o) Cor

zeshan Khattak - 14.09.11 6:54 pm

Great Article. Very much helpful.

I still have a bit problem with my url...
This is my original URL:

I want to convert it into the following URL.

I am searching for help for one week but cant find solution.
I will be very thankful to you if helped.
Thanks in advance.


Read the article again, but more slowly, is my recommendation. ;o) Cor

Olivier - 17.09.11 1:07 pm

I would like to block a browser language and I have added these line in my htaccess but it doesn't seem to work:

RewriteCond %{HTTP:Accept-Language} ^zh [NC]
RewriteRule ^.* - [F,L]

What would be the correct synthax?
Thank's in advance.

Content negotiation doesn't work like that; it's inclusive. If you are trying to deny access to all Chinese speaking peoples, why not simply deny all their IP blocks? Better yet, don't bother. ;o) Cor

Maggie - 17.09.11 11:25 pm

Thank you very much for this article - I've been bashing my head against a ton of mod_rewrite docs (official and un-) and this is the clearest, most comprehensible I've run across. The conversational tone really helps.

Neville - 19.09.11 9:10 pm

I have renamed a few of my webpages, now I want do a redirect ot the 404 pages! I am hosted on an appache server, but I have never try my hand at .httaccess.

Can you please advise on the subject on how to do a redirect! Do I really need to use .httaccess?

I need help badly,

My regards,

smiley for :blank:

I have very limited knowledge of redirect, preferring rewrites, as above. Search part one of the above article for the phrase "404", and download what you find (my clever 404 script). If you use php on your site, its ability to jump users automatically to your missing pages will be most useful. ;o) Cor

Stickyness - 20.09.11 9:05 am

Hi Cor,

Must say, I find your blog, its content and your explanations very informative and often enlightening. Thanks! I visit often when I'm stuck or other dudes don't explain as well.

I have some terrible mod_rewrite ailments and using your catch-all.php would help me guide those in the know to help me overcome the Apache Fever I currently have.

One question: when you say: 'make it your target' does the RewriteRule go in the .htaccess, I assume, and does it stand on its own?

Just trying to get a practical application of using this amazing debugging tool to end my nightmare.

Yes, the rule would go inside .htaccess (or anywhere else you might put a rewrite rule, httpd.conf, etc.), Here's a slightly useful example..

RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_URI} !debug-report.php
RewriteRule . debug-report.php?uri=%1

And Yes, it stands alone. If everything goes to plan, debug-report.php pops up in your browser with oodles of information.

;o) Cor

ps. my blog is at /blog/, this is a finely crafted article!

shri ram - 20.09.11 1:19 pm

Hello Sir
I have site as and i have one more domain as

I want point to but it should not change the URL address. URL address must be

Can you please tell me how can i do that?

Use an internal rewrite (no [R] flag). ;o) Cor

azanga - 22.09.11 10:05 am

Hello, thank you for this post, very helpful!

i have a small problem, i change the script i'm using for my website, and i want to redirect all url's to my new website...
How can i do it?
i have .htaccess

this is the old url look like:

And i want to redirect to
can i use redirect 301?
and how can i setup the .htacess to redirect all /quick_search?xxxxxxxxxxxxxxx
because i have 2800 url to redirect

Thank yousmiley for :lol:

Yup, a regular R=301 will work. Use the [qsa] flag to keep your query strings. ;o) Cor

a - 23.09.11 11:58 am

If I want to remove the .php .html .htm etc extension and I want any case that user key in url, it change to lower case.
And I want to define my own 404 error. I had a 404 erro