Mod_rewrite delete parameter in 301 Redirect

I want to remove all instances on aff=x regardless of how many other parameters in the URL.

Assuming you want to keep any other URL parameters (in any order) and simply remove the aff=number parameter, then you can do something like the following using mod_rewrite in the root .htaccess file:

RewriteCond %{QUERY_STRING} ^(.*&|)aff=\d+(?:&(.*)|)$
RewriteRule (.*) /$1?%1%2 [R=302,L]

This will need to go before the existing WordPress directives.

This assumes that if the aff parameter is present it will have a value of only digits and at least 1 digit.

The $1 is a backreference to the captured RewriteRule pattern. So, this will handle any URL-path, not just the document root, as in your example.

%1 and %2 are backreferences to the captured groups in the previous CondPattern. %1 is before the parameter to be removed and %2 is after. Both are optional.

Change the 302 (temporary) redirect to 301 (permanent) only after you have confirmed this is working OK (if this is intended to be permanent).


UPDATE#1: Query string contains %-encoded characters

If any of the other URL parameters (that you want to keep) contain URL-encoded (%-encoded) values then you will need to add the NE (noescape) flag to the RewriteRule directive to prevent these characters from being doubly encoded in the substitution. For example:

RewriteRule (.*) /$1?%1%2 [NE,R=302,L]

The QUERY_STRING server variable is not %-decoded by Apache. Normally, mod_rewrite URL-encodes the substitution before sending the response back to the client. But this will doubly encode any already-encoded characters that we have captured from the query string. The NE flag prevents this from happening.


UPDATE#2: URL parameter value to be removed could be anything

The question specifically dealt with removing a URL parameter called aff that contained a “number”. Generally, you should be as specific as possible when dealing with regex, however, if the URL parameter to be removed can contain anything then modify the CondPattern to be something like one of the following

  • ^(.*&|)aff=.*?(?:&(.*)|)$ – a non-greedy match of 0 or more characters.
  • ^(.*&|)aff=[^&]*(?:&(.*)|)$ – matches anything except & (URL parameter delimiter) 0 or more times.

The important point in both of these regex is that the value being matched is not captured, ie. must not be surrounded in plain parentheses.

In summary:

RewriteCond %{QUERY_STRING} ^(.*&|)aff=[^&]*(?:&(.*)|)$
RewriteRule (.*) /$1?%1%2 [NE,R=302,L]

Leave a Comment