Load & activate mod_rewrite

Search inside Apache's httpd.conf for a line similar to the following and remove the # at the beginning of the line.

LoadModule mod_rewrite.so

Enable mod_rewrite

RewriteEngine on

Enable mod_rewrite support inside .htaccess files

By default usage of mod_rewrite inside .htaccess files is not allowed. To allow usage add the following lines to the webroot Directory block inside your httpd.conf.

AllowOverride FileInfo

// will also work
AllowOverride All


mod_rewrite Conditions are constructed as followed:

RewriteCond <test-string> <condition> [<flags>]

Supported conditions

<less than
>more than
-dcheck if path is an existing directory
-fcheck if path is an existing file
-scheck if path is an existing file larger than 0 bytes
-lcheck if path is an symbolic link
-Fcheck if path is an existing file and user is authorized to access it
-Uchecks if test string is a valid url and user is authorized to access it


NC / nocasecase-insensitive matching (default: case-sensitive)
OR / ornextcombine conditions via logical or (default: logical and)

Magical values

$1 .. $9buffered values from current rewrite directive
%1 .. %9buffered values from last rewrite condition.


mod_rewrite Rewrite rules are constructed as followed:

RewriteRule <original-path-regexp> <rewritten-path> [<flags>]

<original-path-regexp> is a perl regular expression (PCRE). PCRE delimiter (e.g. /) are omitted. <original-path-regexp> can be negated by prefixing it with !

<rewritten-path> can contain matches from <original-path-regexp>. Rewrite dependents on context.

Rewrite context

main configurationwhole url is rewritten
inside <Directory> block or .htaccessonly the path from the current directory is rewritten.

Supported flags

Insinde RewriteRule mod_rewrite supports the following flags:
chain / Cgroup rewrite rules in a chain. later rules are executed, only if the previous ones are matching
cookie=<name>:<value>:<domain>[:<lifetime>[:<path>] / CO= set a cookie based on the given data.
env=<variable>:<value> / E=VAR:VALset environment variable variable to value
forbidden / Fsend HTTP status header FORBIDDEN (403) immediately
gone / Gsend HTTP status header GONE (410)
last / Lstop processing rewrite rules after this one
next / Nabort current rewrite directive and restart rewriting
nocase / NCperfom case-insensitive matching
noescape / NEdisable automatic url-encoding
nosubreq / NS
redirect / R[=301|302|303]perform a HTTP redirect to destination and send HTTP status header (default: 302)
passthrough / PTonly needed in complexe scenarios where you use multiple url rewrite engines like mod_rewrite and mod_alias together.
proxy / Pa requests to the given url is performed by Apache's module mod_proxy
qsappend / QSAappend parameters to current query string
skip=[1,2,3,..,n] / S=[1,2,3,..,n]skip the next n rewrite directives
type= / T=specify mime type for request

Magical values

Insinde RewriteRule mod_rewrite supports the magical values:
$1 .. $9buffered values from current rewrite directive


Server variables are handy for writing complex mod_rewrite rules sets. The following are available inside mod_rewrite.



HTTP Headers







Using mod_rewrite you can realize redirects quickly. Here are the most common redirects.

File and directories

Redirect single url

// single url
RewriteRule ^moved-file.html$ destination-file.html [R=302,NC]

Redirect directory

// whole directory
RewriteRule ^moved-dir(/.*)?$ destination-dir$1 [R=302,NC]

Redirect to directories with trailing slash

RewriteCond $1 !/$
RewriteCond %{REQUEST_FILENAME}/ -d
RewriteRule (.+) http://www.example.com/$1/ [R=301,L]

Redirect (sub)domains

Permanent redirect (301) to new domain

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

Permanent redirect (301) to www.*

RewriteCond %{HTTP_HOST} !^www.example.com$
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]

Permanent redirect (301) to domain without www

RewriteCond %{HTTP_HOST} !^example.com$
RewriteRule (.*) http://example.com$1 [R=301,L]


Redirect file extensions

RewriteBase /
// redirect (old) calls to php scripts to html file extension
RewriteRule ^(.*)\.php $1.html [R=301,L]
// interal map html extension to php extension
RewriteRule ^(.*)\.html $1.php [L]

Seo friendly urls

// map single url
RewriteRule ^the-best-mod-rewrite-cheatsheet$ cheatsheet.html [L]

// map all urls that consist of alphanumeric to frontcontroller (index.php)
RewriteRule ^([a-z0-9-]+)/? index.php?page=$1 [NC,L]

Path without file extensions

RewriteCond %{REQUEST_FILENAME}.php -f  
RewriteRule ^/?([a-z0-9]+)$ $1.php [NC,L]  
RewriteCond %{REQUEST_FILENAME}.html -f  
RewriteRule ^/?([a-z0-9]+)$ $1.html [NC,L]

Map non-existing urls

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*)$ index.php?page=$1


Some mod_rewrite conditions for handling query strings.

Evaluate query string

Check if query parameter exists

RewriteCond %{QUERY_STRING} !parameter=
RewriteRule ^/?parameter\.php$ missing.php [QSA,L]

Remove query string

Delete query string from request

RewriteRule ^test\.php$ test.php?

// also remove from browser's address bar
RewriteRule ^test\.php$ test.php? [R,L]


Deny access by IP

In most cases using Allow <IP> and Deny <IP> is better. However you can also control access by IP via mod_rewrite.

RewriteCond %{REMOTE_ADDR} ^205\.209\.177\.
RewriteRule .* - [F]

Prevent image hotlinking

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


Ensure HTTPS

// based on protocol
RewriteCond %{REQUEST_URI} ^secure_area/  
RewriteCond %{HTTPS} !on   
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

// alternative using server port
RewriteCond %{REQUEST_URI} ^secure_area/  
RewriteCond %{SERVER_PORT} !^443$ 
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

Common Software

Coming soon...