StarDomain

Common .htaccess URL Rewrite Rules

Common .htaccess URL Rewrite Rules

URL rewriting with mod_rewrite is one of the most powerful features of the Apache .htaccess file. It allows you to create clean, SEO-friendly URLs, set up redirects, and control how your server responds to requests. This guide provides ready-to-use rewrite rules for the most common scenarios.

Understanding mod_rewrite Basics

Before diving into rules, understand the key components:

RewriteEngine

Every .htaccess file using rewrite rules must start with:

RewriteEngine On

This enables the rewrite engine for the directory.

RewriteRule Syntax

RewriteRule Pattern Substitution [Flags]
  • Pattern: A regular expression matched against the URL path
  • Substitution: The URL to serve or redirect to
  • Flags: Modifiers that control behavior (e.g., [L], [R=301], [NC])

Common Flags

FlagMeaning
[L]Last rule — stop processing further rules
[R=301]Permanent redirect (301)
[R=302]Temporary redirect (302)
[NC]Case-insensitive matching
[QSA]Append query string to substitution
[F]Forbidden — return 403 error
[P]Proxy — internally proxy the request

RewriteCond Syntax

RewriteCond TestString ConditionPattern [Flags]

Conditions must be met before the following RewriteRule is applied.

Important: Always test rewrite rules on a staging environment or subdirectory before applying them to your live site.

Domain and Protocol Redirects

Force HTTPS

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

Force HTTPS and WWW Together

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

Force HTTPS and Remove WWW

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

Redirect Entire Domain to New Domain

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

URL Cleanup and SEO

Remove Trailing Slash

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

Add Trailing Slash

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

Remove .html Extension

Serve clean URLs without the .html extension:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html [L]

Also redirect .html URLs to clean versions:

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

Remove .php Extension

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

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

Remove index.html or index.php from URLs

RewriteEngine On
RewriteRule ^(.*)index\.(html|php)$ /$1 [L,R=301]

Page and Path Redirects

Redirect a Single Page

Redirect 301 /old-page.html /new-page.html

Or using RewriteRule:

RewriteRule ^old-page\.html$ /new-page.html [L,R=301]

Redirect a Directory to Another Directory

RewriteRule ^old-folder/(.*)$ /new-folder/$1 [L,R=301]

Redirect All Pages to a Single Page (Maintenance Mode)

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000$
RewriteRule ^(.*)$ /maintenance.html [L,R=302]

Replace 123.456.789.000 with your IP address to exempt yourself from the redirect.

Redirect Based on Query String

RewriteCond %{QUERY_STRING} ^id=123$
RewriteRule ^product\.php$ /products/widget-name? [L,R=301]

The trailing ? removes the old query string.

Clean URL Routing

Front Controller Pattern (Used by Many CMS/Frameworks)

Route all non-file, non-directory requests to index.php:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

This is the basis for URL routing in WordPress, Laravel, CodeIgniter, and many other frameworks.

Pretty URLs for a Custom Application

Convert URLs like /products/widgets to product.php?category=widgets:

RewriteRule ^products/([a-zA-Z0-9_-]+)/?$ product.php?category=$1 [L,QSA]
RewriteRule ^products/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ product.php?category=$1&item=$2 [L,QSA]

Blog-Style URLs

Convert /2026/03/my-article to blog.php?year=2026&month=03&slug=my-article:

RewriteRule ^([0-9]{4})/([0-9]{2})/([a-zA-Z0-9_-]+)/?$ blog.php?year=$1&month=$2&slug=$3 [L,QSA]

Security Rules

Block Access to Hidden Files

RewriteRule (^\.|/\.) - [F]

Block Specific User Agents (Bots)

RewriteCond %{HTTP_USER_AGENT} (BadBot|EvilScraper|SpamCrawler) [NC]
RewriteRule .* - [F,L]

Block Hotlinking (Prevent Image Theft)

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,L]

Block Access by IP Address

Order Deny,Allow
Deny from 192.168.1.100
Deny from 10.0.0.0/24
Allow from all

Performance Optimization

Enable Gzip Compression

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css text/javascript
  AddOutputFilterByType DEFLATE application/javascript application/json
  AddOutputFilterByType DEFLATE application/xml text/xml
  AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>

Browser Caching

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpeg "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 application/javascript "access plus 1 month"
  ExpiresByType application/font-woff2 "access plus 1 year"
</IfModule>

Troubleshooting Rewrite Rules

  1. 500 Internal Server Error: Check for syntax errors. Comment out rules one by one to find the culprit.
  2. Redirect loops: Ensure your conditions properly exclude the target URL from the pattern.
  3. Rules not working: Verify that RewriteEngine On is present and mod_rewrite is enabled.
  4. Order matters: Rules are processed top-to-bottom. More specific rules should come before general ones.
  5. Check the [L] flag: Without it, subsequent rules may modify the rewritten URL.
  6. Test with [R=302] first: Use temporary redirects during testing, then switch to [R=301] when confirmed working. Browsers aggressively cache 301 redirects.

Tip: Use online .htaccess testing tools to validate your rules before deploying to production.

  • Introduction to .htaccess Files
  • How to Force HTTPS on Your Website
  • Troubleshooting 500 Internal Server Errors

Need help with URL rewrites or .htaccess configuration? Contact our support team at {{SUPPORT_EMAIL}} or visit {{SUPPORT_URL}}.