RewriteCond is an Apache server directive that tells the software to only perform a URL redirect or rewrite if specific conditions are met. You place these conditions immediately before a RewriteRule to control when that rule triggers. Marketers use it to manage SEO redirects based on user devices, hostnames, or specific server environments.
What is [RewriteCond]?
The RewriteCond directive acts as a filter for the RewriteRule that follows it. It evaluates a specific "TestString" (such as a browser type or an IP address) against a "CondPattern" (usually a regular expression). If the test matches the pattern, the server moves to the next condition or executes the rewrite rule.
You can use an unlimited number of conditions for a single rule. By default, the server evaluates multiple RewriteCond directives using a logical AND sequence. This means every condition must be true for the rewrite to occur unless you specify otherwise with flags.
Why [RewriteCond] matters
Using conditions prevents blanket redirects that might hurt your site's SEO or user experience.
- Device-Specific Targeting: Deliver mobile-specific pages only to users on mobile browsers by checking the
HTTP_USER_AGENTvariable. - Preventing Hotlinking: Protect your server bandwidth by blocking other sites from embedding your images.
- Canonical Hostnames: Ensure all traffic goes to the "www" or "non-www" version of your site by checking the
HTTP_HOST. - Maintenance Windows: Redirect users to a "down for maintenance" page based on the server's time variables.
- Security and Access Control: Block specific IP addresses or referrers that show suspicious patterns.
[Using a high trace log level for mod_rewrite will slow down the Apache HTTP Server dramatically] (Apache HTTP Server Documentation). Always use levels higher than trace2 only for temporary debugging.
How [RewriteCond] works
The rewriting engine follows a specific sequence to process your conditions:
- Rule Evaluation: The server actually looks at the
RewriteRulefirst to see if the URL pattern matches. - Condition Testing: If the rule matches, the server then evaluates any
RewriteConddirectives placed above that rule. - Variable Expansion: The server expands variables in the
TestString, such as%{HTTP_HOST}or%{QUERY_STRING}. - Pattern Matching: The server compares the expanded string against the
CondPatternusing Perl Compatible Regular Expressions (PCRE). - Execution: If the conditions are met, the server performs the substitution defined in the
RewriteRule.
Back-references
RewriteCond creates back-references that you can reuse later. While RewriteRule uses $N (like $1, $2) to reference parts of its matched pattern, RewriteCond uses %N (like %1, %2) to reference grouped parts of its own patterns.
Best practices
Use the NC flag for case-insensitivity.
When matching strings like User-Agents or hostnames, use the [NC] (no case) flag to ensure the condition catches variations in capitalization.
Limit use of internal subrequests.
The -F (file via subrequest) and -U (URL via subrequest) tests check if a file or URL exists via a secondary internal request. [These checks can impact your server's performance and should be used with care] (Apache HTTP Server Documentation).
Clean up your logs.
In modern Apache versions, [the functionality of RewriteLog and RewriteLogLevel has been completely replaced by the per-module LogLevel configuration] (Apache HTTP Server Documentation). Use LogLevel alert rewrite:trace3 to see detailed processing for debugging.
Use the OR flag for multiple alternatives.
If you want a rule to trigger if any of several conditions are true, append the [OR] flag to each RewriteCond except the last one.
Common mistakes
-
*Mistake:* Putting a leading slash in
.htaccessconditions. In a per-directory context (like.htaccess), the directory path is stripped before matching. Fix: Patterns in.htaccessshould not start with a slash because they match against a string that never has one. -
*Mistake:* Negating patterns and using back-references. If you use
!to negate a pattern, you cannot use%Nin your substitution string. Fix: Only use back-references when the condition is set to match a pattern, not when it is set to "not match." -
*Mistake:* Forgetting that Virtual Hosts do not inherit rules. [Rewrite configurations are not inherited by virtual hosts by default] (Apache HTTP Server Documentation). Fix: Place a
RewriteEngine ondirective inside every virtual host where you want to use conditions. -
*Mistake:* Confusing
$1with%1. Using the wrong symbol for back-references causes the server to insert empty strings or incorrect data. Fix: Use$for groups found in theRewriteRuleand%for groups found in theRewriteCond.
Examples
Redirect mobile users to a subfolder
This scenario checks the User-Agent string to see if the visitor is using a mobile platform.
RewriteCond "%{HTTP_USER_AGENT}" "(iPhone|Blackberry|Android)"
RewriteRule "^/$" "/homepage.mobile.html" [L]
Block image hotlinking
This scenario checks the HTTP_REFERER to ensure it matches your own site's hostname. If it does not match, the request for any image file in the /images folder is forbidden.
RewriteCond expr "! %{HTTP_REFERER} -strmatch '*://%{HTTP_HOST}/*'"
RewriteRule "^/images" "-" [F]
Redirect specific IP address range
This scenario uses a regular expression to match an internal IP range and sends those users to a specific intranet server.
RewriteCond "%{REMOTE_ADDR}" "^10\.2\."
RewriteRule "(.*)" "http://intranet.example.com$1"
FAQ
What variables can I test with RewriteCond?
You can test HTTP headers (like HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE), server internals (SERVER_ADDR, DOCUMENT_ROOT), and date/time variables (TIME_YEAR, TIME_DAY). You can also check the QUERY_STRING to find specific parameters in a URL.
Does RewriteCond support numeric comparisons?
Yes. You can use operators like -eq (equal), -gt (greater than), and -lt (less than). These treat the values as integers rather than strings, which is useful for checking timestamps or port numbers.
How do I test if a file exists on the server?
You can use the -f flag to check if the TestString is a regular file on the disk. For example, RewriteCond %{REQUEST_FILENAME} !-f is a common way to say "only run this rule if the requested file does not exist."
What is the difference between [L] and [END] flags?
The [L] flag stops the current rewriting process but may trigger again in certain contexts like .htaccess. [The END flag stops the rewriting process immediately and prevents further execution of rewrite rules in per-directory and .htaccess contexts] (Apache HTTP Server Documentation).
Can I use multiple conditions for one rule?
Yes. You can list several RewriteCond lines before a single RewriteRule. All must be true (AND logic) unless you add the [OR] flag to the end of the condition lines.