Infrastructure & Networking

What is a .htaccess file?

An.htaccess file, hypertext access, is a directory-level configuration file used by the Apache web server to apply configuration directives to the directory in which it is placed and all subdirectories beneath it. Unlike Apache’s main server configuration file, httpd.conf or apache2.conf: which requires server administrator access and a server restart to apply changes an.htaccess file can be placed in any directory accessible to the web server and takes effect immediately, no server restart required.

The dot prefix in .htaccess follows Unix filesystem convention for hidden files, files whose names begin with a dot are not displayed by default in directory listings. This convention applies across Linux and macOS systems, the .htaccess file is hidden from ordinary directory browsing while remaining accessible to the Apache process. On Windows systems hidden files work differently but the Apache convention is maintained for cross-platform consistency.

.htaccess files are most widely used on shared hosting environments where users do not have access to the main server configuration and need directory-level control over redirects, URL rewriting, authentication, caching, and access control. The ability to configure redirects without server administrator privileges made.htaccess the dominant redirect implementation mechanism for the shared hosting era, and it remains widely used today despite the availability of more modern alternatives.

For redirect management.htaccess is historically significant, the Apache mod_rewrite module accessed through.htaccess provides powerful URL rewriting and redirect capabilities. Understanding.htaccess redirect syntax enables management of legacy hosting environments and interpretation of redirect configurations inherited from older web properties.

How.htaccess works

Apache processes.htaccess files as part of handling each request, reading the file from the directory hierarchy and applying its directives before processing the request.

Processing on every request: Apache reads and processes.htaccess files for every request, not just on configuration changes. When a request arrives Apache traverses the directory path from the document root to the requested file, reading each.htaccess file encountered along the way and applying its directives. A request for https://example.com/blog/post/page.html causes Apache to check for.htaccess files in the root directory, the blog directory, and the post directory, applying all directives found in each.

This per-request processing has a performance cost, reading and parsing.htaccess files adds overhead to every request. For high-traffic production servers this overhead is significant, Apache documentation recommends disabling.htaccess support, setting AllowOverride None in the main configuration, and moving all directives to the main configuration file for better performance. On shared hosting where per-user configuration is necessary.htaccess overhead is accepted as the cost of the flexibility it provides.

AllowOverride directive: the Apache main configuration controls whether.htaccess files are permitted and which directives they may contain through the AllowOverride directive. AllowOverride None disables.htaccess processing entirely. AllowOverride All permits all directives. AllowOverride FileInfo AuthConfig permits specific directive groups. Shared hosting providers typically set AllowOverride All: enabling users to configure redirects and other settings. Managed hosting and VPS environments often restrict.htaccess permissions for security and performance.

Directive inheritance: directives in.htaccess files apply to the directory containing the file and all subdirectories. A redirect rule in /public_html/.htaccess applies to all URLs on the site. A rule in /public_html/blog/.htaccess applies only to URLs under /blog/. Directives in subdirectory.htaccess files can override or extend directives from parent directory.htaccess files, providing directory-specific configuration within a broader site configuration.

.htaccess redirect syntax

.htaccess provides two primary mechanisms for implementing redirects, the Redirect directive for simple redirects and the mod_rewrite module for complex URL rewriting and pattern-based redirects.

The Redirect directive: the simplest.htaccess redirect mechanism. The Redirect directive maps a URL path to a new destination, returning the appropriate redirect status code.

# 301 permanent redirect
Redirect 301 /old-page https://example.com/new-page

# 302 temporary redirect
Redirect 302 /temp-page https://example.com/destination

# Permanent redirect (keyword shorthand for 301)
Redirect permanent /old-page https://example.com/new-page

# Temporary redirect (keyword shorthand for 302)
Redirect temp /old-page https://example.com/destination
# 301 permanent redirect
Redirect 301 /old-page https://example.com/new-page

# 302 temporary redirect
Redirect 302 /temp-page https://example.com/destination

# Permanent redirect (keyword shorthand for 301)
Redirect permanent /old-page https://example.com/new-page

# Temporary redirect (keyword shorthand for 302)
Redirect temp /old-page https://example.com/destination
# 301 permanent redirect
Redirect 301 /old-page https://example.com/new-page

# 302 temporary redirect
Redirect 302 /temp-page https://example.com/destination

# Permanent redirect (keyword shorthand for 301)
Redirect permanent /old-page https://example.com/new-page

# Temporary redirect (keyword shorthand for 302)
Redirect temp /old-page https://example.com/destination

The Redirect directive performs prefix matching, Redirect 301 /old/ matches any URL beginning with /old/ and appends the remaining path to the destination. Redirect 301 /old/ https://example.com/new/ redirects /old/page to https://example.com/new/page.

RedirectMatch directive: like Redirect but with regular expression pattern matching rather than prefix matching. Enables more sophisticated redirect patterns:

# Redirect any URL ending in .html to the equivalent without extension
RedirectMatch 301 ^(.*)\.html$ $1

# Redirect old category URLs to new format
RedirectMatch 301 ^/category/([^/]+)$ /topics/$1
# Redirect any URL ending in .html to the equivalent without extension
RedirectMatch 301 ^(.*)\.html$ $1

# Redirect old category URLs to new format
RedirectMatch 301 ^/category/([^/]+)$ /topics/$1
# Redirect any URL ending in .html to the equivalent without extension
RedirectMatch 301 ^(.*)\.html$ $1

# Redirect old category URLs to new format
RedirectMatch 301 ^/category/([^/]+)$ /topics/$1

mod_rewrite, the powerful option: Apache’s URL rewriting module provides comprehensive redirect and rewriting capabilities through RewriteRule directives. mod_rewrite is more powerful than Redirect: supporting conditions, multiple rule interactions, and complex transformations, but more complex to configure correctly.

Enabling mod_rewrite in.htaccess requires the RewriteEngine On directive:

RewriteEngine On
RewriteEngine On
RewriteEngine On

Basic mod_rewrite redirect: a simple path redirect using mod_rewrite:

RewriteEngine On
RewriteRule ^old-page$ /new-page [R=301,L]
RewriteEngine On
RewriteRule ^old-page$ /new-page [R=301,L]
RewriteEngine On
RewriteRule ^old-page$ /new-page [R=301,L]

The pattern ^old-page$ matches the path old-page exactly, anchors ^ and $ prevent partial matches. The destination /new-page is the redirect target. The flags [R=301,L] specify a 301 redirect, R=301: and stop processing further rules, L for last.

RewriteCond, conditional rewriting: RewriteCond directives add conditions that must be satisfied before the following RewriteRule fires. Conditions can test server variables, HTTP_HOST, HTTPS, REQUEST_URI, enabling context-sensitive redirect logic:

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

# Redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

# Redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Redirect HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

# Redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Redirect HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

# Redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

mod_rewrite flags: RewriteRule flags modify how rules behave. The most important flags for redirect management:

R=301: return a 301 permanent redirect. R=302 for temporary redirect. L: last rule, stop processing further rules after this one matches. NC: no case, case-insensitive matching. QSA: query string append, preserve the original query string in the destination. NE: no escape, do not URL-encode special characters in the output.

Common.htaccess redirect patterns

HTTP to HTTPS redirect: the universal HTTPS enforcement redirect:

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

www to non-www canonical redirect:

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

Non-www to www canonical redirect:

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

Trailing slash removal:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]

Domain migration, redirect all traffic to new domain:

RewriteEngine On
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]
RewriteEngine On
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]
RewriteEngine On
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]

Redirect specific file extensions: redirecting.html URLs to clean URLs:

RewriteEngine On
RewriteRule ^([^.]+)\.html$ /$1 [R=301,L]
RewriteEngine On
RewriteRule ^([^.]+)\.html$ /$1 [R=301,L]
RewriteEngine On
RewriteRule ^([^.]+)\.html$ /$1 [R=301,L]

Custom 404 error page:

ErrorDocument 404 /404.html
ErrorDocument 404 /404.html
ErrorDocument 404 /404.html

.htaccess security configuration

Beyond redirects.htaccess provides security configuration capabilities, protecting sensitive files and directories.

Blocking access to sensitive files: preventing direct access to configuration files, backup files, and other sensitive resources:

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

# Block access to backup files
<FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
    Order allow,deny
    Deny from all
</FilesMatch>
# Block access to .htaccess itself
<Files .htaccess>
    Order allow,deny
    Deny from all
</Files>

# Block access to backup files
<FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
    Order allow,deny
    Deny from all
</FilesMatch>
# Block access to .htaccess itself
<Files .htaccess>
    Order allow,deny
    Deny from all
</Files>

# Block access to backup files
<FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
    Order allow,deny
    Deny from all
</FilesMatch>

Directory listing prevention: preventing Apache from displaying directory contents when no index file is present:

Options -Indexes
Options -Indexes
Options -Indexes

Security headers: adding HTTP security headers through.htaccess:

# HSTS header
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# Content Security Policy
Header always set Content-Security-Policy "default-src 'self'"

# X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"
# HSTS header
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# Content Security Policy
Header always set Content-Security-Policy "default-src 'self'"

# X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"
# HSTS header
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# Content Security Policy
Header always set Content-Security-Policy "default-src 'self'"

# X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"

The mod_headers Apache module must be enabled for Header directives to work.

.htaccess limitations and alternatives

.htaccess is widely used but has limitations that make alternatives preferable in many production contexts.

Performance overhead: per-request.htaccess processing adds latency, Apache reads and parses.htaccess files for every request. High-traffic production servers should move.htaccess directives to the main server configuration, AllowOverride None: eliminating per-request file I/O. Moving.htaccess content to the main configuration provides equivalent functionality without the performance cost.

Limited to Apache:.htaccess is Apache-specific. Nginx, a widely used alternative to Apache, does not support.htaccess files. Nginx configuration is defined in nginx.conf and server block configuration files, more performant than.htaccess but requiring server administrator access. Sites migrating from Apache shared hosting to Nginx VPS hosting must convert.htaccess directives to Nginx configuration syntax.

No management interface:.htaccess redirect rules are plain text in a file, there is no management interface, no validation, no analytics, and no monitoring. Managing large numbers of redirects through.htaccess requires careful file editing and manual validation. Redirect management platforms provide interfaces, validation, analytics, and monitoring that.htaccess cannot.

Limited to server-level execution:.htaccess redirects execute on the origin server, not at the edge. All redirect requests travel to the origin before receiving redirect responses. Edge-based redirect platforms serve redirects from edge nodes near users, faster redirect responses and lower origin load than.htaccess-based redirects.

Related terms

Related terms

Ready to keep every link alive?

Ready to keep every link alive?

Ready to keep every link alive?