mod_rewrite is the world-famous regular-expressions-based URL manipulation engine that is now available for IIS users in the framework of Helicon Ape. It can:

  • rewrite, redirect, proxy requests ( see details )
  • impose conditions on HTTP headers and query string values, server variables states etc.
  • easily handle large sets of data with the help of mapfiles
  • set/unset environment variables
  • block access to specific hosts, referrers, pages

Quick start

Let's take a real-life example that is often requested/used by our customers.

Requested URL:
Address bar:
Content shown:

Surely one usually needs to rewrite a large number of URLs of similar pattern (same parameters but different parameters' values), hence map files are most suitable for this situation. So we need...


param1=value1&param2=value2   keyword1 
param1=value3&param2=value4   keyword2
param1=value5&param2=value6   keyword3


RewriteEngine on 
RewriteBase / 
#to use relative paths in RewriteMap, map files must reside in the same folder as .htaccess
RewriteMap mapfile txt:mapfile.txt [NC]
RewriteMap revmapfile txt_rev:mapfile.txt [NC]
RewriteCond %{QUERY_STRING} (.+) 
RewriteRule ^index\.asp$ ${mapfile:%1}? [NC,R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.asp?${revmapfile:$1} [NC,L,NS]

Related articles and topics


Simple search engine friendly URLs

Use IIS as reverse proxy

Emulating host-header-based virtual sites

Blocking inline-images (stop hot linking)

Moving site location

Browser-dependent content

Dynamically generated robots.txt

Emulating load balancing

Blocking annoying robots


Name Context Description
RewriteBase S V D .h sets the base URL for per-directory rewrites
RewriteCond S V D .h imposes condition on the subsequent RewriteRule / RewriteProxy / RewriteHeader directive
RewriteEngine S V D .h enables or disables rewriting engine for the current context
RewriteHeader S V D .h rewrites any HTTP request header
RewriteLog S V D .h sets the name and path to mod_rewrite log file
RewriteLogLevel S V D .h specifies the verbosity of rewrite.log
RewriteMap S V D .h defines the name and path to the map file
RewriteOptions S V D .h specifies special rewriting options
RewriteProxy S V D .h proxies request to a remote server
RewriteRule S V D .h sets the matching pattern and destanation path for URL rewriting


When RewriteRule directive is used in per-directory configuration files (. htaccess ) it will automatically strip the local directory prefix from the path and apply rules only to the remainder. RewriteBase directive allows you to explicitly specify a base for the rules, i.e. the part that will be stripped.

For directory context RewriteBase will be empty by default but for .htaccess configurations it will contain virtual path to requested directory.


RewriteBase URL-path


RewriteBase requested-directory-path


RewriteBase /
RewriteRule ^test\.asp$ index.htm [NC,L]


RewriteCond directive defines a single condition for the following RewriteRule , RewriteHeader or RewriteProxy directive.
Multiple conditions for the same rule are possible. When several conditions are applied to the rule, by default, the rule fires when ALL of them get matched (AND logic). If you want OR logic instead (at least one condition must match for the rule to fire), use [OR] flag.


RewriteCond TestString CondPattern


  • TestString additionally to plain text supports the following constructs:
    • Back references to RewriteRule pattern using $N syntax
    • Back references to preceding RewriteCond patterns using %N syntax
    • map files calls using ${mapname:key|default} syntax
    • Environment variable using %{ENV:variable} syntax
    • HTTP header value with %{HTTP:header} syntax
    • Server variable using %{NAME_OF_VARIABLE} syntax (Here is the list of supported server variables: )
  • CondPattern specifies a regular expression that will be applied to the instance of TestString . The following special values are also supported :
    • ! — prefix to negate CondPattern
    • <CondPattern — treats CondPattern as a plain string that will be lexicographically compared as "more than"
    • >CondPattern — lexicographically less then comparison
    • =CondPattern — lexicographically equals comparison
    • -d TestString is existing directory
    • -f TestString is existing file
    • -s TestString is a file of non-zero size

    The following values are unsupported because they are senseless in IIS:

    • -l — is a link
    • -x — has executable permissions
    • -F — is existing file, via subrequest
    • -U — is existing URL, via subrequest


  • NoCase or NC — makes the CondPattern case-insensitive
  • Ornext or OR — combines subsequent RewriteCond directives with logical OR instead of implicit AND
  • Optimize or O — normalizes string before processing (removes URL-encoding, illegal characters, etc; also, IIS normalization implies removal of query string from the URL)

Note! RewriteCond directive affects only ONE subsequent RewriteRule , RewriteHeader or RewriteProxy directive.


# send all requests like to index.htm page
RewriteCond %{QUERY_STRING} ^id=(\d+)$
RewriteRule ^test\.asp$ index.htm? [NC,L]


RewriteEngine enables or disables rewriting runtime for the context it's specified in. Use RewriteEngine off instead of commenting out rewrite rules if you need to disable mod_rewrite module or specific .htaccess file.


RewriteEngine On|Off

Note! Unlike in ISAPI_Rewrite 3, it's necessary to specify RewriteEngine On directive to make the config working.


RewriteHeader directive is a more general case of RewriteRule directive; it's designed to rewrite not only the URL part of client request, but any HTTP header. Technically RewriteRule directive is equivalent to RewriteHeader URL: Pattern Substitution [flags] . This directive can be used to rewrite, create or delete any HTTP headers in the client request before it is processed by other applications on IIS.


RewriteHeader HeaderName: Pattern Substitution [flags]


  • HeaderName specifies the name of HTTP header that will be rewritten
  • Pattern , Substitution and flags have the same meaning as for RewriteRule directive

Note! RewriteHeader directive has no equivalent in Apache (see Compatibility chart ).


RewriteLog directive sets the name and path to the log file where mod_rewrite will log its actions.


RewriteLog file_path optionalParameter1 value optionalParameter2 value

Optional parameters of the directive:

  • archiveAboveSize - Size in kilobytes above which log files will be automatically archived.
  • maxArchiveFiles - Maximum number of archive files that should be kept. Default: 9
  • archiveNumbering - Way file archives are numbered. Possible values:
    • Rolling - Rolling style numbering (the most recent is always #0 then #1, ..., #N.
    • Sequence - Sequence style numbering. The most recent archive has the highest number.
    • Date - Date style numbering. The date is formatted according to the value of archiveDateFormat.
  • archiveEvery - Indicates whether to automatically archive log files every time the specified time passes. Possible values:
    • Day - Archive daily.
    • Hour - Archive every hour.
    • Minute - Archive every minute.
    • Month - Archive every month.
    • None - Don't archive based on time.
    • Year - Archive every year.


RewriteLog "C:\local\path\rewrite.log"


# RewriteLog directive can be put in .htaccess file. In such case the file-path relative to site root must be specified:
RewriteLog "rewrite.log" archiveEvery Day archiveNumbering Date maxArchiveFiles 150
RewriteLogLevel 9


RewriteLogLevel directive defines the verbosity of logging output. The default value of 0 means no logging, while maximum level of 9 means all actions will be logged.

Using higher values of logging may slow down mod_rewrite operation. We recommend you to disable logging by setting log level to 0 after debugging of your ruleset has been completed.


RewriteLogLevel Level


RewriteLogLevel 0


RewriteLogLevel 9


RewriteMap directive is used to define a key to value lookup function. This is useful when you have to deal with large amount of values of similar pattern since it is much faster than doing it with rule matching.


RewriteMap MapName MapType:MapSource


  • MapName is the name of mapping function that will be used to refer to this map from RewriteRule command. Make sure that every mapping is given a unique name.
  • MapType may be one of the following:
    • txt — mapping using text file map
      #plain text file
      key1 value1
      key2 value2
      keyN valueN
    • txt_rev — mapping using reverse text file map
      #plain text map file with columns in reverse order
      value1 key1
      value2 key2 
      valueN keyN 
    • rnd — random value select from multiple choices
      #one of the right column values is randomly selected
      key1 value1|value2|value3
      key2 value4|value5|value6|valueN
    • int — internal functions
      • toupper — converts the key to all upper case (not really necessary with the introduction of [NC] flag)
      • tolower — converts the key to all lower case (not really necessary with the introduction of [NC] flag)
      • escape — encode special characters to hex values
      • unescape — unencode hex values to special characters
    • dbd — mapping using external database


      Below is the example of how to use dbd-type map file to rewrite SEO-friendly URLs to original physical pages. What you need is a database containing two columns: OriginalURL (with real physical URLs) and SEO_URL (with pretty SEO-friendly links). Having created the database you are ready to use this config:

      DBDriver mssql
      DBDParams "Data Source=server;Initial Catalog=database;User ID=user;Password=password"
      DBDPrepareSQL "select OriginalURL from seo_mapping where `SEO_URL` =@KEY" seo_map_select
      RewriteEngine On
      RewriteMap map_dbd dbd:seo_map_select
      RewriteCond ${map_dbd:$1|NOT_FOUND} (.*)
      RewriteCond %1 !NOT_FOUND 
      RewriteRule (.+) %1 [L]
  • MapSource is the path (absolute or relative) to the map file.


  • NoCase or NC — makes the comparison of mapfile values with corresponding rule submatch case-insensitive

You can call mapping function in the Substitution value of RewriteRule directive using the following syntax:

${ MapName : LookupKey | DefaultValue }

If this construction is found in Substitution , mod_rewrite will lookup for the key in the map file and if one is found, substitute the construct by its value. If no key is found, optional DefaultValue will be used. If no DefaultValue is specified, it will be substituted by an empty string.


RewriteMap examplemap txt:/path/to/file/map.txt [NC]

Then you may use this map in RewriteRule as follows:

RewriteRule ^/ex/(.*) ${examplemap:$1|0}


RewriteOptions directive sets special options for mod_rewrite.


RewriteOptions Options

Currently only one option is available:

  • inherit — forces current config to inherit all options and rules from the parent. This means that all rules from the parent config will be executed again but from the context as if they were written in the current config.


RewriteOptions inherit


RewriteProxy causes the resulting URL to be internally treated as a target on another server and immediately (i.e. rules processing stops here) passed to the remote server. Response of the remote server will then be passed back to the client. Proxy requires you to specify fully qualified URL, starting from protocol, host name, etc.


RewriteProxy Pattern Substitution [flags]

Syntax of RewriteProxy is the same as of RewriteRule directive.


  • A ( A dd authentication headers) — allows passing of an authentication information from proxy to an internal server when client authentication against a proxy server is used. Proxy module will append headers

    corresponding to server variables


    to a request sent to a proxied server.

  • CR (use CR edentials) — proxy module will try to login on a remote server with the credentials specified in the URL or using basic authentication headers. With this flag you can use http://user:[email protected]/path/ syntax as a URL within substitution string.


RewriteEngine On
RewriteBase /
RewriteProxy ^folder/(.*)$$1

Note! RewriteProxy directive has no equivalent in Apache (see Compatibility chart ).

Note! RewriteProxy directive uses mod_proxy and requires it to be enabled in addition to mod_rewrite.


RewriteRule directive defines a single URL rewriting operation.


RewriteRule Pattern Substitution [flags]


  • Pattern — Perl-compatible regular expression which will be matched against current URL. The current URL may be either originally requested URL or URL already altered by preceding rules. URL never includes protocol, host name and port number (they are defined in RewriteCond if necessary).

    Note! The current URL may differ depending on the location of configuration file—for directory level configurations current directory name is substracted from the URL to match.

    Please address Regular expression syntax section of the documentation for more information on building regular expressions.

    Preceding pattern by a ! character will negate entire expression. Negated pattern cannot generate submatches so you cannot use $N references in substitution.

  • Substitution — specifies format string to generate new URL if the Pattern is matched. In addition to plain text it can include:
    • back references to RewriteRule pattern: $N ($0-$9) and $$NN ($$10-$$99)
    • back references to RewriteCond pattern: %N (%0-%9) and %%NN (%%10-%%99)
    • map files calls %{mapname:key|default}
    • server variables %{VARNAME}
    • environment variables %{ENV:variable}
    • conditional format patterns (?Ntrue_string:false_string)
    • grouping parenthesis ‘ ( ‘ and ‘ )

    The syntax also allows escape sequences...

RewriteRule directives are applied in order of appearance in configuration file, starting from the parent configuration files. Each rule will apply only if its Pattern matches reuqested URL and all related conditions ( RewriteCond ) are also matched.

Special string ' - ' (dash) in Substitution means no substitution and is useful when you need to apply the rule but perform no actions (leave original URL intact).


RewriteEngine On
#do nothing when requested resource is either physical file or folder
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .? - [L]


  • CaseLower or CL — changes the case of substitution result to lower
  • CaseUpper or CU — changes the case of substitution result to upper
  • Chain or C — chains current rule with the next rule. Next rule will be executed only if the current rule is matched. Chain may contain more than 2 rules
  • Cookie or CO=NAME:VAL:domain[:lifetime[:path]] — sets cookie header with the fields specified and sends it to the client in response to the current request
  • Env or E=VAR:VAL — sets an environment variable
  • Forbidden or F — sends immediate 403 Forbidden response to the client; stops rules processing and all other subsequent processing on this request
  • Gone or G — sends immediate 410 Gone response to the client; stops rules processing and all other subsequent processing on this request
  • Handler or H=Content-handler — unsupported. Explicitly specifies handler for a request. In IIS world this can be achieved by rewriting file extension of requested file but there is no direct translation from Apache handlers to IIS file extensions
  • Last or L — stops rewriting process here and doesn't apply any more rules from the current configuration file. Descendant .htaccess files will still be applied if any
  • Loop or LP — re-runs current single rule in the loop while its pattern and conditions are matched. Number of iterations is limited to a value of 200 to avoid infinite loops
  • Next or N — re-runs entire rewriting process starting from the beginning of current configuration file. Number of iterations is limited to a value of 200 to avoid infinite loops
  • NoCase or NC — makes the Pattern case-insensitive
  • NoEscape or NE — prevents mod_rewrite from applying the usual URI escaping rules to the rewriting result. With this flag special characters (e.g. '%', '$', ';', etc) will NOT be escaped into their hexcode equivalents ('%25', '%24', '%3B' respectively)
  • NoSubreq or NS — forces rewriting engine to skip a rule if the current request is an internal sub-request. Supported only in IIS7.
  • nOrmalize or O — normalization includes removing of an URL-encoding, illegal characters, etc.; also normalization of URL completely removes query string from it. When O flag is not set , normalization takes place. If you set O at the end of the rule, normalization will not occur
  • Proxy or P — forces the resulting URL to be internally treated as a target on another server and immediately passed to the remote server
  • PassThrough or PT — unsupported or always on. Result is always passed through the next handler in IIS
  • QSAppend or QSA — appends query string of the original request to the Substitution string (regardless of whether Substitution has new query string or not). It may be useful when you need add new query string parameters but also preserve the originally requested ones
  • Redirect or R[=code] — forces server to send immediate response with redirect instruction, providing Substitution as a new location. You can optionally prefix Substitution with http://thishost[:thisport]/ bringing URL to a valid absolute form. If no code is specified, 302 (Moved Temporarily) response will be used by default. You can optionally specify any code from 3xx range
  • Skip or S=num — forces rewriting engine to skip the next num rules in sequence, if the current rule matches
  • StatusCode or SC=200..500 — forces server to send immediate response with custom status code page
  • Type or T=MIME-type — forces the MIME-type of the target file to be MIME-type . This can be used to set up the content-type based on some conditions
  • Unmanglelog or U — logs the URL as it was originally requested and not as the URL was rewritten