Master Apache redirects for WordPress. Learn when to use 301 vs 302, fix redirect loops, and optimize .htaccess performance.
EN

Complete .htaccess Redirect Guide for WordPress (2026)

5.00 /5 - (30 votes )
Last verified: March 1, 2026
Experience: 19+ years experience
Table of Contents

Introduction to Apache mod_rewrite

The .htaccess file is one of the most powerful tools in a WordPress administrator’s arsenal. This configuration file allows you to override server settings at the directory level, giving you granular control over URL redirections, access restrictions, and performance optimizations.

What is mod_rewrite?

mod_rewrite is an Apache module that provides a rule-based rewriting engine to rewrite requested URLs on the fly. It’s the engine behind WordPress’s pretty permalinks and is essential for modern SEO-friendly URL structures.

Key Benefits:

  • SEO Preservation: Redirect old URLs to new ones without losing search rankings
  • User Experience: Ensure visitors always reach the correct content
  • Security: Force HTTPS and block malicious requests
  • Performance: Implement caching headers and compression

When to Use 301 vs 302 Redirects

Understanding HTTP status codes is crucial for proper SEO implementation:

Redirect TypeUse CaseSEO Impact
301 PermanentContent moved permanently, domain changes, HTTPS migrationPasses 90-99% link equity, search engines update index
302 FoundTemporary maintenance, A/B testing, short-term content movesNo link equity passed, original URL remains indexed
307 TemporaryStrict HTTP/1.1 temporary redirect, POST data preservationSame as 302 but preserves HTTP method
308 PermanentStrict HTTP/1.1 permanent redirect, POST data preservationSame as 301 but preserves HTTP method

Golden Rule: If the change is permanent, always use 301. Using 302 for permanent moves can significantly hurt your SEO rankings.


Common Redirect Scenarios

1. Single Page Redirects

The simplest form of redirection moves one specific URL to another:

# Redirect a single page (simple syntax)
Redirect 301 /old-page.html https://www.domain.com/new-page.html

# Alternative using RewriteRule
RewriteEngine on
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

When to use each:

  • Use Redirect 301 for simple, exact URL matches
  • Use RewriteRule when you need pattern matching or conditions

2. Entire Site Redirection

Moving your entire website to a new domain requires careful handling:

# Redirect entire site to new domain
Redirect 301 / https://www.newdomain.com/

# Preserve full URL structure
RewriteEngine on
RewriteBase /
RewriteRule (.*) https://www.newdomain.com/$1 [R=301,L]

Important: Always test with a few URLs first before implementing site-wide redirects.

3. Subfolder to Root (or vice versa)

Common when restructuring content:

# Redirect entire site to a subfolder
Redirect 301 / https://www.domain.com/subfolder/

# Redirect subfolder to another site
Redirect 301 /subfolder https://www.domain.com/

# Using RewriteRule with full path preservation
RewriteEngine on
RewriteRule ^subfolder/(.*)$ /$1 [R=301,L]

4. File Extension Changes

When migrating from .html to .php or implementing pretty permalinks:

# Redirect .html to .php
RedirectMatch 301 (.*)\.html$ https://www.domain.com$1.php

# Remove .php extension (make URLs cleaner)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

5. Force HTTPS (SSL)

Essential for security and SEO:

# Force HTTPS - Method 1 (simple)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Force HTTPS - Method 2 (with www handling)
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.domain.com/$1 [L,R=301]

6. Force www or non-www

Consistency in URL structure matters for SEO:

# Force www
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ https://www.domain.com/$1 [L,R=301]

# Force non-www (naked domain)
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.domain\.com [NC]
RewriteRule ^(.*)$ http://domain.com/$1 [L,R=301]

Advanced Rewrite Rules

Query String Redirects

Handling URLs with parameters requires special attention:

# Redirect specific query parameter
RewriteEngine on
RewriteCond %{QUERY_STRING} id=1
RewriteRule ^index.php$ /path-to-new-location/? [R=301,L]

# Redirect with query string preservation
RewriteEngine On
RewriteCond %{QUERY_STRING} ^category=([^&]+)
RewriteRule ^index.php$ /category/%1/? [R=301,L]

# Remove query strings entirely
RewriteEngine On
RewriteCond %{QUERY_STRING} .
RewriteRule ^$ /? [R=301,L]

Note: The trailing ? in the destination URL strips the original query string.

Pattern Matching with Regex

Regular expressions provide powerful pattern matching:

# Redirect date-based URLs
RewriteEngine On
RewriteRule ^blog/([0-9]{4})/([0-9]{2})/(.+)$ /news/$1/$2/$3 [R=301,L]

# Redirect with wildcards
RewriteEngine On
RewriteRule ^products/(.*)$ /shop/$1 [R=301,L]

# Multiple pattern matches
RewriteEngine On
RewriteRule ^(blog|news|articles)/(.+)$ /content/$2 [R=301,L]

Domain Change with Path Preservation

When migrating to a completely new domain:

# Old domain to new domain with full path
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.old-domain.com$
RewriteRule (.*)$ https://www.new-domain.com/$1 [R=301,L]

# With subdirectory adjustment
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/blog/(.*)$
RewriteRule ^(.*)$ https://www.newdomain.com/news/%1 [R=301,L]

Testing Redirects Safely

Before Going Live

  1. Use 302 Temporary First: Test with 302 redirects before making them permanent
  2. Check Redirect Chains: Ensure you’re not creating redirect loops
  3. Test Multiple Scenarios: Check with and without www, HTTP and HTTPS
  4. Validate with Tools: Use online redirect checkers

Testing Methods

# Using curl to check headers
curl -I http://yourdomain.com/old-page

# Follow redirects with curl
curl -L http://yourdomain.com/old-page

# Check specific status codes
curl -I -L http://yourdomain.com/old-page 2>&1 | grep HTTP

Online Testing Tools

  • Redirect Checker: httpstatus.io
  • HTTP Status: httpstatus.io
  • Google Search Console: Check for crawl errors after implementation

Troubleshooting Redirect Loops

Common Causes

  1. Circular References: Rule A redirects to B, Rule B redirects back to A
  2. Protocol Mismatches: HTTP rule conflicting with HTTPS forcing
  3. WWW Conflicts: www and non-www rules fighting each other
  4. WordPress Conflicts: Plugin redirects conflicting with .htaccess

Diagnosis Steps

# Add this temporarily to see what's happening
RewriteEngine On
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3

Note: This requires server-level access and should be removed after debugging.

Solutions

# Prevent loops by checking if already redirected
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# Specific protocol handling to avoid loops
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Performance Impact of .htaccess Rules

Understanding the Cost

Every RewriteRule adds processing overhead:

  • Simple Redirects: Minimal impact (< 1ms)
  • Complex Regex: Moderate impact (1-5ms per rule)
  • Multiple Conditions: Cumulative impact (5-20ms+)

Optimization Best Practices

  1. Order Matters: Place most frequently matched rules first
  2. Use Specific Patterns: More specific patterns are faster
  3. Limit Regex Complexity: Avoid greedy quantifiers where possible
  4. Consider Server-Level Config: For high-traffic sites, use httpd.conf instead
# Optimized ordering example
RewriteEngine On

# Most common redirects first
RewriteRule ^wp-admin$ /wp-admin/ [R=301,L]

# Then specific patterns
RewriteRule ^old-product/(.*)$ /shop/$1 [R=301,L]

# Generic patterns last
RewriteRule ^blog/(.*)$ /news/$1 [R=301,L]

Caching Considerations

# Enable mod_expires for better caching
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 month"
</IfModule>

# Enable compression
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css application/javascript
</IfModule>

WordPress-Specific Considerations

Integration with WordPress Rewrite Rules

WordPress uses its own rewrite rules in .htaccess. Always place custom rules before the WordPress block:

# BEGIN Custom Redirects
RewriteEngine On
# Your custom rules here
# END Custom Redirects

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Common WordPress Redirect Scenarios

# Redirect attachment pages to parent post
RewriteEngine On
RewriteRule ^attachment/(.*)$ / [R=301,L]

# Redirect author archives to homepage
RewriteEngine On
RewriteRule ^author/(.*)$ / [R=301,L]

# Redirect category archives to specific page
RewriteEngine On
RewriteRule ^category/old-category$ /new-section/ [R=301,L]

Security Considerations

Protecting Sensitive Files

# Block access to sensitive WordPress files
<FilesMatch "^\.">
  Order allow,deny
  Deny from all
</FilesMatch>

# Protect wp-config.php
<Files wp-config.php>
  order allow,deny
  deny from all
</Files>

# Block access to .htaccess itself
<Files .htaccess>
  order allow,deny
  deny from all
</Files>

Blocking Malicious Requests

# Block SQL injection attempts
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]

Complete Reference: Redirect Types

Simple Redirect Syntax

# Basic 301 redirect
Redirect 301 /old /new

# 302 temporary redirect
Redirect 302 /maintenance /temp-page

# Redirect with full URL
Redirect 301 /page http://example.com/new-page

RedirectMatch Syntax

# Pattern-based redirect
RedirectMatch 301 ^/blog/(.*)$ http://example.com/news/$1

# Case-insensitive
RedirectMatch 301 (?i)^/old-folder/(.*)$ /new-folder/$1

RewriteRule Syntax

# Basic structure
RewriteRule Pattern Substitution [Flags]

# Common flags:
# [R=301] - Permanent redirect
# [R=302] - Temporary redirect
# [L] - Last rule (stop processing)
# [NC] - No case (case-insensitive)
# [QSA] - Query string append
# [NE] - No escape

FAQ

Q: Why are my redirects not working? A: ‘Common causes include: mod_rewrite not enabled, .htaccess not allowed in Apache config, syntax errors, or conflicting rules. Check your Apache error logs for details.’

Q: How do I redirect without losing SEO value?

Q: Can I redirect based on user agent?

RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
RewriteRule ^(.*)$ /mobile-version/$1 [R=301,L]

Q: How do I fix “too many redirects” errors?

Q: Should I use plugins or .htaccess for redirects?

Q: How do I redirect a subdomain?

RewriteCond %{HTTP_HOST} ^subdomain\.domain\.com$ [NC]
RewriteRule ^(.*)$ https://www.domain.com/subfolder/$1 [R=301,L]

Q: Can I chain multiple redirects?


Summary Checklist

Before implementing redirects:

  • Test redirects with 302 before making them 301
  • Verify no redirect loops exist
  • Check mobile and desktop behavior
  • Test with both www and non-www URLs
  • Verify HTTPS enforcement if applicable
  • Monitor Google Search Console for crawl errors
  • Update internal links to point to new URLs
  • Create a backup of your .htaccess file

Remember: A well-planned redirect strategy preserves your SEO rankings and ensures a seamless user experience during site migrations or restructuring.


Advanced Techniques for 2026

NGINX Compatibility Considerations

While .htaccess is Apache-specific, understanding how rules translate to NGINX is crucial for developers working across platforms:

Apache (.htaccess) to NGINX Conversion:

Apache DirectiveNGINX Equivalent
Redirect 301 /old /newreturn 301 /new;
RewriteRule ^old$ /new [R=301,L]location = /old { return 301 /new; }
RewriteCond %{HTTPS} offif ($scheme != 'https')

NGINX server block example:

server {
    listen 80;
    server_name example.com;

    # Permanent redirect to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    # WordPress rewrite rules
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}

Edge Cases and Special Scenarios

1. Multilingual Site Redirects

# Redirect based on Accept-Language header
RewriteEngine On
RewriteCond %{HTTP:Accept-Language} ^de [NC]
RewriteRule ^$ /de/ [L,R=302]

RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteRule ^$ /fr/ [L,R=302]

2. Mobile Device Detection

# Detect mobile user agent
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|midp|mmp|mobile.+firefox|netfront|opera\ m(ob|in)i|palm\ (os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ ce|xda|xiino [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|l\ |nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/ [NC]
RewriteRule ^$ /mobile/ [L,R=302]

3. Time-Based Redirects

# Redirect during maintenance window
RewriteEngine On
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0800 [NC]
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1700 [NC]
RewriteRule ^$ /maintenance/ [L,R=302]

4. HTTP/HTTPS Detection for Load Balancers

# Handle X-Forwarded-Proto header from load balancers
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Debugging and Logging

Enable detailed rewrite logging:

# For Apache 2.4+
LogLevel alert rewrite:trace6

# Log to file
ErrorLog ${APACHE_LOG_DIR}/rewrite.log

Common debugging commands:

# Check Apache modules
apache2ctl -M | grep rewrite

# Test .htaccess syntax
apache2ctl configtest

# Check if mod_rewrite is enabled
a2enmod rewrite

# View Apache error logs
tail -f /var/log/apache2/error.log

Migration Checklist for Large Sites

When migrating a large WordPress site with thousands of redirects:

  1. Inventory Phase

    • Export all URLs from Google Analytics
    • Crawl existing site with Screaming Frog
    • Export all indexed pages from Google Search Console
    • Document all 404 errors
  2. Planning Phase

    • Map old URLs to new URLs
    • Group redirects by pattern
    • Prioritize high-traffic pages
    • Plan redirect chains to minimize hops
  3. Implementation Phase

    • Test redirects on staging environment
    • Implement in batches
    • Monitor server response times
    • Check for redirect loops
  4. Verification Phase

    • Use online redirect checkers
    • Monitor Search Console for crawl errors
    • Check server response times
    • Verify link equity transfer
  5. Cleanup Phase

    • Remove temporary 302 redirects (convert to 301)
    • Remove unnecessary rules
    • Document all redirects for future reference
    • Update XML sitemap with new URLs

WordPress Plugin Alternatives

For non-technical users or complex redirect management:

Redirection

  • Free, widely used
  • Supports regex patterns
  • 404 logging
  • Import/export functionality

Yoast SEO Premium

  • Built-in redirect manager
  • Automatic 404 monitoring
  • Seamless WordPress integration
  • Regex support

Safe Redirect Manager

  • WordPress.org plugin
  • Whitelist-based redirects
  • HTTP status code selection
  • Multisite compatible

Rank Math SEO

  • Comprehensive SEO suite
  • 301/302/307 redirects
  • 404 monitoring
  • 301 bulk import

Conclusion

Mastering .htaccess redirects is essential for any WordPress developer or site administrator. The key takeaways are:

  1. Always use 301 for permanent moves to preserve SEO value
  2. Test thoroughly before deployment using 302 redirects first
  3. Avoid redirect chains that create unnecessary hops
  4. Order rules logically with most specific patterns first
  5. Monitor performance as complex rules can impact page load times
  6. Document all redirects for future maintenance and troubleshooting

With the techniques and examples in this guide, you can confidently handle any redirect scenario, from simple page moves to complex multi-domain migrations.


WordPress-Specific .htaccess Optimizations

Default WordPress .htaccess Structure

WordPress generates a default .htaccess file when you enable pretty permalinks. Understanding its structure is crucial for adding custom rules:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Adding Custom Rules Without Breaking WordPress

When adding custom rules, always place them before the WordPress rules:

# BEGIN Custom Rules
Redirect 301 /old-page /new-page
# END Custom Rules

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Handling WordPress Multisite

WordPress Multisite requires additional configuration:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

Security Rules for .htaccess

Blocking Access to Sensitive Files

# Block access to wp-config.php
<files wp-config.php>
order allow,deny
deny from all
</files>

# Block access to .htaccess itself
<files ^\.htaccess>
order allow,deny
deny from all
</files>

# Block directory browsing
Options -Indexes

IP-Based Access Control

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} ^(.*)?wp-admin(.*)? [OR]
RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)?
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.100$
RewriteRule .* https://%{HTTP_HOST}/ [R=301,L]
</IfModule>

Performance Optimization with .htaccess

Browser Caching Headers

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
</IfModule>

# GZIP Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
</IfModule>

Troubleshooting Redirect Loops

Common causes:

  1. Conflicting rules
  2. Protocol mismatch (HTTP/HTTPS)
  3. Missing conditions
  4. WordPress conflicts

Debugging:

curl -I http://example.com/old-url

Migration Scenarios

HTTP to HTTPS Migration

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Domain Migration

RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain\.com$ [NC]
RewriteRule (.*)$ https://www.new-domain.com/$1 [R=301,L]

URL Structure Changes

RewriteEngine On
RewriteRule ^blog/([0-9]{4})/([0-9]{2})/(.+)$ /articles/$3 [R=301,L]

Advanced Techniques

Mobile Redirects

RewriteCond %{HTTP_USER_AGENT} (android|bb\d+|meego)|mobile|up\.browser [NC]
RewriteRule ^(.*)$ https://mobile.example.com/$1 [R=301,L]
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^https://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F]

Force Download Files

<FilesMatch "\.pdf$">
Header set Content-Disposition attachment
</FilesMatch>

FAQ

When to use Redirect vs RewriteRule?

  • Use Redirect 301 for simple, exact URL matches
  • Use RewriteRule for complex pattern matching

How to test redirects before permanent change?

Use 302 first:

RewriteRule ^old-page$ /new-page [R=302,L]

What causes 500 Internal Server Error?

  • Syntax errors
  • Invalid regex patterns
  • Conflicting rules causing loops

Additional Resources:

Additional Resources:

Article FAQ

Frequently Asked Questions

Practical answers to apply the topic in real execution.

SEO-ready GEO-ready AEO-ready 5 Q&A
What's the difference between Redirect 301 and RewriteRule?
Redirect 301 is simpler syntax for basic redirects. RewriteRule uses regex pattern matching and is more powerful for complex URL manipulations. Use Redirect for simple cases, RewriteRule for pattern-based redirects.
Why am I getting a redirect loop error?
Redirect loops occur when rules reference each other (A redirects to B, B redirects to A) or when protocol mismatches exist. Check for conflicting rules and use RewriteCond to prevent loops.
Do .htaccess redirects affect website speed?
Minimal impact for a few redirects. However, performance degrades with many RewriteRule directives because Apache processes them sequentially for every request. Consider implementing redirects at the server config level for high-traffic sites.
Should I use 301 or 302 redirect?
Use 301 for permanent changes (domain moves, HTTPS migration, permanent URL changes) - it passes 90-99% link equity. Use 302 only for temporary situations like maintenance or A/B testing.
How do I redirect with query strings?
Use RewriteCond %{QUERY_STRING} to match query strings, then RewriteRule with [R=301,L,QSD] flags. The QSD flag (Query String Discard) removes the original query string from the destination.

Need an FAQ tailored to your industry and market? We can build one aligned with your business goals.

Let’s discuss

Related Articles