A 301 redirect is the response a server uses to tell browsers and search engines that a page has moved permanently and that the new address should be used instead of the old one.
Before writing a line of configuration you need a map: old URL, new URL, one row per page, exported from a crawler or from the server logs. Without that list, redirects get improvised while traffic drops. Google's documentation on site moves with URL changes says Googlebot follows up to 10 hops in a chain and recommends staying under three, because every extra hop is waiting time the visitor pays for. Better to point straight at the final destination.
When you need a 301
A 301 makes sense when the old address is not coming back. The cases that actually happen:
- a change of slug or URL structure, for example from /p?id=441 to /mens-hiking-boots/
- a domain migration, a rebrand, two sites merged into one
- moving from HTTP to HTTPS after installing an SSL certificate, and choosing a single variant between example.com and www.example.com
- consolidating two pages that compete for the same query
- a discontinued product with an equivalent replacement, not a distant cousin
Outside these cases it is the wrong tool. A page offline for two weeks needs a temporary code, which is covered in the entry on the 302 redirect. A page with no replacement needs a 404 error, not a bounce to the homepage: someone looking for a specific model finds nothing and goes back to Google.
Which redirect code to use
Most comparisons stop at 301 versus 302 and leave out the two codes the HTTP specification added to close an ambiguity. The current reference is RFC 9110, published in June 2022, which replaced RFC 7231, still cited by many articles.
| Code | Name | How Google reads it | HTTP method | When to use it |
|---|---|---|---|---|
| 301 | Moved Permanently | Permanent: the target becomes the canonical URL and appears in the results | The user agent may change POST to GET | Permanent URL change, domain migration, HTTP to HTTPS |
| 302 | Found | Temporary: the original URL stays in the results | The user agent may change POST to GET | Page suspended for a short time, A/B tests, maintenance |
| 307 | Temporary Redirect | Temporary, like the 302 | Method and request body stay unchanged | Temporary redirects on forms and APIs, the internal HSTS redirect |
| 308 | Permanent Redirect | Permanent, exactly like the 301 | Changing the method is not allowed | Permanent move of endpoints that receive POST |
The ambiguity is the one in the method column. Faced with a 301, the client may change the method of the next request from POST to GET: RFC 9110 allows it for historical reasons, and MDN Web Docs confirms it is the behaviour the Fetch Standard specifies. On a content page it changes nothing. On an endpoint receiving data from a form or an integration, the 301 turns the POST into a GET and the request arrives without its payload. That is exactly what the 308 is for: same permanence, no touching the method. For search engines the two codes are equivalent, as Google Search Central's page on redirects states.
How to write it, environment by environment
| Environment | Where it goes | Minimum line | Worth knowing |
|---|---|---|---|
| Apache | .htaccess or the virtual host configuration | Redirect 301 "/old" "https://www.example.com/new" | Without the status argument the directive returns a 302 |
| Nginx | server block in nginx.conf | return 301 https://www.example.com$request_uri; | return accepts 301, 302, 303, 307 and 308 from version 0.8.42 |
| WordPress | a dedicated plugin or a PHP hook | wp_redirect( $url, 301 ); exit; | Every request goes through PHP, so it costs more than a server rule |
| Cloudflare | Rules, then Redirect Rules or Bulk Redirects | expression on the request, target URL, status 301 | Responds from the edge, without waking the application |
# Apache, single page (mod_alias)
Redirect 301 "/old-page" "https://www.example.com/new-page/"
# Apache, whole domain from non-www to www over HTTPS (mod_rewrite)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# Nginx, dedicated server block
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
# WordPress, in a plugin (never in the theme file)
add_action( 'template_redirect', function () {
if ( is_404() && untrailingslashit( $_SERVER['REQUEST_URI'] ) === '/old-slug' ) {
wp_redirect( home_url( '/new-slug/' ), 301 );
exit;
}
} );
Two traps. In Apache the Redirect directive without a status argument returns a 302, not a 301: the mod_alias documentation says so, and these are redirects Google treats as temporary without anyone noticing for months. On Nginx the syntax is documented in the ngx_http_rewrite_module, where rewrite ... permanent does the same thing as return 301 at the cost of a regex evaluation per request.
On WordPress, hand-written code is rarely needed. Redirection, John Godley's plugin, has over 2 million active installations and keeps the rules in the database; Rank Math and Yoast SEO have an equivalent module. The cost is that every redirected request goes through PHP: past a thousand or so rules it is worth moving them upstream, to the vhost or to Cloudflare Redirect Rules, where the response leaves from the edge. If page speed is already an open issue, it is one of the few optimisations that shows up straight away in TTFB.
What passes to the new URL
Google's documentation is more restrained than what you read around. It says two things: with a permanent redirect the target is used as a canonicalisation signal and the new address appears in the results; with a temporary one the original stays in the results. No percentage, no dilution coefficient.
The figure of 15 per cent of value lost that has been going round for years has no verifiable primary source: it is reported second-hand and appears on no page of Google's documentation. What does not pass through the redirect, and is forgotten almost every time:
- internal links, which keep pointing at the old address until you rewrite them in the database: the redirect makes them work, but adds a hop to every click
- Search Console history, which stays tied to the old domain's property
- continuity of GA4 reports, where the old page stops collecting data and the new one starts from zero
- backlinks, which technically work but still point elsewhere: for the ones that bring real traffic it is worth asking the publisher to update them
How long Google takes to consolidate the signal
The answer is in the documentation on site moves: for a medium-sized site it can take weeks or more before Google starts showing the new URLs instead of the old ones, and longer for large sites. It is not a switch: in the first weeks the two versions coexist in Search Console, with impressions gradually sliding from one to the other.
On the other side, Google recommends keeping redirects in place as long as possible, generally at least a year. It is the first thing to go during a redesign: the hosting changes, the rules file doesn't come along, and three months later a thousand old addresses return 404. If organic traffic collapses after a migration, check the redirects before the content; the rest of the diagnosis is in the entry on website traffic drops.
The mistakes that cost traffic
- Chains and loops. A to B to C works, but should be rewritten as A to C and B to C. A loop never opens at all: the browser gives up after a fixed number of attempts.
- Mass redirects to the homepage. Technically a 301, in practice a wall: someone looking for a product page lands on a page that doesn't answer their question and goes back.
- JavaScript instead of the server. Google lists JavaScript redirects as the last resort, after server-side ones and after meta refresh, because rendering can fail.
- Browser cache. A 301 is stored by the client: if the target is wrong, anyone who has already visited that page keeps ending up in the wrong place even after the fix. While testing, use a 302 and switch to 301 once the target is confirmed.
- Trailing slash and capitals. To the server /page and /page/ are two different addresses, and the same goes for /Page. It is the most trivial cause of redirects that don't fire, and the entry on common URL problems goes into detail.
A canonical does not replace a 301
They are two signals with very different weights. A 301 takes the old page out of circulation: whoever requests it is moved on and the server no longer returns that content. The canonical tag leaves both pages reachable and suggests which one to index, which is useful when both versions have to stay online, such as variants with filter parameters. If the old page no longer needs to serve anyone, the canonical is the weak choice: how to set it up is in the entry on the canonical URL.
Frequently asked questions
A 301 says the move is permanent: Google uses the target as the canonical URL and shows it in the results. A 302 says it is temporary and leaves the original URL in the results. If the old page is not coming back, the correct code is 301.
Google recommends keeping it as long as possible, generally at least a year. In practice it is worth not removing it while external links still point to the old address, because that traffic keeps arriving even years later.
A 301 to a genuinely equivalent page does not cause any ranking loss documented by Google. The drops seen after a migration almost always come from something else: redirect chains, poorly matched targets, missing rules, content rewritten along with the URL.
According to Google documentation on site moves with URL changes, a medium-sized site can take weeks or more, and large sites longer. In the meantime the old and new addresses coexist in Search Console.
The command curl -I followed by the address shows the status code and the Location header without following the hop. A crawler such as Screaming Frog runs the same check on the whole list and shows the chains. The URL Inspection tool in Search Console tells you how Googlebot saw it.
Technically yes, but it is the choice that gives the worst results: someone looking for that content lands somewhere else and goes back. If there is no relevant target, a 404 or a 410 is more honest with the user and clearer for Google.
Something the industry rarely says: the redirects file ages badly and has no owner. After two migrations nobody knows which of the eight hundred rules are still needed, nobody dares delete one, and the file grows with every redesign. The habit that takes five seconds and pays back two years later is commenting each block with the date and the reason, as you would in a changelog, so whoever reopens that file knows what they are looking at. If the migration is a big one and you are the one inheriting that file, outside help on the SEO side costs less than the traffic lost putting it back together six months later.