Use 301 or 308 for permanent moves and 302, 303 or 307 for temporary ones. Pick 307 or 308 when the method and body must stay the same, and 303 after a POST so a refresh does not resubmit. The older 301 and 302 leave method handling ambiguous.
The decision table
This table follows MDN's guide to redirections:
| Code | Name | Type | Method handling |
|---|---|---|---|
| 301 | Moved Permanently | Permanent | GET unchanged, others may or may not become GET |
| 308 | Permanent Redirect | Permanent | Method and body unchanged |
| 302 | Found | Temporary | GET unchanged, others may or may not become GET |
| 303 | See Other | Temporary | Others change to GET, body lost |
| 307 | Temporary Redirect | Temporary | Method and body unchanged |
MDN explains that the "may or may not" wording for 301 and 302 reflects browser behavior. The specification did not intend method changes, so 308 and 307 were created to remove the ambiguity.
Permanent vs temporary
Permanent redirects tell crawlers to replace the old URL with the new one. Temporary redirects mean the new URL should not be remembered. Use permanent only when you are sure, because clients and caches may keep the mapping a long time. According to the HTTP specification, 301 and 308 are cacheable by default while the temporary codes are not unless the response carries explicit freshness information. Verify this against the current spec for your clients.
Common use cases
- Redirecting example.com to www.example.com or to a renamed domain.
- Forcing HTTPS by redirecting http requests to https. Pair this with HSTS, covered in HSTS explained.
- Keeping old links alive after restructuring a site.
- Responding 303 after a POST, PUT or DELETE so reloading the page does not resend the request.
- Pointing a long running request to a status page with 303.
HTTP, HTML and JavaScript redirects
MDN recommends HTTP redirects whenever possible. A meta refresh redirect works when you do not control the server, and a JavaScript redirect only runs on clients that execute scripts. HTTP redirects run first. If HTTP and meta redirects fall out of sync you can get an infinite loop. Each redirect adds a round trip, so keep chains short.
Security notes
- Validate targets. A redirect built from user input is an open redirect. Use an allow list. See open redirect safe patterns and the OAuth redirect URI checklist.
- Keep CR and LF out of Location. See response splitting.
- Do not leak credentials. Some clients have forwarded authorization headers across redirects, as in a past requests library advisory. Check how your client behaves on cross host redirects.
- Avoid downgrades. Never redirect from https to http.
Where Safeguard fits
Safeguard does not host or route your site. It scans the dependencies and SBOMs behind your applications, including HTTP client and server libraries, for known issues. You can run a free scan at gold.safeguard.sh/scan.
Quick check
Which redirect keeps a POST as a POST?
307 for temporary and 308 for permanent keep the method and body unchanged.
What is 303 for?
Sending the client to a GET page after a write, so refreshing does not resubmit the request.
Sources
Last reviewed: 19 October 2026.