A 301 redirect is a server response (HTTP status 301 Moved Permanently) telling browsers and search engines that a URL has moved permanently to a new address. Google reads it as a strong signal that the new URL should be canonical, and starts indexing the destination instead of the source.
It is the basic building block of any URL change: it keeps the visits that arrive from old links, bookmarks and search results, and it carries the old page's signals over to the new one. Google covers it in its guide to redirects and Google Search.
When to use a 301 redirect
- URL change: you rename a slug, restructure folders or switch to friendly URLs. Each old URL should point to its new version.
- Domain change: a rebrand or a move from a country domain to a .com. Redirect URL by URL, never the whole domain to the home page. This is the core of any SEO migration.
- Move to HTTPS and a single host: http to https, and non-www to www (or the other way round). If all four variants serve content, you have duplicate content.
- Merging pages: two articles competing for the same query become one, and the one that goes away redirects to the one that stays.
- Removed content with a clear replacement: a discontinued product with a direct successor. If there is no equivalent, a 404 error or a 410 is the honest answer.
Google recommends keeping redirects in place for as long as possible, generally at least one year, according to its guide on site moves with URL changes. In practice, if they cause no trouble, keep them forever.
301 and 308: the two permanent redirects
The 308 Permanent Redirect status is permanent too. The difference is technical: a 308 forces the browser to repeat the request with the same HTTP method (a POST stays a POST), while with a 301 the browser may turn a POST into a GET. For Google they are equivalent: both are a strong canonicalization signal.
For regular pages, which are requested with GET, it makes no difference which one you use. The 308 matters for APIs and forms, and some frameworks, such as Next.js, return it by default for permanent redirects. If an audit shows a 308, it is not an error.
Redirect chains
A chain happens when A redirects to B and B redirects to C. It is common after several migrations pile up:
http://example.com/page→ 301 to the https versionhttps://example.com/page→ 301 to the www versionhttps://www.example.com/page→ 301 to the new URLhttps://www.example.com/new-page/→ 200
Three hops to load one page. Googlebot follows up to 10 hops, according to Google's documentation on HTTP status codes, and if it does not reach the content, Search Console reports a redirect error. Tolerating it does not make it a good idea: every hop is one more request that slows the page down for users and burns crawl budget. Google has said that 30x redirects do not lose PageRank, so the real cost of a chain is not some authority lost at each hop, but latency and wasted crawling.
The rule is simple: always redirect straight to the final URL. When you change a URL that was already the target of other redirects, update the old rules as well. You can see every hop and its status code with the redirect checker.
How to set up a 301 redirect
On Apache (.htaccess)
On Apache or LiteSpeed servers, redirects live in the .htaccess file. One line is enough for a single URL:
Redirect 301 /old-page/ https://www.example.com/new-page/ To force HTTPS and www in a single hop with mod_rewrite:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301] Note that both conditions share one rule: if you write them as separate rules, an http non-www URL will take two hops.
On nginx
Nginx does not read .htaccess. Redirects go in the server configuration:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
location = /old-page/ {
return 301 https://www.example.com/new-page/;
} On WordPress
If you have no server access, a plugin such as Redirection, or the redirect module in an SEO plugin, lets you create 301s from the dashboard. They work well for dozens of rules. For a domain change or thousands of URLs, do it at server level: it is faster and does not depend on WordPress loading.
Common 301 redirect mistakes
- Redirecting everything to the home page. If you delete 200 products and send them all to the home page, Google treats those redirects as soft 404s: no signals are consolidated and users land on a page they were not looking for. Redirect to the closest equivalent (the successor or the category) or return a 404.
- Redirecting to broken URLs. The destination must return 200 and be indexable. A 301 that ends in a 404, on a noindex page or on a URL blocked in robots.txt is useless.
- Leaving internal links on old URLs. They still work, but every click and every crawl goes through an extra hop. Update menus, in-content links, the sitemap and canonical URLs so they point to the final URL.
- Using a 302 for a permanent change. Many servers and frameworks return a 302 redirect by default. Check the real status code after you publish.
- Conflicting rules. One rule that forces www and another that strips it cause a redirect loop, and the page stops loading.
Frequently Asked Questions
-
A 301 signals a permanent move, which Google treats as a strong signal to index the destination URL. A 302 signals a temporary move, so Google usually keeps the original URL indexed because it expects it to come back. If the change is final, always use a 301.
-
Google has said that 30x redirects do not lose PageRank. Some ranking movement is normal while Google recrawls the new URLs and consolidates signals, but when every old URL points to its real equivalent, traffic recovers.
-
Google recommends keeping redirects for as long as possible, generally at least one year. Since visits keep arriving from external links and bookmarks, the safest option is to never remove them.
-
Run
curl -I https://your-urland look at the status code on the first line and theLocationheader, or paste the URL into a redirect checker, which lists every hop with its status code up to the final URL.