HTTP 308 Permanent Redirect – Free, Online, Private
308 Permanent Redirect is a permanent move that keeps the method and body.
What HTTP 308 means
308 says the resource has a new URI and the client should remember it, and the follow-up request must use the same method and body. It fixes the POST-to-GET problem of 301. Caches may store it. Use it when a write URL has permanently moved and replaying the write at the new URL is correct.
308 Permanent Redirect belongs to the 3xx redirection class. Clients that only look at the class will group it with its neighbors. Clients that care about the exact code should use the narrower rule on this page, because the class is only the first digit.
When you see HTTP 308
When you see HTTP 308 Permanent Redirect, stop on that exact status line. 308 Permanent Redirect is a permanent move that keeps the method and body. The trace that usually produces it: An API versioned a write path and wanted clients to update their stored URL. The 3xx redirection class only tells you the first digit. A neighbor in that class is a different fault, and the fix on this page does not transfer to it.
Return 308 for a permanent move of an endpoint that receives POST, PUT, or PATCH. Return 301 if you are only moving browser navigations and you are comfortable with GET. Do not use 308 for a one-day maintenance bounce. That is 307. Send Location.
How to fix HTTP 308
To fix HTTP 308, change the condition that made the server choose Permanent Redirect. Update the stored URL. Replay the method and body once. Do not replay a non-idempotent POST in a loop if the new server also returns 308. Do not keep using the old URL. If the replay fails with a 5xx, retry the new URL according to the method's safety, not the old one. If the log line is a different code, leave this page. The mix-up people make with 308 is this one: 301 is the permanent redirect that may drop the method. 307 is the temporary redirect that keeps it. 308 is permanent and method-preserving.
- A client followed 308 and resent a non-idempotent POST, creating a second object because the first hop had already created one.
- A cache stored the 308 and kept sending users to a URL you later retired.
- Location was http on an https site and the client refused the downgrade.
An access log that only stores 308 is not enough to tell these apart. Keep the method, the path, and a request id. Do not keep the Authorization header or a request body that might be a token. The status explains the outcome. It is not a place to echo secrets back to the client either.
Example response
HTTP 308 Permanent RedirectHTTP/1.1 308 Permanent Redirect
Location: https://api.example.com/v2/items
The client repeats the original method against the new URL and should store that URL as the new target. If the first server already performed the write before redirecting, the replay duplicates it. Redirect before the side effect, or make the write idempotent.
What the client should do
Update the stored URL. Replay the method and body once. Do not replay a non-idempotent POST in a loop if the new server also returns 308.
308 may be cached like 301. A mistake sticks. Set Cache-Control if you are not sure the move is permanent.
Do not keep using the old URL. If the replay fails with a 5xx, retry the new URL according to the method's safety, not the old one.
Codes people confuse with HTTP 308
301 is the permanent redirect that may drop the method. 307 is the temporary redirect that keeps it. 308 is permanent and method-preserving.
Frequently asked questions
Why not 301 for an API?
301 may be followed as GET. 308 keeps POST, PUT, and PATCH.
Is 308 cached?
It may be. Treat it as sticky, the way you treat 301.
Can it duplicate a write?
Yes, if you perform the write and then redirect. Redirect first, or use an idempotency key.
What is the temporary equivalent?
307 Temporary Redirect.
What should I do first when I see HTTP 308?
Read the status as 308 Permanent Redirect specifically. 308 Permanent Redirect is a permanent move that keeps the method and body. Then check the cause that matches the request you sent, starting with: An API versioned a write path and wanted clients to update their stored URL.