.htaccess Redirect Cookbook: Every RewriteRule You Actually Need
If you're on Apache, .htaccess is where redirects live. This cookbook covers every pattern you'll actually need — no filler, just the rules, what they do, and the gotchas.
Your three tools
Redirect(mod_alias) — simple path-to-path redirects, no regex.RedirectMatch(mod_alias) — path-to-path with regex.RewriteRule(mod_rewrite) — everything else, including conditional logic.
Rule of thumb: use Redirect for simple cases, RewriteRule for anything touching query strings, hosts, or conditions.
Simple redirects with Redirect
# Permanent redirect for a single page
Redirect 301 /old-page.html /new-page.html
# Permanent redirect for an entire directory
Redirect 301 /old-docs /docs
# Temporary (302)
Redirect 302 /sale /promo
# Gone (410)
Redirect gone /discontinued.htmlThe Redirect directive does a prefix match. Redirect 301 /old-docs /docs will redirect /old-docs/foo to /docs/foo automatically.
Pattern matching with RedirectMatch
# Redirect all .html to clean URLs
RedirectMatch 301 ^/(.*)\.html$ /$1
# Redirect numbered blog posts to slug-based URLs
RedirectMatch 301 ^/post/(\d+)$ /blog/archive/$1RewriteRule: the heavy lifter
Any time you need to inspect the host, query string, headers, or environment, use RewriteRule with RewriteCond.
RewriteEngine On
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Redirect non-www to www (pick one and stick with it)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]Flags you need to know
- R=301 — send a 301 response (use
R=302for temporary) - L — last rule; stop processing further rewrites
- NC — case-insensitive match
- QSA — append original query string
- QSD — discard original query string
Common cookbook entries
HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]Behind a load balancer or Cloudflare Flexible SSL, %{HTTPS} is always off. Use:
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]Redirect based on query string
# /search?q=foo -> /search/foo
RewriteCond %{QUERY_STRING} ^q=([^&]+)$
RewriteRule ^search$ /search/%1? [R=301,L]The trailing ? in the target removes the original query string.
Redirect by user agent
RewriteCond %{HTTP_USER_AGENT} (iPhone|Android) [NC]
RewriteRule ^/?$ /mobile [R=302,L]Bulk redirects from a mapping file
# In httpd.conf (not .htaccess):
RewriteMap redirects txt:/etc/apache2/redirects.txt
# Then in .htaccess:
RewriteCond ${redirects:$1} !=""
RewriteRule ^(.*)$ ${redirects:$1} [R=301,L]Gotchas
- Order matters. Rules are evaluated top-down. Put the most specific rules first, and use the
Lflag to stop processing. - Rewrite loops. If your rule matches its own output, you'll get an infinite loop and an HTTP 500. Use
RewriteCondto exclude the target. - .htaccess is slow. Apache re-reads it on every request. For high-traffic sites, put rules in the main config.
- Backticks and dollar signs. In regex,
$1is a back-reference; inRewriteCondpatterns,%1refers to the condition's capture groups. - Escaping dots. Always write
example\.com, notexample.com, in regex patterns — unescaped dots match any character.
Debugging a .htaccess that's misbehaving
- Add
LogLevel alert rewrite:trace6to your vhost config (not .htaccess) to dump rewrite traces to the error log. tail -f /var/log/apache2/error.logand make a request.- Test with
curl -I -Lto follow the whole chain. - Remember to turn the trace logging back off in production — it's verbose.
Wrap-up
For anything more complex than a single page redirect, reach for RewriteRule. Keep rules ordered from specific to general, always set R=301 or R=302 explicitly, and test the full chain before deploying. After any change, verify with Redirect Check to make sure you haven't introduced a loop or a stray 302 where you meant 301.
Verifique seus redirecionamentos agora
Não deixe redirecionamentos ruins prejudicarem seu SEO. Use nossa ferramenta gratuita para auditar seus links instantaneamente.
Artigos Relacionados
Ver todos os posts arrow_forwardHow to Fix ERR_TOO_MANY_REDIRECTS: A No-BS Troubleshooting Guide
Stuck in a redirect loop? Learn how to diagnose and fix the ERR_TOO_MANY_REDIRECTS error with practical solutions for WordPress, Cloudflare, Apache, and Nginx.
Setting Up Redirects in Cloudflare: A No-Nonsense Guide for 2025
Master Cloudflare redirects with this practical guide. Learn Single Redirects, Bulk Redirects, common pitfalls, and real troubleshooting tips that actually work.
Mobile-First Redirects: How to Optimize for Core Web Vitals in 2025
Learn how redirects impact Core Web Vitals and mobile performance. Practical strategies to maintain LCP, INP, and CLS scores during redirects.