A 301 redirect is a server response that says a URL has moved permanently. Browsers follow it, and Google treats the target as the canonical URL, so ranking signals move with it. Use 301 or 308 for permanent moves, 302 or 307 only when the old URL is coming back.
Most redirect problems I see are not missing redirects. They are redirects that technically work and still leak: a 302 left over from a staging setup, a chain of four hops because http, www and a trailing slash each got their own rule, or a migration that sent three thousand product pages to the homepage. All of these return a working page in the browser. Google reads them differently.
What a 301 redirect does for SEO
A 301 is the HTTP status “Moved Permanently”. The server answers the old URL with that code and a Location header pointing at the new one. For a user it’s invisible. For Google it’s a strong canonical signal: according to the redirect documentation on Google Search Central, the target of a permanent redirect is treated as the canonical URL, and the old one drops out of results over time.
That’s why the 301 is the backbone of every domain change without losing rankings. Links pointing at the old address keep working, and their value flows to the new one.
301 vs 302 and the other redirect types
Google’s own table is short enough to memorise:
| Type | Google treats it as | Use it for |
|---|---|---|
| 301 Moved Permanently | Permanent, target becomes canonical | Domain moves, URL restructures, http to https |
| 308 Permanent Redirect | Permanent, same as 301 | Same, when the method must stay (POST stays POST) |
| 302 Found / 303 / 307 | Temporary, source may stay in results | Maintenance pages, A/B tests, geo or login bounces |
| meta refresh, 0 seconds | Permanent | Static hosting where you can’t touch the server |
| meta refresh, more than 0 seconds | Temporary | Rarely a good idea |
JavaScript location | Permanent, if Google renders it | Last resort only |
The practical rule: if the old URL is never coming back, send a 301. A 302 that stays in place for years leaves Google to work out on its own which URL you meant, and there’s no reason to make it guess.
301 redirect in nginx
For a whole domain moving to a new one, give the old domain its own server blocks and return early. No rewrite, no regex.
server {
listen 80;
listen [::]:80;
server_name old-example.com www.old-example.com;
return 301 https://new-example.com$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name old-example.com www.old-example.com;
ssl_certificate /etc/letsencrypt/live/old-example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/old-example.com/privkey.pem;
return 301 https://new-example.com$request_uri;
}
$request_uri contains the path and the query string, so /shop/shoes?colour=red lands on the same path at the new domain. The HTTPS block matters: plenty of backlinks and bookmarks already use https://old-example.com, and without a valid certificate on the old host those visitors get a browser warning instead of a redirect. On nginx older than 1.25.1, drop the http2 on; line and write listen 443 ssl http2; instead.
Single pages go inside the main site’s server block:
location = /old-page/ {
return 301 /new-page/;
}
Run nginx -t before systemctl reload nginx. A typo there takes the whole site down, not just the redirect.
301 redirect in Apache (.htaccess)
On shared hosting you usually only get .htaccess. With mod_rewrite a full domain move looks like this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old-example\.com$ [NC]
RewriteRule ^(.*)$ https://new-example.com/$1 [R=301,L]
Apache appends the original query string automatically as long as the target URL contains none, so ?colour=red survives. For a handful of single pages, mod_alias is easier to read:
Redirect 301 /old-page/ https://new-example.com/new-page/
Don’t mix the two styles for the same URLs. mod_alias and mod_rewrite run in different phases, and mixed rules are a common source of loops.
301 redirect with Cloudflare Redirect Rules
If the old domain has no server any more, Cloudflare can answer the redirect at the edge. Under Rules, create a Single Redirect:
- When incoming requests match: custom filter expression
(http.host eq "old-example.com") or (http.host eq "www.old-example.com") - Then: URL redirect, type Dynamic
- Expression:
concat("https://new-example.com", http.request.uri.path) - Status code: 301
- Preserve query string: on
One catch trips people up regularly. Cloudflare only sees traffic for hostnames whose DNS record is proxied (orange cloud). If the domain has no origin, create a dummy record such as A @ 192.0.2.1 and A www 192.0.2.1, both proxied. The address comes from a range reserved for documentation, so nothing is ever served from it; the redirect fires before Cloudflare would try to connect.
Testing a 301 redirect with curl
The browser hides too much, because it caches 301s aggressively. Use curl:
curl -sI "http://www.old-example.com/shop/shoes?colour=red"
HTTP/1.1 301 Moved Permanently
Server: nginx
Location: https://new-example.com/shop/shoes?colour=red
Exactly one hop, permanent, path and query intact. To see the full chain including the final status, add -L and filter:
curl -sIL http://www.old-example.com/shop/ | grep -iE "^(HTTP|location)"
If you see two or three HTTP/1.1 301 lines before the 200, you have a chain.
Redirect chains and loops
Googlebot follows up to 10 hops, but Google’s site move guide asks you to redirect straight to the final destination and, if that’s impossible, keep chains to about three hops. Chains usually grow by accident: a 2019 http-to-https rule, a 2021 www rule and a 2026 domain move, each correct in isolation. The fix is to rewrite the old rules so every variant points at the newest URL directly.
Loops are louder. The browser shows “too many redirects”, and curl -L keeps hopping until it hits its limit. The classic cause is an https redirect on the origin combined with Cloudflare set to “Flexible” SSL, where Cloudflare talks http to the origin, which redirects to https, which Cloudflare fetches over http again. Setting SSL mode to Full (strict) ends it.
How long to keep 301 redirects
Google recommends at least a year for a site move. My advice is simpler: keep them as long as you own the old domain, and keep the old domain. Renewing a domain costs €14.99 a year for a .com; losing it means someone else can register it and inherit every backlink you spent years earning. Our guide to Search Console’s Change of Address tool covers the 180-day window Google uses on its side.
If you’re consolidating several names onto one site, the same rules apply, with a few twists covered in running multiple domains on one website.
Before you register a new target domain, check the current price list for renewal costs as well as the first year, and run your shortlist through the domain availability search. If it’s a .com you’re after, the .com details page shows the yearly price that also applies on renewal.
Step by step
- Decide the target for every old URLExport the old URLs from your sitemap or analytics and map each one to its closest new URL. Mark pages without an equivalent for a 404 or 410.
- Pick the layer that does the redirectUse the web server (nginx, Apache) if you control it, the CDN (Cloudflare Redirect Rules) if the old domain only needs to forward, or the CMS as a last resort.
- Write the rules with a permanent status codeUse return 301 in nginx, R=301 in Apache mod_rewrite, or status 301 in a Cloudflare Single Redirect. Keep the path and query string.
- Remove chainsPoint every old URL straight at its final destination, including the http and www variants, so no request needs more than one hop.
- Test with curlRun curl -sI against old URLs and check for exactly one 301 with the right Location header, then a 200 on the target.
- Update internal links and canonicalsChange internal links, canonical tags, hreflang and the sitemap to the new URLs, so the redirects only serve visitors and crawlers arriving from outside.
Found your domain? You can check and register it directly at compare domain prices – yearly price from €2.99.
FAQ
Does a 301 redirect lose PageRank?
No. Google's site move documentation says 301 and other permanent redirects don't cause a loss in PageRank. Rankings can still wobble during a move, because Google has to recrawl and reprocess the new URLs, but that is not a penalty for redirecting.
What is the difference between a 301 and a 308 redirect?
Both are permanent, and Google treats them the same way. The difference is for clients: a 308 forbids changing the request method, so a POST stays a POST. For ordinary page moves either works; 301 has broader support in old tools and CMS plugins.
How long should I keep a 301 redirect in place?
Google recommends at least one year for site moves. Keeping them longer costs almost nothing and catches old bookmarks, printed links and backlinks that nobody will ever update. Dropping them after a year is a choice, not a requirement.
Can I redirect all old pages to the homepage?
You can, but Google advises against it. Mass redirects to an unrelated page can be treated like soft 404s, so the signals of the old pages don't carry over. Map each old URL to its closest equivalent, or return 404 or 410 if there is none.