A RewriteRule is a directive in the Apache mod_rewrite module that changes requested URLs on the fly using a rule-based engine. It maps a URL to a filesystem path, redirects to another URL, or invokes a proxy fetch based on specific patterns. This tool is essential for SEO practitioners to manage site migrations, create clean URL structures, and handle complex redirects.
What is RewriteRule?
RewriteRule is the primary directive used by the mod_rewrite module to perform URL transformations. It uses Perl Compatible Regular Expressions (PCRE) to identify specific URL patterns and replace them with a new string. The module identifies the requested path, checks if it matches the defined pattern, and applies the specified substitution.
Rules can be defined in the main server configuration file (httpd.conf) or within per-directory .htaccess files. While the server configuration context matches against the full URL-path after the hostname, the per-directory context matches only the partial path below the directory where the rule is located.
Why RewriteRule matters
- URL Canonicalization: Direct users and search engines to a single version of a URL to prevent duplicate content issues.
- Site Migrations: Manage bulk 301 redirects to preserve link equity when changing site structures or moving to a new domain.
- User Experience: Transform complex, parameter-heavy URLs into clean, readable paths that are easier for users to share.
- Security and Access Control: Forbid access to specific file types, such as
.exefiles, by returning 403 Forbidden status codes. - Resource Management: Signal that a resource is permanently gone with 410 status codes or serve different content versions (like mobile) based on the user's browser.
How RewriteRule works
The basic syntax of a RewriteRule follows this order: RewriteRule Pattern Substitution [Flags]. The process involves three main components:
- Pattern: A regular expression that is matched against the URL. If the pattern does not match, Apache skips the rule and moves to the next one.
- Substitution: The string that replaces the original URL. This can be a filesystem path, a URL-path relative to the document root, or an absolute URL.
- Flags: Optional modifiers in square brackets that change how the rule behaves, such as forcing a redirect or stopping further rule processing.
Before a rule runs, it may be subject to a RewriteCond (Rewrite Condition). This acts as a gatekeeper: if the condition is not met, the following RewriteRule is ignored.
Common RewriteRule Flags
Flags modify the behavior of a rule. Multiple flags can be used together, separated by commas.
| Flag | Name | Function |
|---|---|---|
| [R] | Redirect | Forces an external redirect (defaults to 302, but can be 301). |
| [L] | Last | Stops the rewriting process for the current round. |
| [NC] | No Case | Makes the pattern matching case-insensitive. |
| [QSA] | Query String Append | Combines the original query string with the new one in the substitution. |
| [F] | Forbidden | Returns a 403 Forbidden status immediately. |
| [G] | Gone | Returns a 410 Gone status immediately. |
| [P] | Proxy | Forces the request to be handled by mod_proxy. |
[The QSD flag, which stands for Query String Discard, was introduced in version 2.4.0 to allow for the clean removal of incoming query strings] (Apache HTTP Server Version 2.4).
Best practices
- Enable the engine: Always include
RewriteEngine Onin your configuration before defining rules. - Use the Last flag: Frequently include the
[L]flag to prevent Apache from processing subsequent rules once a match is found. - Order your rules: Define specific rules before general ones to ensure the correct transformation is applied.
- Test in increments: Use the
trace1totrace8log levels to debug rules, but keep levels low in production to avoid slowing down the server. - Avoid loops: Be careful when using the
[N]flag, as it restarts the ruleset from the top and can cause infinite loops. [In version 2.4.8 and later, the module returns an error after 10,000 iterations to stop unintended looping] (Apache HTTP Server Version 2.4).
Common mistakes
Mistake: Using a leading slash in .htaccess patterns.
Fix: In per-directory context, the prefix is stripped, so patterns should not start with /. Use ^index.html instead of ^/index.html.
Mistake: Forgetting the [QSA] flag when redirecting URLs with parameters.
Fix: Add [QSA] to ensure that parameters like ?source=email are carried over to the new URL.
Mistake: Relying on [L] to stop all processing in .htaccess.
Fix: The server may re-inject the rewritten request, causing the .htaccess rules to run again. Use [the END flag, available since version 2.3.9, to permanently stop further rewrite processing in per-directory contexts] (Apache HTTP Server Version 2.4).
Mistake: Using RewriteRule when simpler directives work.
Fix: Use Redirect or Alias for simple mappings, as they are more efficient than the full rewrite engine.
Examples
Creating a 301 Redirect
To move a page permanently and preserve SEO value:
RewriteRule "^old-page\.html$" "/new-page.html" [R=301,L]
Forcing a 410 Gone Status
To tell search engines a product page no longer exists:
RewriteRule "old-product-slug" "-" [G,NC]
Serving Mobile Content
Using conditions to serve a specific file to mobile users:
RewriteCond "%{HTTP_USER_AGENT}" "(iPhone|Blackberry|Android)"
RewriteRule "^/$" "/homepage.mobile.html" [L]
FAQ
What is the difference between [L] and [END]?
The [L] flag stops processing the current round of rules, but in .htaccess files, the request might be re-processed by the engine from the start. The [END] flag terminates all rewrite processing for that request immediately, preventing any subsequent rounds.
How do I handle special characters in my URLs?
Use the [B] flag to escape non-alphanumeric characters in backreferences before the transformation. This prevents broken URLs when your parameters contain spaces or slashes. [Apache version 2.4.60 added the UnsafePrefixStat flag to handle potentially unsafe substitutions involving variables and filesystem paths] (Apache HTTP Server Version 2.4).
Can I set cookies with a RewriteRule?
Yes, use the [CO] flag. You must specify the name, value, and domain. For example, [CO=frontdoor:yes:.example.com:1440:/] sets a cookie named 'frontdoor' that lasts for 24 hours across the entire domain.
Does RewriteRule affect site performance?
High log levels (above trace2) and complex rule sets can slow down the server. It is usually more efficient to use standard directives like Alias or DirectoryMatch if a regular expression is not strictly necessary.
How do I redirect based on a hostname?
You cannot match the hostname directly in the RewriteRule pattern. You must use a RewriteCond with the %{HTTP_HOST} variable before the rule.