Not sure whether this is directly related to Craft but I’ve been using this method for years and it has always worked with other sites.

I’m replacing an old site and some pages have moved. I want to redirect any old pages to the new url since there are already indexed.

I’m using a simple redirect 301 Redirect 301 /work/project-name http://www.mysite.com/case-studies

I’m getting http://www.mysite.com/case-studies/project-name?p=work/project-name and of course a page not found since this is not where I intended the page to go.

  • Just a hunch, but try setting omitScriptNameInUrls to true in your config file.
    – Lindsey D
    Mar 9, 2016 at 0:06
  • Nope. Unfortunately that didn’t change anything. Mar 9, 2016 at 7:23

1 Answer 1


Craft works by taking requests that normally would 404—because they don't actually exist on the server but in the database. The piece that makes this happen is the rewrite rules.

It's helpful to look at Craft's .htaccess file line-by-line:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

The request must not already exist and the file is not already an existing directory on the server.

RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]

The URL must not be favicon.ico, apple-touch-icon.whatever.png. The NC at the end means no-case (meaning case-insenstive).

RewriteRule (.+) index.php?p=$1 [QSA,L]

This is the rule that actually fires. Take those would-be 404s, redirect to /index.php (the controller). $1 means the match found in (.+).

The QSA flag means query string append. This is the part that's actually causing you issues. (You could remove it but get URLs with parameters called from controllers might not work in certain situations.)

L means last; if this rule is applied, it won't process anything else. Doesn't matter here unless you have other rules.

What you need to do is tell Apache to exclude this particular request from Craft's processing (put it after the favicon rule):

RewriteCond %{REQUEST_URI} !^/(work/project-name)$ [NC]

Now what will happen is your Redirect 301 rule will fire by itself. Since /case-studies doesn't actually exist on the server, Apache is going to send that rule back to Craft and fire like any normal "page" which is what you want.

If you have other redirected 301s from the old /work section, you might do something like:

RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC]

That will let Craft know not to touch any of your 301s in the old work section. You still need your old Redirect 301 rules. (You could make a RewriteRule for those if you wanted to simply things but this will get you going.)

Your completed file would look like:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]

Redirect 301 /work/project-name http://www.mysite.com/case-studies

I find some browsers will "cache" an old page/redirect for awhile. To confirm it's actually working you might want to use curl -I http://site/work/project-name. If you see "moved permanently" message, you're all set.

  • this doesn’t seem to work for me. What I’m trying to do is to redirect old pages (which are non-existent now) to new ones. /work is now /case-studies. anything preceded by /work/ can go to /case-studies too. I thought this was going to be simple and straightforward. Mar 9, 2016 at 18:08
  • Can you post your .htaccess? Mar 9, 2016 at 18:14
  • <IfModule mod_rewrite.c> RewriteEngine On # Send would-be 404 requests to Craft RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC] RewriteRule (.+) index.php?p=$1 [QSA,L] RewriteEngine On RewriteBase / Redirect 301 /work /case-studies Redirect 301 /work/the-cake-decorator /case-studies Redirect 301 /work/cream-co /case-studies/ Redirect 301 /work/josies /case-studies Redirect 301 /work/head-smash /case-studies Redirect 301 /profile/seven-ideas /profile </IfModule> Mar 9, 2016 at 18:36
  • You want to make sure RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC] is included. I've updated my answer above with a more complete example. Mar 9, 2016 at 19:09
  • 1
    @RitterKnight Thank you for the interesting explanation.
    – Masiorama
    Oct 10, 2017 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.