If you've ever migrated a site, changed a URL structure, or pushed a WordPress site to HTTPS — you've dealt with.htaccess` redirects. And if you've ever broken your site by putting the wrong code in that file, you know how unforgiving it can be.
This is the guide I wish I'd had. No fluff — just what the redirect codes actually mean, when to use each one, the real Apache syntax that works, and a free tool so you never have to write these rules by hand again.
What is .htaccess?
.htaccess (Hypertext Access) is a directory-level configuration file for Apache web servers. Place it in your site's root directory and it controls how the server handles requests — redirects, rewrites, password protection, custom error pages, caching rules, and more.
Most shared hosting (Hostinger, Bluehost, SiteGround, GoDaddy) and CMS platforms (WordPress, Joomla, Magento) run on Apache, making .htaccess the go-to method for managing redirects without touching httpd.conf directly.
One important rule: a single syntax error in .htaccess causes a 500 Internal Server Error across your entire site. Always back up the file before editing.
The 4 Redirect Status Codes — What They Actually Mean
301 — Permanent Redirect (use this 90% of the time)
apache
Redirect 301 /old-page.html https://example.com/new-page
Tells search engines: "This page has moved forever." Google transfers nearly all ranking power (link equity) from the old URL to the new one. Use 301 for:
- Permanent page moves
- Domain migrations
- HTTP → HTTPS upgrades
- www → non-www consolidation (or vice versa)
- Cleaning up old URLs you're deleting
SEO impact: Passes link equity. Old rankings transfer to the new URL, usually within a few weeks.
302 — Temporary Redirect
apache
Redirect 302 /sale https://example.com/summer-sale-2025
Tells search engines: "The content is temporarily somewhere else — keep the original URL in your index." Google retains the original URL's value rather than transferring it.
Use 302 for:
- Maintenance pages ("We'll be back in 2 hours")
- A/B testing landing pages
- Seasonal redirects you'll reverse later
Common mistake: Using 302 when you mean 301. Many developers default to 302 out of caution, but if the move is permanent, you're actively harming your SEO by not using 301.
307 — Temporary Redirect (Strict)
Similar to 302, but with one key difference: it preserves the HTTP method. If the original request was a POST, the redirected request must also be POST. Relevant for form submissions and API endpoints.
Use 307 when you have a temporary redirect that involves form data or non-GET requests and you need the method preserved exactly.
303 — See Other
apache
Redirect 303 /form-submitted https://example.com/thank-you
Specifically designed for post-redirect-get (PRG) patterns. After a form submission (POST), redirect the user to a confirmation page (GET) so refreshing doesn't resubmit the form. This is correct UX, not just an SEO consideration.
Real .htaccess Examples You Can Use Today
Force HTTPS (HTTP → HTTPS)
apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
www to non-www
apache
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
non-www to www
apache
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Redirect a single page
apache
Redirect 301 /old-about.html https://example.com/about
Redirect an entire old directory
apache
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1
Remove /index.html from URLs
apache
RewriteCond %{THE_REQUEST} /index\.html[\s?] [NC]
RewriteRule ^(.*)index\.html$ /$1 [R=301,L]
Redirect old domain to new domain (full site migration)
apache
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain\.com$ [NC]
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]
The Flags Explained
Those cryptic flags at the end of RewriteRule lines actually matter:
| Flag | Meaning |
|---|---|
R=301 |
Respond with a 301 redirect |
R=302 |
Respond with a 302 redirect |
L |
Last rule — stop processing after this |
NC |
Case-insensitive match |
NE |
Don't escape special characters in the output |
QSA |
Append query string from original request |
The most common combination is [R=301,L] — permanent redirect, stop processing.
Common Mistakes That Break Sites
1. Redirect chains
A redirects to B, B redirects to C. Each hop adds latency, and Google loses some link equity at each step. Always redirect A directly to C.
2. Redirect loops
A redirects to B, B redirects to A. Site becomes inaccessible. Usually happens when the HTTPS redirect condition is missing and catches the HTTPS request too.
3. Placing rules inside the WordPress block
WordPress adds its own .htaccess block. Putting your rules inside it means they get overwritten on the next WordPress update. Place custom rules above the WordPress block.
4. Using 302 when you mean 301
If the move is permanent, use 301. A 302 tells Google to keep ranking the old URL, which is actively unhelpful when you want traffic on the new one.
5. Not testing after deployment
Use an HTTP header checker (curl or a browser extension) to confirm the redirect returns the right status code and destination. Don't assume it works.
Skip Writing Rules by Hand
Writing .htaccess redirect rules manually is error-prone, especially when you're managing multiple redirects across a site migration. One misplaced character breaks everything.
I've been using OurToolkit's free HTACCESS Redirect Generator — you enter the old URL, new URL, and select the redirect type, and it generates the correct Apache code instantly. Supports 301, 302, 303, and 307, with real code examples and explanations of when to use each.
No account, no limits, works in your browser.
How to Access and Edit Your .htaccess File
Via FTP (FileZilla or similar) — Connect to your server, navigate to
public_html, and look for.htaccess. You may need to enable "show hidden files" — the dot prefix makes it hidden by default.Via cPanel File Manager — Go to cPanel → File Manager →
public_html→ Settings → check "Show Hidden Files."Via SSH —
nano /var/www/html/.htaccess
If the file doesn't exist, create a plain text file named .htaccess (no file extension) and upload it to your root directory.
After Adding Redirects
- Clear your browser cache before testing — cached responses will show the old behaviour
-
Test with curl:
curl -I https://example.com/old-pageand check theLocation:header - Update your XML sitemap — remove the old URLs, add the new ones, resubmit in Google Search Console
- Check Search Console a few weeks later — the "URL Inspection" tool shows whether Google has indexed the new URL
Redirects are one of those things that seem simple but have real consequences when done wrong. Get them right the first time and you'll never have to chase mysterious traffic drops after a site migration.
What .htaccess redirect situations have you run into? Drop them in the comments — happy to help work through the right approach.
`
Top comments (0)