I have a similar situation as described in

the difference is I don't use custom post permalink /%postname%.html but just /%postname%, so my post URL looks like this https://www.example.com/post.

And problematic URLs added by amp plugin are sitewide (not just post URL).

Post URL

Category URL

Tag Archieve 

Paginated and search result variation example

My .htaccess:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

Can .htaccess catch all those URL parameters and redirect them to the corresponding permalink?


1 Answer 1


This is really a generalised version of my answer to an earlier question, linked above.

This will remove a trailing /amp (or /amp/) at the end of any URL-path. It will also remove the amp or noamp URL parameter in the query string (and its optional value) on any URL, preserving all other URL parameters. With keeping this as a single rule, it will remove both a trailing /amp in the URL-path and amp URL parameter in a single redirect (although that may not actually be required here).

Try the following before the existing WP code block, ie. before the # BEGIN WordPress comment marker.

# Redirect old "amp" URLs back to permalink (general version)
RewriteCond %{QUERY_STRING} ^(.*&)?(?:no)?amp(?:=[^&]*)?&?(.*)$ [OR]
RewriteCond %{REQUEST_URI} /amp/?$
RewriteRule ^/?(.*?)(/amp/?)?$ /$1?%1%2 [NE,R=301,L]

The RewriteRule pattern ^/?(.*?)(/amp/?)?$ matches any URL-path but captures only the part of the URL before /amp (or /amp/) - if present - at the end of the URL-path. If /amp (or /amp/) does not appear at the end of the URL-path then the entire URL-path is captured (less the slash prefix if used in a server context). This is captured in the $1 backreference.

The two conditions (RewriteCond directives) then check whether either the query string contains the amp URL parameter OR the URL-path ends with /amp/. If the query string contains the amp URL param then this URL param is removed by capturing the parts of the query string before and after this param in the %1 and %2 backreferences respectively - which are used later in the substitution string to reconstruct the query string. If the amp URL param is not present in the query string then the %1 and %2 backreferences are empty and we essentially append an empty query string (which gets removed by Apache when constructing the Location header).

This is reliant on a couple of additional features of Apache:

  • A stray & at the end of the query string is removed before sending the redirect response (in the Location header) back to the client. This will occur when the amp URL parameter is the last URL param and there are other URL params that precede it. eg. ?q=search_term&amp is reduced to ?q=search_term& by the above rule, but Apache itself then removes the trailing &, so the end result is actually ?q=search_term.

  • A stray ? at the end of the URL-path (ie. an empty query string) is also removed.

  • Given the above two points... The only edge case in which this "fails" (in a very mild way) is if you received a request for ?&amp (an arguably malformed query string), where there is no preceding URL parameter, but there is still a URL param delimiter, then this will get reduced to <url-path>? - the trailing ? is still present on the response (and visible in the browser). Given a resulting query string of just ?&, Apache only removes the trailing & (as per the note above) not & and ?. If this did ever become a problem then you can remove a stray ? (empty query string) with an additional redirect.

The NE flag is likely to be required (particularly for the last example, ie. /?q=search_term&amp) in order to prevent the query string being doubly URL-encoded in the response. The QUERY_STRING server variable is not %-decoded, so the %1 and %2 backreferences are already %-encoded.

You do not need to repeat the RewriteEngine directive that already occurs later in the WP code block.

Test first with a 302 (temporary) redirect in order to avoid potential caching issues.

Make sure all (browser) caches are cleared before testing.

  • 2
    Youre a lifesaver MrWhite, God Bless You
    – takraw
    Feb 27, 2022 at 2:23
  • MrWhite, im getting a redirect loop after adding the rules ..my htaccess is exactly like given above with additional rules added by wp rocket cache for caching purposes
    – Anton Nb
    Apr 8, 2022 at 11:27
  • @AntonNb Please consider asking another question with additional details of the redirect-loop you are seeing and the full contents of the .htaccess file. ie. What URLs are being redirected from/to (check the browser dev tools). This rule alone should not trigger a redirect loop unless "something else" is redirecting you back again. Presumably you have already removed all code/plugins that generates these URLs in the first place? You will need to make sure that all caches have been cleared.
    – MrWhite
    Apr 8, 2022 at 12:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.