301, 302 or 308? Picking the right redirect
What each code tells browsers and search engines, and how the wrong one leaks rankings or breaks POST requests
Updated Sep 30, 2026

What a redirect actually says
Every redirect is a short message from your server to whoever asked: "not here, go there, and here is how much to trust that". The URL is the "there". The status code is the "how much to trust it". Browsers, search engines, link previewers and API clients all read that second part and behave differently depending on it, which is why the wrong code causes bugs that look like nothing else: a link you updated an hour ago that still sends people to the old page, an API call that silently turns into a GET, a campaign URL that Google decided to index instead of your landing page.
There are seven 3xx codes in the HTTP spec. Three of them cover almost everything a short link ever needs.
The three codes you actually need
| Code | Meaning | Cached by browsers | Method preserved | Typical use |
|---|---|---|---|---|
| 301 | Moved permanently | Yes, aggressively | No, POST may become GET | Domain moves, retired URLs |
| 302 | Found, moved temporarily | No, by default | No, POST may become GET | Campaigns, bio links, anything you will re-point |
| 308 | Moved permanently, strict | Yes | Yes | API endpoints, webhooks, machine callers |
A 301 tells the client the move is final. Browsers store that answer and skip your server on the next visit. Search engines consolidate ranking signals onto the new URL and drop the old one from the index over time. It is the right code exactly once: when the old URL will never mean anything else again.
A 302 says the opposite: the resource is elsewhere for now, keep asking me. Nothing is cached unless you add cache headers yourself, the original URL stays the canonical one in search results, and every visitor goes through your server again, where your rules and analytics live.
A 308 is the strict sibling of 301. It is permanent, but the client must repeat the request exactly as it was, same method, same body. That last property is the whole reason it exists.
The POST-to-GET trap
The original HTTP specification allowed clients to change a POST into a GET when following a 301 or 302, and most browsers still do. That is harmless for a person clicking a link. It is destructive for a webhook or an API client: the receiver gets a GET with no body, returns 200 because the URL exists, and the sender concludes the delivery succeeded. Nothing was delivered.
If a machine calls the URL with anything other than GET, use 307 or 308. If you do not know who calls it, assume a machine eventually will.
$ curl -sI https://go.example.com/launch | head -2
HTTP/2 302
location: https://example.com/spring-launchWhy a short link should almost never be permanent
Short links exist to be re-pointed. A campaign target changes when the landing page is rebuilt. A QR code on packaging outlives three product pages. A bio link rotates weekly. The moment you serve any of those as a 301, the browsers that already followed it stop asking. You update the destination, the analytics flatline for returning visitors, and someone files the classic bug: "I changed the link but nothing happened".
This is not a rii.link quirk. It is how permanent redirects are designed to work, and it is why every rii.link redirect is a 302 unless you choose otherwise. In the dashboard the status code is a per-redirect setting, so the exceptions are still one click away.
What search engines do with each code
Google has said for years that no 3xx redirect loses ranking signals in itself. What differs is what gets indexed. After a 301 or 308, the destination becomes the indexed URL. After a 302 or 307, the original URL usually stays indexed and the destination is treated as a temporary stand-in. Both are correct behaviours for the right situation:
- Moving
example.com/blog/old-nametoexample.com/blog/new-namefor good: 301. You want the new URL to take over. - A short link
go.example.com/springpointing at this year's landing page: 302. You do not wantexample.com/spring-2026to inherit the short link's history and then vanish when the campaign ends.
The confusion usually comes from treating short links as if they were page moves. They are not. They are pointers, and pointers should stay temporary.
Rules of thumb
- Will this URL ever point somewhere else? Then 302. Campaigns, bio links, QR codes, seasonal targets, anything with an owner who might change their mind.
- Is it a real, final move? Domain migrations, retired product pages,
httptohttps,wwwto apex: 301. - Do machines call it with a body? Webhooks, API base URLs, form actions: 308 for permanent, 307 for temporary.
- Not sure? Start with 302. You can always upgrade a redirect to permanent later. You cannot un-cache a 301 from the world's browsers.
Setting the code on rii.link
Each redirect you build in the rii.link dashboard carries its own status code, chosen from 301, 302, 307 and 308, with 302 as the default; links created through the API always answer with a 302. Two neighbouring settings matter for the same reasons:
- Append original query params adds the visitor's original query string to the destination, so
?utm_source=newslettersurvives the hop and lands in your analytics. It is off by default. - Append original path carries the requested path over to the destination, so one catch-all 301 on an old domain moves every page to the new one, path preserved, and inbound links keep working.
Written by
Florian
Florian builds rii.link, the routing layer behind short links: redirects, dynamic responses and links that answer AI agents. He writes The Redirect about what happens between a click and its destination.


