Tutorial

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.

Ben Johnson · last checked 2026-09-21 · 4 min read

TL;DR
  • 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.

# 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.

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.

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:

RewriteEngine On

Then write the pattern and the target.

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:

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:

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:

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:

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:

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:

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. 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 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 to produce the lines. Then put them in the right order and test with a 302. That is the whole job.