<p>Had the same problem and found this solution:</p>
<p>Instead of <code>Redirect 301</code> use a <code>RewriteRule</code> instead:</p>
<p><code>RewriteRule ^/work/project-name(/.*)?$ /case-studies$1 [R=301,L]</code></p>
<p>Insert this <strong>before</strong> Craft's Rewrite rules and it should work.</p>
<p>Credit where credit is due: This solution <a href="https://craftcms.stackexchange.com/a/940/5424">here</a> and it is from <a href="https://craftcms.stackexchange.com/users/103/anna-mediagirl">Anna-Mediagirl</a></p>

CC BY-SA 4.0
2023-01-06T19:33:49.347Z
2023-01-06T19:33:49.347Z
Luke
<p>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. </p>

<p>It's helpful to look at Craft's <code>.htaccess</code> file line-by-line:</p>

<pre><code>RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
</code></pre>

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

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

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

<pre><code>RewriteRule (.+) index.php?p=$1 [QSA,L]
</code></pre>

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

<p>The <code>QSA</code> 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.)</p>

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

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

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

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

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

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

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

<p>Your completed file would look like:</p>

<pre><code>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
...
</code></pre>

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

CC BY-SA 3.0
2016-03-09T18:08:26.770Z
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.
Clint Tabone
CC BY-SA 3.0
2016-03-09T18:14:24.460Z
Can you post your .htaccess?
RitterKnight
CC BY-SA 3.0
2016-03-09T18:36:54.120Z
<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>
Clint Tabone
CC BY-SA 3.0
2016-03-09T19:09:21.210Z
You want to make sure ``RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC]`` is included. I've updated my answer above with a more complete example.
RitterKnight
CC BY-SA 3.0
2017-10-10T18:49:54.937Z
@RitterKnight Thank you for the interesting explanation.
Masiorama
CC BY-SA 3.0
2016-03-09T17:25:50.373Z
2016-03-09T19:08:35.607Z
2016-03-09T19:08:35.607Z
RitterKnight
<p>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.</p>

<p>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.</p>

<p>I’m using a simple redirect 301
Redirect 301 /work/project-name <a href="http://www.mysite.com/case-studies" rel="noreferrer">http://www.mysite.com/case-studies</a></p>

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

CC BY-SA 3.0
2016-03-09T00:06:30.320Z
Just a hunch, but try setting [`omitScriptNameInUrls`](https://craftcms.com/docs/config-settings#omitScriptNameInUrls) to `true` in your config file.
Lindsey D
CC BY-SA 3.0
2016-03-09T07:23:41.407Z
Nope. Unfortunately that didn’t change anything.
Clint Tabone
<redirect><htaccess>
Why am I getting ?p=oldpage in a 301 redirect?
# Why am I getting ?p=oldpage in a 301 redirect?

(Asked by: username_0 on 2016-03-08)

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.

**Tags:** redirect, htaccess
> **Comments:**
> **username_1**: Just a hunch, but try setting [`omitScriptNameInUrls`](https://craftcms.com/docs/config-settings#omitScriptNameInUrls) to `true` in your config file.  
> **username_0**: Nope. Unfortunately that didn’t change anything.  

---

## 2 answers

### Answer by username_3 on 2016-03-09. Score: 9 | Accepted answer

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.

> **Comments:**
> **username_0**: 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.  
> **username_3**: Can you post your .htaccess?  
> **username_0**: <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>  
> **username_3**: You want to make sure ``RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC]`` is included. I've updated my answer above with a more complete example.  
> **username_4**: @RitterKnight Thank you for the interesting explanation.  

---

### Answer by username_2 on 2023-01-06. Score: 1

Had the same problem and found this solution:

Instead of `Redirect 301` use a `RewriteRule` instead:

`RewriteRule ^/work/project-name(/.*)?$ /case-studies$1 [R=301,L]`

Insert this **before** Craft's Rewrite rules and it should work.

Credit where credit is due: This solution [here](https://craftcms.stackexchange.com/a/940/5424) and it is from [Anna-Mediagirl](https://craftcms.stackexchange.com/users/103/anna-mediagirl)


---

