# How to set up redirects in .htaccess

> 301s for pages you have moved, the difference from a 302, and the order that stops rules fighting each other.

Source: https://cwp.sg/tutorials/htaccess-redirects/  
Author: Ben Johnson  
Last verified: 2026-09-21

**In short:** - A 301 redirect is permanent and cached by browsers; always test with a 302 first to avoid serving the wrong URL for days. - Put specific redirects above general ones in `.htaccess` — the first matching rule wins, and a general rule can block a specific one below it. - One syntax error (missing quote, extra space) causes a 500 Internal Server Error on your whole site; rename the file to `.htaccess.bak` to recover. - Redirect loops happen when a rule sends a request to a URL that still matches the same pattern; use the `L` flag and test with 302 to spot them.

You are getting 404 errors because you moved a page, renamed a file, or restructured your directories. The fix is a redirect in `.htaccess`. One wrong line and the whole site goes down.

This guide covers the two redirect methods for your free hosting account at cwp.sg, explains why order matters, and shows you the trap that creates redirect loops.

## 301 and 302 — pick the right one

A 301 redirect is permanent. Browsers cache it aggressively. If you test a 301 and get it wrong, visitors will keep hitting the old destination for days. A 302 is temporary, and browsers generally do not cache it the way they cache a 301.

Test with a 302. Once you confirm the redirect works, change it to 301.

```apache
# Temporary — use this for testing
Redirect 302 /old-page.html /new-page.html

# Permanent — only after you verify the 302 works
Redirect 301 /old-page.html /new-page.html
```

## Redirect by file

Match a single file path.

```apache
Redirect 301 /products/widget.html /shop/widgets/widget.html
```

The path starts after your domain name. The full URL `https://your-site.cwp.sg/products/widget.html` becomes just `/products/widget.html` in the rule.

## Redirect an entire directory

Send everything under `/old-folder/` to a new location.

```apache
Redirect 301 /old-folder/ /new-folder/
```

A request for `/old-folder/blue/` goes to `/new-folder/blue/`. The trailing slash on both paths matters — leave it off and the redirect may not work.

## RewriteRule for patterns Redirect cannot handle

`Redirect` is simple but limited. It cannot match patterns, query strings, or parts of a URL. For that you need `RewriteRule`, which uses regular expressions.

Turn on the rewrite engine first:

```apache
RewriteEngine On
```

Then write the pattern and the target.

```apache
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
```

The `R=301` flag makes it a permanent redirect. The `L` flag means "last" — stop processing rules after this match. Without `L`, Apache may apply more rules to the redirected URL.

Redirect a directory with RewriteRule:

```apache
RewriteRule ^old-folder/(.*)$ /new-folder/$1 [R=301,L]
```

The `(.*)` captures everything after `old-folder/`. The captured part is not needed here because the directory structure stays the same.

Strip a query string:

```apache
RewriteRule ^product\.php$ /product/ [R=301,L,QSD]
```

The `QSD` flag discards the original query string. Without it, `?id=5` survives the redirect.

## Rules run in order — put specific above general

Apache processes `.htaccess` from top to bottom. The first matching rule wins. Put your most specific redirects first and the catch-all ones last.

Wrong:

```apache
Redirect 301 /products/ /shop/
Redirect 301 /products/widget.html /shop/widgets/widget.html
```

The second rule never runs. Every request for `/products/widget.html` matches the first rule and goes to `/shop/widget.html`. Add a 404 because that file does not exist at `/shop/`.

Right:

```apache
Redirect 301 /products/widget.html /shop/widgets/widget.html
Redirect 301 /products/ /shop/
```

The specific file rule runs first. Only requests that do not match it fall through to the directory redirect.

The same applies to RewriteRule. Test your ordering by reading the file top to bottom with a few example URLs.

## The loop trap

A redirect loop happens when rule A sends a request to URL B, and URL B matches rule A again. The browser gives up with `ERR_TOO_MANY_REDIRECTS`.

Common cause — redirecting to a URL that still matches the original pattern:

```apache
RewriteRule ^old/(.*)$ /new/ [R=301,L]
```

If the rewritten URL is `/new/something` and your site has another rule that matches `/new/` back to `/old/`, you have a loop. The request bounces forever.

Another cause — using a relative path that resolves to the same directory:

```apache
Redirect 301 /folder/ /folder
```

No slash at the end of `/folder`. Some servers see `/folder` as a file path and redirect again to add the slash. Loop.

If you hit a loop, clear your browser cache and test with a 302. Use the `L` flag on every RewriteRule to stop processing after a match.

## A syntax error kills the entire site

One missing quote, one extra space, and every page on your domain returns a [500 Internal Server Error](/errors/500-internal-server-error/). The server refuses to process the file at all.

Check these three things before you save:

- Every `Redirect` line has three parts: the status, the old path, the new path.
- Every `RewriteRule` line has three parts: the pattern, the target, the flags in square brackets.
- There is no stray whitespace at the start of a line.

If you get a 500, rename `.htaccess` to `.htaccess.bak` through FTP or the web file manager. The site comes back. Then fix the line.

## Redirect rules in .htaccess fix real problems

Redirects fix [404 errors](/errors/404-not-found/) and preserve your traffic. They do not fix slow PHP processes, high inode counts, or the other resource limits on your free account. Each account gets 10 concurrent PHP processes and 30,000 files. A thousand redirect rules use none of those, which is the one good thing about them.

If you do not want to write these rules by hand, use the [.htaccess generator](/tools/htaccess-generator/) to produce the lines. Then put them in the right order and test with a 302. That is the whole job.

---

Content Website Platform (cwp.sg) operates the free hosting it writes about; see https://cwp.sg/about/ for the methodology and the commercial disclosure.
