.htaccess Redirect Generator
Generate redirect rules for Apache or nginx: single URLs, whole folders, www and HTTPS canonicalisation, and trailing slashes, with the right status code.
# Redirects. Put this ABOVE the "# BEGIN WordPress" block in .htaccess:
# WordPress's own rules end with [L] and would otherwise run first.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_URI} ^/old-page/$
RewriteRule ^ /new-page/ [R=301,L]
</IfModule>
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Write redirect rules for Apache or nginx: single pages, whole folders, the www and HTTPS decision, and trailing slashes, each with the status code that means what you intend.
How to use
- Use 301 once you are sure. Browsers cache it hard, and a wrong 301 follows visitors around until they clear their cache.
- Use 302 while you are still deciding, and 410 for a page you deliberately deleted. 410 tells a crawler to stop asking, which a 404 does not.
- Put the rules above the WordPress block in
.htaccess. WordPress’s own rules end with[L], so anything after them may never run. - Force one host and one protocol. Serving both
wwwand bare, or both HTTP and HTTPS, is two sites as far as a crawler is concerned. - Behind Cloudflare or any proxy, check
X-Forwarded-Protoinstead ofHTTPS. The connection to the origin is plain HTTP, and checking the wrong thing is an infinite redirect.
Example
A folder move that keeps the rest of the path:
RewriteCond %{REQUEST_URI} ^/old-blog/(.*)$
RewriteRule ^ /articles/%1 [R=301,L]
Matching on REQUEST_URI rather than in the RewriteRule pattern is deliberate: inside .htaccess the rule pattern has the leading slash stripped, which is why ^/old-blog/ never matches there.
Pitfalls
- A 301 is cached by the browser, often indefinitely. Testing one you are unsure about means clearing your cache, or testing in a private window, every time.
- Rules placed below the WordPress block may never be reached. The
.htaccessrules WordPress writes end with[L]. - Checking
%{HTTPS}behind a proxy gives a redirect loop, because the origin only ever sees HTTP. - Chaining redirects costs a round trip each.
/ato/bto/cshould be/ato/c. - A redirect to a page that redirects back is a loop the browser gives up on after about twenty hops, with a blank page.
- WordPress already canonicalises trailing slashes to match your permalink setting. Adding your own rule on top is where most trailing slash loops come from.
RewriteRulepatterns are regular expressions. A dot in a path matches any character unless you escape it.- Redirecting a whole folder to a single page is a soft 404 in Google’s eyes: better to map the useful URLs and let the rest 410.
Compatibility
mod_rewrite rules work in Apache 2.2 and later, and .htaccess needs AllowOverride FileInfo or more. The [G] flag for 410 has been available since Apache 2.0. nginx has no .htaccess: rules live in the server block and need a reload. 307 preserves the request method, which matters for a POST endpoint that has moved, and is supported by every current browser. The tool runs entirely in your browser.
Frequently asked questions
301 or 302?
Where do the rules go in .htaccess?
# BEGIN WordPress block. Below it, WordPress’s rules may match first and stop processing.Why am I getting a redirect loop?
%{HTTPS}, or a trailing slash rule fighting WordPress’s own canonicalisation.