I recently released my new Drupal site online, replacing its predecessor, which was run by a home-spun CMS that I never really finished properly (I eventually gave up on re-inventing the wheel). My new Drupal site is at the same address as its predecessor.

The problem is that my logs are getting flooded with 404 errors, constantly reporting that the pages of the old site (which are no longer online) cannot be found. The errors are all generated by search bots such as googlebot continuing to hit these non-existent pages.

I've done some reading on the subject, including:

http://drupal.org/node/8278 (drupal handbook page on redirecting old URLs)
http://www.tamingthebeast.net/articles3/spiders-301-redirect.htm (in-depth how-to on redirecting)

And from looking at these sources, I gather that putting a 301 redirect in my .htaccess file is the way to go. 301 is appropriate in my case, since all the 404-not-found pages have corresponding pages on the new site. Because the old URLs don't map exactly to the new ones, I have to put in a specific redirect for each one (only about 30 all up). Here's what I've got in my .htaccess (I put it just above the "overload PHP variables" in the Drupal default .htaccess - someone let me know if this is the wrong place, or if it even matters where it goes):

Redirect 301 /forums.php http://www.greenash.net.au/index.php?q=contact/forums

This works fine, and seems to be stopping the flood of errors. But what I'd really like is to do this:

Redirect 301 /forums.php http://www.greenash.net.au/contact/forums

When I do this, however, I get an http 500 error. Is there any way to make the old pages redirect to their corresponding new pages, but for the redirects to use clean URLs? Drupal handbook, other forum threads, and external sources that I've seen didn't answer this. I suspect that I need to use a mod_rewrite RewriteRule instead of just a Redirect, but I'm not much of a "regexpert", and don't know how to do it. Any suggestions?

All help appreciated,

Jeremy Epstein - GreenAsh


amanda’s picture

I have a similar problem, and the 301 redirects might solve it (i'm not bent out of shape about keeping the clean URLs, though it would be nice), but I would like to try to decipher it by looking at my webstates. Problem is the stats live (according to my ISPs set up) at www.mysite.net/stats which I can't get to with Clean URLs turned on. Does anyone know how to edit the .htaccess file to allow certain urls to resolve outside of the drupal system?

Jaza’s picture

I was having this problem too - I have various html pages stored in subfolders on my site, and I was getting errors when I tried to access www.mysite.net/subfolder also. What I did was edit this line of .htaccess:

# Set the default handler to index.php:
DirectoryIndex index.php

Like so:

# Set the default handler to index.php (and index.html):
DirectoryIndex index.php index.html

Since the index page for all my subfolders is index.html, this was all I needed to do - all the errors went away. You may need to add various other names, e.g. index.htm, index.shtml, index.asp, index.cgi, index.cfm, etc. (maybe it's possible to put index.*? not sure). You can also put this in a separate .htaccess file in the subfolder, if you only want it to affect a specific area - although as long as you leave index.php at the top, Drupal shouldn't be affected.

Jeremy Epstein - GreenAsh

Jeremy Epstein - GreenAsh

axbom’s picture

I have the same problem and would love to see how anyone has solved this. I've posted my query on modrewrite.com and you can read the full post there:



axbom’s picture

Searching for something entirely different I stumbled upon the solution. The trick is not to use the Redirect command but instead to rewrite the URL.

In your example above, the correct entry in .htaccess would be

RewriteRule ^forums.php$ http://www.greenash.net.au/contact/forums [R=301,L]

The 301 tells browsers and spiders it is a permanent redirect, and the L ensures that no other rewrites are processed on the URL before it reaches Drupal; Hence place this code above Drupal 's own URL rewrite, but below the command RewriteEngine on.

This should perhaps go in the Drupal handbook.
Good luck!


Jaza’s picture

Thankyou very much for finding that solution, axbom, and for posting it here! As I said at the start of this thread, I suspected that a RewriteRule would be needed, but I had no idea how I was to go about using it.

I didn't think it would be that easy - the example you've given is almost as simple as a non-mod_rewrite redirect.

Jeremy Epstein - GreenAsh

kyote’s picture

Sweet! This really helped out. I switched from wordpress to drupal on a site and had all these hits to the old RSS feeds. This worked out great!

Jason Shultz
Open Sky Media

sepeck’s picture

Create a new page in the handbook as a child page in the migrations section perhaps? It will go into moderation and be reviewed before approval

Test site...always start with a test site.
Drupal Best Practices Guide

-Steven Peck
Test site, always start with a test site.
Drupal Best Practices Guide

slower’s picture

I've fixed my URLs using this excellent suggestion, but for some reason, if I append a query string to the old URL, it still carries over to the new, clean Drupal URL. An example of my htaccess entries looks like so:

RewriteRule ^profiles.php$ http://www.ayfn.org/about/members [R=301,L]

This goes after "RewriteEngine on" and before the Drupal rewrite rules. When accessing "http://www.ayfn.org/profiles.php?test=true" the resulting URL is "http://www.ayfn.org/about/members?test=true".

How can I lose that unwanted query string? The "L" option doesn't seem to be working...

India Ink Web Design

axbom’s picture

Sorry for a late answer, haven't checked the forums for a while.

You need the QSA flag. QSA means "Query String Append" and tells Apache that if there is a query string present, it needs to be used again in the resulting query.

RewriteRule ^profiles.php$ http://www.ayfn.org/about/members [R=301,QSA,L]

You will notice the same flag present in the Main Drupal Rewrite section of the .htaccess file:

RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]


slower’s picture

Actually, the query string is carrying over already -- I'm trying to drop it entirely. Whether or not the QSA option is present, the query string is attached to the new URL.

India Ink Web Design

slck0’s picture

I'm pretty ignorant in this area, but one benefit of the redirect is it could redirect any file in a directory to the same filename in the new directory. Is it possible to do the same with the rewrite?

For example:
http://www.site.com/dir/ goes to
http://www.site.com/dir/anyfile.htm goes to

timetrial’s picture

This will do it:
RewriteRule ^dir/(.+)$ http://www.example.com/newdir/ [R=301,L]


Ian Ward’s picture

I have a link like fishing/index.php?pid=200 which i want to redirect to another url. I've tried commenting out and not commenting out the special characters, but nothing seems to work. I've also included ^ and excluded it. Anyone have any ideas? I thought it might have something to do with not including the query string on the new URL, but not sure...

I tried the following:

RewriteRule fishing/index\.php\?pid=200 http://www.example.com/fishing [R=301,L]
RewriteRule fishing/index.php?pid=200 http://www.example.com/fishing [R=301,L]
RewriteRule ^fishing/index.php?pid=200 http://www.example.com/fishing [R=301,L]
RewriteRule ^fishing/index\.php\?pid=200 http://www.example.com/fishing [R=301,L]
jmiccolis’s picture

It looks like the way to do this is:

RewriteCond %{QUERY_STRING} pid=200
RewriteRule ^fishing/index\.php$ /fishing? [R=301,L]

This should turn www.example.com/fishing.php?pid=200 into www.example.com/fishing

unrev.org’s picture

I have done what I believe to be everything correctly. However, this is still not working!

I used the info on the book page pertaining to this forum posting to create the following:

# Modify the RewriteBase if you are using Drupal in a subdirectory and
  # the rewrite rules are not working properly.
  #RewriteBase /drupal

  #custom redirects
RewriteRule ^workshops_main.htm$ http://www.mydomain.org/workshops [R=301,L]
  #end custom redirects

  # Rewrite old-style URLs of the form 'node.php?id=x'.
  #RewriteCond %{REQUEST_FILENAME} !-f
  #RewriteCond %{REQUEST_FILENAME} !-d
  #RewriteCond %{QUERY_STRING} ^id=([^&]+)$
  #RewriteRule node.php index.php?q=node/view/%1 [L]

I have added the before and after code to show where I placed this in the .htaccess file.

I do have the RewriteEngine on:

# Various rewrite rules.
<IfModule mod_rewrite.c>
  RewriteEngine on

It is still not working, however, and all I end up with is a page that says "2" in the main content area. Thus, it is not a 404 not found error, just a lonely "2".

For the record, I did save the file as UTF8, as suggested in the above-mentioned book page.

One thing that might be affecting it is that I am using a different domain name than the original site for the development site. I don't think this would cause this problem, though.

Any suggestions for this? I am using 4.7.2

Many thanks!

unrev.org’s picture

and it worked fine.

I started with the original .htaccess file and it worked!

I must have had some problems with the saving of the file in UTF8 format or something.

swordbreaker’s picture

I'm importing a wordpress site to drupal, I have 500+ posts all with the url of www.mysite.com/?p=id (i.e. www.mysite.com/?p=500). In the new Drupal site they become www.mysite.com/id (i.e. www.mysite.com/500).

I have read through the handbook article, as well as searched through the threads here, based on what I've read, I added the following to my .htaccess file:

#custom redirects

RewriteRule ^/(.*)$ http://mysite.com/ [R=301,L]

#end custom redirects

And now when I enter the old URL, it simply leads me to www.mysite.com/?p=id, I've also tried other variations of the codes, and spent hours searching on google for solutions.

I know it's probably something simple that I've missed, on the handbook it says ^old/URL/path$ is the old path off the root, so mysite.com/?p=id would be /(.*)? And since http://yourdomain.com/new/path is the full path including the domain, in my case where the new url is mysite.com/id, I just put in http://mysite.com/, do I need any special character after that? Or do I need something more, like:

RewriteCond %{QUERY_STRING} ^p=([^&]+)$ (which I have tried and didn't work)

Despite being quite "computer illiterate," I'm really enjoying my time playing around with Drupal, and it's providing me with a lot more options than WordPress would have in the long run. If anyone would care to explain it to me, I would be very grateful.

swordbreaker’s picture

Just figured it out, for those who cares, I used

RewriteCond %{QUERY_STRING} ^p=([0-9]+)$
RewriteRule ^$ http://www.mydomain.com/%1? [R=301,L]
bsuttis’s picture

Sorry to be a bother, but for some reason using the simple works for my site

redirect 301 /index.html http://www.example.com/content

The old site was just static HTML (no CMS) and drupal is in a subdirectory (/content). Anyone know why it works for me? Maybe this still isn't the best way to redirect? I don't wanna lose my search engine rankings. A explanation is appreciated. =D

ahniwa’s picture

I recently moved my wordpress blog to a /blog subdir from it's long-standing home on the root dir. I put what will, at some point, be a drupal portal at the root. It's probably the most straightforward rewrite, but I lack experience in these things. Anyway, using clean URLs for both, I found this line to save my a$$.

RewriteRule ^(.*)$ http://www.mysite.com/blog/$1 [R=301,L]

Thanks to everyone here for posting their comments. They were really helpful!

ahniwa’s picture

Is there any way I can run the rewrite script I wrote previously ONLY when the queried page isn't found on the root directory? For instance, I don't want mysite.com to rewrite to mysite.com/blog, because mysite.com exists as well. But I do want mysite.com/2004/12/blog-post-93 to rewrite to mysite.com/blog/2004/12/blog-post-93. A way to do this in either the .htaccess or in a custom 404 file would be greatly appreciated. Thanks in advance!

nishitdas’s picture

I am facing the problem of added Extra String at the end of new redirected URL.

The OLD URL I want to redirect: http://cat4mba.com/tips/?p=1
The New URL to which above URL need to be redirected : http://cat4mba.com/node/144

What I have tried:
RewriteCond %{QUERY_STRING} p=1
RewriteRule ^tips/$ http://cat4mba.com/node/144 [R=301,L]

RewriteCond %{THE_REQUEST} p=1
RewriteRule ^tips/$ http://cat4mba.com/node/144 [R=301,L]

Both does the same thing it directs me to my new url but with an extra string ?p=1 ie my new url is http://cat4mba.com/node/144?p=1

How to get rid of the unnecessary ?p=1 string. The redirection is working fine as long as contents are concerned as it is taking to the right page.

nishitdas’s picture

I got the solution.
If some one else is having the same problem, just add ${pages:%1¦NULL}? At the end of the url and it ll do the trick

nishitdas’s picture

Sorry i fogot to write the complete code
The OLD URL I want to redirect: http://mysite.com/tips/?p=1
The New URL to which above URL need to be redirected : http://mysite.com/node/144

The code

RewriteCond %{QUERY_STRING} p=1
RewriteRule ^tips/$ http://mysite.com/tips/?p=1${pages:%1¦NULL}? [R=301,L]

cowhead’s picture

I'm trying to redirect

I can do simple redirects but when the original page has two php variables and is in a directory I always get a server error. I've tried all sorts of things... anyone got an idea?


cowhead’s picture

Can anyone help me out here?

nishitdas’s picture

try the below code..it shd word

RewriteCond %{QUERY_STRING} var1=x&var2=y
RewriteRule ^exdir/page\.php$ http://www.example.com/some/seo_friedly/URL${pages:%1¦NULL}? [R=301,L]