Introduction: Why .htaccess Matters
The .htaccess file is one of the most powerful configuration tools available to web developers and site administrators running Apache servers. Short for "hypertext access," this small plain-text file controls how your server handles URL routing, redirects, security headers, caching, and access control -- all without touching the main server configuration.
Whether you are migrating a website to a new domain, enforcing HTTPS, cleaning up messy URLs for SEO, or setting up custom error pages, .htaccess redirects and rewrite rules are the standard solution. This guide covers everything from basic 301 redirects and 302 redirects to advanced mod_rewrite patterns, with copy-ready code examples you can use immediately.
What Is an .htaccess File?
An .htaccess file is a per-directory configuration file for the Apache HTTP Server. When Apache receives a request, it checks for .htaccess files in every directory along the path to the requested resource and applies the directives it finds. This makes .htaccess ideal for shared hosting environments where you do not have access to the main httpd.conf or apache2.conf files.
Key characteristics of the .htaccess file:
- Per-directory scope -- Rules apply to the directory containing the file and all subdirectories below it.
- No restart required -- Changes take effect immediately on the next request, unlike the main Apache config which requires a server restart.
- Cascading -- A child directory's .htaccess can override or extend rules from a parent directory.
- Requires AllowOverride -- The server's main config must have
AllowOverride All(or specific categories) enabled for .htaccess to work.
# Basic .htaccess file structure
# Lines starting with # are comments
# Enable the rewrite engine
RewriteEngine On
# Redirect rules go here
Redirect 301 /old-page.html /new-page.html
301 vs 302 Redirects: Permanent vs. Temporary
The HTTP specification defines several redirect status codes. The two most common are 301 (Moved Permanently) and 302 (Found / Temporary). Choosing the right one has significant implications for SEO, browser caching, and user experience.
| Feature | 301 (Permanent) | 302 (Temporary) |
|---|---|---|
| SEO link equity | Passes ~90-99% of link juice to the new URL | Does not transfer link equity; original URL keeps its ranking |
| Search engine indexing | Search engines replace the old URL with the new one in their index | Search engines keep the old URL indexed |
| Browser caching | Browsers cache the redirect permanently | Browsers check the redirect on every request |
| Use case | Domain migration, URL restructuring, HTTP to HTTPS | A/B testing, maintenance mode, seasonal promotions |
| .htaccess syntax | Redirect 301 or [R=301,L] |
Redirect 302 or [R=302,L] |
Rule of thumb: If the old URL will never come back, use a 301. If the old URL might return in the future, use a 302. When in doubt, start with a 302 -- you can always upgrade to a 301 later, but undoing a cached 301 in browsers and search engines is difficult.
Basic .htaccess Redirect Syntax
Apache provides three main directives for redirects, each with different capabilities:
1. The Redirect Directive
The simplest way to create a redirect. It maps one URL path to another:
# Syntax: Redirect [status] /old-path new-url
# 301 permanent redirect
Redirect 301 /old-page.html https://example.com/new-page.html
# 302 temporary redirect
Redirect 302 /promo.html https://example.com/summer-sale.html
# Redirect an entire directory
Redirect 301 /blog https://example.com/articles
2. The RedirectMatch Directive
Like Redirect, but uses regular expressions for pattern matching:
# Redirect all .html files to .php equivalents
RedirectMatch 301 ^/(.*)\.html$ https://example.com/$1.php
# Redirect all pages under /category/ to /topics/
RedirectMatch 301 ^/category/(.*)$ https://example.com/topics/$1
# Redirect any URL ending with a trailing slash (except root)
RedirectMatch 301 ^/(.+)/$ https://example.com/$1
3. The RewriteRule Directive (mod_rewrite)
The most powerful option. Requires mod_rewrite to be enabled and offers conditions, flags, and complex pattern matching:
RewriteEngine On
# Syntax: RewriteRule pattern substitution [flags]
# Redirect a single page
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
# Redirect with query string preservation
RewriteRule ^search$ /find [R=301,L,QSA]
Common .htaccess Redirect Examples
Here are the most frequently needed .htaccess redirect examples, each with copy-ready code:
Redirect a Single Page to a New URL
# Simple single-page redirect
Redirect 301 /about-us.html https://example.com/about
# Using RewriteRule
RewriteEngine On
RewriteRule ^about-us\.html$ /about [R=301,L]
Redirect an Entire Old Domain to a New Domain
# Place this in the OLD domain's .htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]
Redirect HTTP to HTTPS
# Force all traffic to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Redirect www to non-www (and Vice Versa)
# Redirect www to non-www (canonical)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Redirect non-www to www (alternative)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
Redirect All Pages to Homepage (Maintenance Mode)
# Redirect everything except the maintenance page itself
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^(.*)$ /maintenance.html [R=302,L]
Note the use of 302 for maintenance mode -- you want search engines to know this is temporary and to keep the original URLs indexed.
URL Rewriting with mod_rewrite
The mod_rewrite module is the engine behind advanced URL manipulation in Apache. It uses three core directives: RewriteEngine, RewriteCond, and RewriteRule.
RewriteEngine
Enables or disables the rewrite engine. Must appear before any RewriteRule or RewriteCond:
RewriteEngine On
RewriteCond (Conditions)
RewriteCond defines conditions that must be true for the following RewriteRule to execute. Common server variables include:
| Variable | Description | Example Value |
|---|---|---|
%{HTTP_HOST} |
The hostname from the request | www.example.com |
%{REQUEST_URI} |
The full request path | /blog/my-post.html |
%{HTTPS} |
Whether HTTPS is being used | on or off |
%{REQUEST_FILENAME} |
The full filesystem path of the requested file | /var/www/html/page.php |
%{QUERY_STRING} |
The query string portion of the URL | id=42&sort=date |
%{REMOTE_ADDR} |
The client's IP address | 192.168.1.100 |
RewriteRule Flags
Flags modify how a RewriteRule behaves. The most important ones are:
[R=301]-- Issue a 301 redirect (visible to the browser).[R=302]-- Issue a 302 redirect (temporary).[L]-- Last rule. Stop processing further rules after this one matches.[NC]-- No case. Makes the pattern case-insensitive.[QSA]-- Query String Append. Preserves the original query string in the redirect.[NE]-- No Escape. Prevents Apache from encoding special characters in the output URL.[P]-- Proxy. Internally proxies the request to the substitution URL (requires mod_proxy).
# Combine multiple flags with commas
RewriteRule ^old-path$ /new-path [R=301,L,NC]
# Preserve query strings when redirecting
RewriteRule ^search\.php$ /find [R=301,L,QSA]
# /search.php?q=test -> /find?q=test
Htaccess for SEO: Clean and Canonical URLs
Search engines treat example.com/page, example.com/page/, example.com/page.php, and www.example.com/page as four different URLs. Without proper .htaccess redirect rules, you risk splitting your SEO value across duplicate URLs. Here are the essential rules for SEO-friendly URLs:
Remove .php and .html Extensions
# Remove .php extension (serve /about instead of /about.php)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [L]
# Redirect requests with .php extension to the clean URL
RewriteCond %{THE_REQUEST} \s/(.+)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,L]
Enforce Trailing Slash Consistency
# Add trailing slash to all URLs (except files)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
# OR: Remove trailing slash from all URLs
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
Force a Single Canonical Domain
# Combined: force HTTPS + non-www (single canonical URL)
RewriteEngine On
# Step 1: Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Step 2: Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
When building these rules, you often need to URL-encode special characters in your redirect targets. Spaces, query parameters, and non-ASCII characters in URLs must be properly encoded for the redirect to work.
Performance and Caching Rules
Beyond redirects, the .htaccess file is commonly used to enable browser caching and compression, which significantly improve page load times:
Browser Caching with mod_expires
# Enable browser caching for static assets
<IfModule mod_expires.c>
ExpiresActive On
# Images: cache for 1 year
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# CSS and JavaScript: cache for 1 month
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Fonts: cache for 1 year
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# HTML: cache for 1 hour
ExpiresByType text/html "access plus 1 hour"
</IfModule>
GZIP Compression with mod_deflate
# Enable GZIP compression for text-based assets
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
</IfModule>
These caching and compression rules work alongside your minified assets. If you are serving minified CSS and HTML, combining them with proper caching headers ensures the fastest possible delivery to your visitors.
Common .htaccess Mistakes to Avoid
Even experienced developers run into these pitfalls when writing .htaccess rewrite rules:
- Redirect loops -- The most common mistake. If your HTTPS redirect rule does not check
RewriteCond %{HTTPS} off, it will redirect HTTPS requests to HTTPS again, creating an infinite loop. Always add conditions that exclude already-correct URLs. - Missing RewriteBase -- If your site runs in a subdirectory (e.g.,
example.com/myapp/), you needRewriteBase /myapp/at the top of your rules. Without it, rewrite paths resolve relative to the server root. - Forgetting the [L] flag -- Without
[L](Last), Apache continues processing subsequent rules after a match. This can cause unexpected rewrites or redirect chains. - Wrong rule order -- Apache processes .htaccess rules top to bottom. Place more specific rules before general catch-all rules. A broad
RewriteRule ^(.*)$at the top will swallow all requests before specific rules can match. - Testing with 301 redirects -- Browsers aggressively cache 301 redirects. During development, use 302 and only switch to 301 once you are confident the rule is correct. Clear your browser cache after changing a 301.
- Not escaping dots in regex -- In
RewriteRule, an unescaped dot matches any character. The patternexample.comalso matchesexampleXcom. Escape dots asexample\.com. - Conflicting with CMS rules -- WordPress, Laravel, and other frameworks ship with their own .htaccess rules. Adding custom rules in the wrong position can break CMS routing. Always add your rules before the CMS block or test carefully.
Frequently Asked Questions
What is the difference between a 301 and 302 redirect in .htaccess?
A 301 redirect is a permanent redirect that tells search engines the old URL has moved permanently and all link equity (SEO value) should transfer to the new URL. A 302 redirect is temporary, meaning the original URL may return in the future -- search engines keep the old URL indexed. Use 301 for permanent moves like domain changes, and 302 for temporary situations like A/B testing or maintenance pages.
How do I redirect HTTP to HTTPS using .htaccess?
Add these lines to your .htaccess file: RewriteEngine On, then RewriteCond %{HTTPS} off, then RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]. This checks if the connection is not HTTPS (RewriteCond %{HTTPS} off) and redirects all requests to the HTTPS version with a 301 permanent redirect. Make sure your SSL certificate is installed before enabling this rule.
Where should I place the .htaccess file?
The .htaccess file should be placed in the root directory of your website (the same directory as your index.php or index.html file). Apache reads .htaccess files on every request in the directory where the file is located and all subdirectories below it. You can also place additional .htaccess files in subdirectories to apply rules only to those sections of your site.
How do I fix a redirect loop in .htaccess?
Redirect loops occur when Rule A redirects to URL B, and Rule B redirects back to URL A. Common causes include: missing RewriteCond conditions that exclude already-rewritten URLs, conflicting rules for www and non-www, or HTTPS rules that conflict with server-level redirects. Fix loops by adding proper conditions (like RewriteCond %{HTTPS} off) before redirect rules and by using the [L] flag to stop rule processing after a match.
Can I remove .php or .html file extensions using .htaccess?
Yes. To remove the .php extension, add: RewriteEngine On, then RewriteCond %{REQUEST_FILENAME} !-d, then RewriteCond %{REQUEST_FILENAME}.php -f, then RewriteRule ^(.*)$ $1.php [L]. This checks if the requested path is not a directory, checks if adding .php would match a real file, and then internally rewrites the URL. Visitors see clean URLs like /about instead of /about.php while Apache serves the correct PHP file.
Conclusion
The .htaccess file is the Swiss Army knife of Apache web servers. With a handful of directives -- Redirect, RedirectMatch, RewriteCond, and RewriteRule -- you can handle virtually any URL routing scenario: 301 permanent redirects for domain migrations, 302 temporary redirects for maintenance, HTTP-to-HTTPS enforcement, www-to-non-www canonicalization, clean URL extensions, trailing slash consistency, and performance optimization through caching and compression.
The key to writing reliable .htaccess rules is understanding RewriteCond conditions (to prevent loops), using the correct flags ([R=301,L] for redirects, [L] for internal rewrites), and testing your regular expression patterns before deploying. Start with 302 during development, verify everything works, and then switch to 301 for production.
If you want to skip the manual syntax and generate .htaccess rules through a visual builder, try our free .htaccess Generator. It supports redirects, rewrite rules, security headers, caching, CORS, custom error pages, and template presets for WordPress, Laravel, static sites, and single-page applications -- with conflict detection and syntax-highlighted output.