This site contains affiliate links — we may earn a commission if you sign up through them. Details

.htaccess Guide 2026: What It Does and the Most Useful Code Examples

คู่มือ .htaccess 2026 ทำอะไรได้บ้าง ตัวอย่าง Code ที่ใช้บ่อย

.htaccess Guide 2026: What It Does and the Most Useful Code Examples

What Is .htaccess and How Does It Work on Apache

The .htaccess file (short for Hypertext Access) is a directory-level configuration file used by Apache Web Server. It allows website owners to modify Apache's behavior on a per-directory basis without needing access to the main server configuration file (httpd.conf) and without requiring a server restart.

The filename begins with a dot (.htaccess), making it a hidden file on Unix/Linux systems. Apache reads this file on every incoming HTTP request, traversing the directory path from the root down to the requested file's location. This means changes take effect immediately — no server reload needed.

The key prerequisite is the AllowOverride directive in httpd.conf, which must be set by the server administrator. AllowOverride All enables the full range of .htaccess directives. Most shared hosting providers enable this by default, which is why .htaccess is so widely used on shared environments.

What .htaccess can do covers a wide spectrum: URL redirection and rewriting, enforcing HTTPS, password-protecting directories, blocking IP addresses, setting cache headers, defining custom error pages, preventing image hotlinking, creating pretty (SEO-friendly) URLs, and even setting per-directory PHP configuration values via php_value.

To create an .htaccess file, simply create a plain text file named exactly .htaccess (leading dot, no extension) and place it in your website's root directory or any subdirectory you want to control. Rules in a subdirectory apply only within that directory and its children — they do not propagate upward.

# Basic .htaccess starter — enable mod_rewrite
Options +FollowSymLinks
RewriteEngine On

# Set the default index file
DirectoryIndex index.php index.html index.htm

Important: .htaccess is exclusive to Apache. If your hosting uses Nginx (increasingly common for high-traffic sites) or IIS on Windows, .htaccess will have no effect. LiteSpeed Web Server, used by many cPanel hosts, does support .htaccess since it is Apache-compatible by design.

URL Redirects and 301 Redirect with .htaccess

Redirecting URLs via .htaccess is one of the most common use cases. Whether you are moving a page to a new URL, migrating a site to a new domain, or cleaning up old URL structures, .htaccess gives you full control with just a few lines of configuration.

A 301 Redirect (Permanent) signals to search engines that the URL has moved permanently. Google transfers the original page's link equity (ranking power) to the destination URL and updates its index. Use this for permanent URL changes, domain migrations, and structural redesigns.

A 302 Redirect (Temporary) tells search engines to keep the original URL in the index and not to transfer ranking signals. Use this for A/B tests, short-term promotional redirects, or maintenance pages where the original URL will return.

# Simple 301 redirect — single page (permanent)
Redirect 301 /old-page.html /new-page.html

# Temporary 302 redirect
Redirect 302 /promo /sale

# Redirect an entire directory
Redirect 301 /blog/ /articles/

# Redirect to an external domain
Redirect 301 /partner https://example.com/partner

# Flexible 301 with mod_rewrite (supports regex)
RewriteEngine On
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

# Redirect all URLs under /products/ to /shop/
RewriteRule ^products/(.*)$ /shop/$1 [R=301,L]

# Redirect a URL with a specific query string
RewriteCond %{QUERY_STRING} ^id=123$
RewriteRule ^page\.php$ /new-page.html? [R=301,L]

Watch out for redirect chains and loops. A chain (A → B → C) adds latency and can confuse crawlers; a loop (A → B → A) produces a "Too many redirects" browser error and makes the page completely inaccessible. Always test redirects with a tool such as Redirect Checker or your browser's DevTools Network tab before going live.

The [L] flag means "Last" — stop processing further rules once this one matches. The [R=301] flag issues a 301 response. Combining them as [R=301,L] is the standard pattern for permanent mod_rewrite redirects.

Forcing HTTPS and www Redirects with .htaccess

As of 2026, serving your site over HTTPS is a non-negotiable baseline. Google uses HTTPS as a ranking factor, and browsers like Chrome mark all HTTP pages with a "Not Secure" warning that visibly erodes user trust. If your hosting includes a free SSL certificate (most do via Let's Encrypt), .htaccess is the simplest way to enforce the redirect.

Beyond HTTPS, you need to pick one canonical form of your domain — https://example.com vs https://www.example.com — and redirect the other variant. Both versions resolving to the same content creates a duplicate content issue that splits your SEO signals.

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

# Force HTTPS + redirect www → non-www (recommended combo)
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

# Or split into two explicit rules for clarity:
# Step 1: Enforce HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Step 2: Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

# Alternatively, redirect non-www → www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

If your site sits behind Cloudflare or another reverse proxy that terminates SSL before the request reaches Apache, the %{HTTPS} variable may always read "off" even when the visitor is using HTTPS. In that case, check the forwarded proto header instead:

# For sites behind Cloudflare / load balancer
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Once HTTPS is enforced, add an HSTS header to tell browsers to always use HTTPS even if the user types "http://" — bypassing the redirect entirely on future visits:

# Add HSTS header (1-year max-age)
<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Protecting Files and Directories with .htaccess

Security through .htaccess operates at several levels: password-protecting admin areas, denying direct access to sensitive files (configuration files, backups, logs), and disabling directory listing that would otherwise expose your file structure to anyone who visits a folder without an index file.

Password-protecting a directory requires first creating an .htpasswd file using the htpasswd command-line tool or an online generator. Store .htpasswd outside your web root for extra security:

# Password-protect a directory with HTTP Basic Auth
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /home/user/private/.htpasswd
Require valid-user

# Allow only a specific user from .htpasswd
Require user admin

Blocking direct access to sensitive file types prevents visitors from downloading your configuration files, SQL dumps, or log files directly from a browser:

# Block access to sensitive file extensions
<FilesMatch "\.(env|sql|log|bak|config|ini|sh)$">
    Require all denied
</FilesMatch>

# Protect .htaccess and .htpasswd from being read
<FilesMatch "^\.ht">
    Require all denied
</FilesMatch>

# Block PHP execution inside uploads folder
<Directory /var/www/html/uploads>
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>
</Directory>

Disabling directory listing prevents Apache from showing a file index when no index.html or index.php exists in a folder:

# Disable directory listing site-wide
Options -Indexes

# Restrict admin file to a specific IP
<Files "admin.php">
    Require ip 203.150.100.50
    Require ip 192.168.1.0/24
</Files>

These .htaccess protections are a useful first line of defense, but they should be combined with strong passwords, regular CMS/plugin updates, and ideally a Web Application Firewall (WAF) for comprehensive security coverage.

Browser Caching and Gzip Compression for Speed

Configuring browser caching and Gzip compression via .htaccess is one of the highest-impact, lowest-effort performance optimizations available on Apache hosting. Together, they can dramatically improve your PageSpeed Insights score and Core Web Vitals without any code changes.

Gzip/Deflate Compression reduces the size of text-based assets (HTML, CSS, JavaScript, JSON) by 60–80% before they are sent over the network. This is especially impactful for visitors on slower mobile connections:

# Enable Gzip compression via mod_deflate
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE image/svg+xml
    AddOutputFilterByType DEFLATE font/woff2

    # Skip old browsers with known Gzip issues
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
</IfModule>

Browser Caching with mod_expires instructs browsers to store static assets locally, reducing HTTP requests on repeat visits:

<IfModule mod_expires.c>
    ExpiresActive On

    # Images — 1 year (rarely change)
    ExpiresByType image/jpeg  "access plus 1 year"
    ExpiresByType image/png   "access plus 1 year"
    ExpiresByType image/webp  "access plus 1 year"
    ExpiresByType image/gif   "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"

    # Fonts — 1 year
    ExpiresByType font/woff2  "access plus 1 year"
    ExpiresByType font/woff   "access plus 1 year"

    # CSS/JS — 1 month (updated more often)
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"

    # HTML — 1 hour (content changes frequently)
    ExpiresByType text/html "access plus 1 hour"

    ExpiresDefault "access plus 1 week"
</IfModule>

# Add explicit Cache-Control headers
<IfModule mod_headers.c>
    <FilesMatch "\.(css|js|jpg|jpeg|png|gif|webp|ico|woff|woff2)$">
        Header set Cache-Control "max-age=2592000, public"
    </FilesMatch>
    <FilesMatch "\.html$">
        Header set Cache-Control "max-age=3600, public, must-revalidate"
    </FilesMatch>
</IfModule>

One pitfall with long cache durations is cache busting: if you update a CSS or JS file but keep the same filename, visitors will continue to see the old cached version. Solve this by appending a version query string (style.css?v=2.1) or using a file hash in the filename (style.abc123.css).

Setting Up Custom Error Pages

Custom error pages replace Apache's default plain-text error screens with branded, user-friendly pages that help visitors find what they are looking for even when something goes wrong. A well-designed 404 page can recover a significant portion of would-be lost traffic.

The most important HTTP error codes to handle are: 404 (Not Found — the URL doesn't exist), 403 (Forbidden — access is not allowed), 500 (Internal Server Error — a server-side problem), and 503 (Service Unavailable — server is overloaded or down for maintenance).

# Define custom error pages
ErrorDocument 400 /errors/400.html
ErrorDocument 401 /errors/401.html
ErrorDocument 403 /errors/403.html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ErrorDocument 503 /errors/503.html

# Or redirect to a full URL
ErrorDocument 404 https://example.com/not-found.html

# Inline short message (useful for quick testing)
ErrorDocument 403 "Access Denied — please contact the site administrator"

# Maintenance mode: redirect all traffic to maintenance page
# (except your own IP)
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^203\.150\.100\.50$
RewriteCond %{REQUEST_URI} !/maintenance.html$
RewriteRule ^(.*)$ /maintenance.html [R=302,L]

A good 404 page should include: your site navigation, a search box, links to popular pages, and a short apology explaining what happened. Monitor your 404 error log regularly — a spike in 404s often indicates broken internal links or a migration that missed some URL mappings.

Your 500 error page deserves special attention: it must be a completely static HTML file with no PHP or database dependencies, since 500 errors often occur when PHP or the database is failing. A 500 page that itself depends on PHP will show a blank screen — the worst possible outcome.

Blocking IP Addresses and Preventing Hotlinking

IP blocking via .htaccess lets you cut off specific addresses or entire subnets from accessing your site — useful for stopping brute-force attackers, blocking aggressive scrapers, or restricting admin pages to office IPs only. Hotlink protection prevents other websites from embedding your images directly, which would consume your server's bandwidth without any benefit to you.

Blocking IPs in Apache 2.4+ (the version in use on virtually all modern hosting):

# Block a single IP address
Require not ip 192.168.1.100

# Block multiple IP addresses
<RequireAll>
    Require all granted
    Require not ip 192.168.1.100
    Require not ip 10.0.0.5
    Require not ip 203.0.113.25
</RequireAll>

# Block an entire /24 subnet (256 addresses)
Require not ip 192.168.1

# Allow only specific IPs (deny everyone else)
Require ip 203.150.100.50
Require ip 192.168.0.0/16

# Alternative: block with mod_rewrite (works on older Apache too)
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.100$
RewriteRule ^ - [F,L]

Preventing hotlinking of your images from external sites:

# Block image hotlinking — show a placeholder instead
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg)$ /images/hotlink-forbidden.png [NC,L]

# Or return a 403 Forbidden response
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,NC,L]

# Allow trusted partner domains
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?partner\.com [NC]
RewriteRule \.(jpg|png|gif)$ /403.png [NC,L]

One caveat: strict Referer checking can block images when users open them directly in a new tab (blank Referer) or when privacy-focused browsers suppress the Referer header entirely. Test thoroughly to ensure the rule does not break image display on your own pages.

Common Pitfalls and How to Debug .htaccess

A single syntax error in .htaccess causes an immediate 500 Internal Server Error for the entire directory — no partial failures, just a completely broken site. Understanding the common failure modes will save you from hours of troubleshooting.

Common pitfalls to watch for:

Debugging approach:

# Enable RewriteLog for debugging (Apache 2.2 style)
RewriteLog /tmp/rewrite.log
RewriteLogLevel 3

# Apache 2.4 equivalent
LogLevel alert rewrite:trace3

# Test Apache config syntax
apachectl -t     # tests httpd.conf — .htaccess must be validated manually

Step-by-step debug workflow: Always test on a staging environment first. Add rules one at a time and verify each one works before moving to the next. Check /var/log/apache2/error.log for the specific error message. Use browser DevTools (Network tab) to inspect HTTP status codes and redirect chains. Use an online htaccess tester to simulate rule matching before deployment.

RecommendedAsiaGB.com — Apache hosting with full .htaccess support out of the box. AllowOverride All on every plan, SSD storage, DirectAdmin control panel, 24/7 Thai-language support, 99% uptime.

AsiaGB.com — server in Thailand & Singapore, SSD, DirectAdmin, 24h support, 99% uptime.

Visit AsiaGB →

Frequently Asked Questions

What web server does .htaccess work with?
.htaccess is an Apache-specific configuration file and does not work natively with Nginx or IIS. Nginx uses server blocks in nginx.conf instead. LiteSpeed Web Server also supports .htaccess since it is Apache-compatible, so many cPanel-based hosts that run LiteSpeed can still use .htaccess without changes.
Does .htaccess slow down my website?
Apache reads every .htaccess file on each HTTP request, which adds a small I/O overhead. For maximum performance, move rules to httpd.conf and set AllowOverride None — Apache then reads the config only once at startup. On shared hosting where you cannot edit httpd.conf, .htaccess is the only option, and the overhead is negligible for most sites.
My .htaccess rules are not working — what should I check first?
Start by confirming that AllowOverride is set to All (not None) in httpd.conf. Next, verify that mod_rewrite is loaded. Then check your file for syntax errors — even a missing space or wrong bracket causes the whole file to fail with a 500 error. Finally, review the Apache error log for a specific error message that points directly to the problem line.
Should I put rules in .htaccess or httpd.conf?
httpd.conf offers better performance because Apache reads it once at startup. .htaccess is more practical on shared hosting since changes take effect instantly and you do not need root access or a server restart. If you manage a VPS or dedicated server, migrating your rules from .htaccess to httpd.conf (with AllowOverride None) is a meaningful performance improvement, especially on high-traffic sites.