HTTP 308

308 Permanent Redirect

Redirect

The target resource has been assigned a new permanent URI and any future references should use the new URI. Like 307, the client must not change the request method or body when following the redirect. 308 is the modern, strict-method equivalent of 301. It gives search engines the same canonical-update signal as 301 while guaranteeing API clients will not silently downgrade POST/PUT/DELETE to GET.

When does this happen?

Use 308 for permanent redirects where method preservation matters. The canonical example is an API endpoint that has moved permanently. POST /v1/old-endpoint should 308 to POST /v2/new-endpoint so clients reissue with the same body and the action completes. Search engines treat 308 the same as 301: they update the canonical URL and transfer link equity. Browsers cache 308s aggressively, similar to 301, so shipping the wrong destination is hard to undo in clients that have already seen it. The Location header is required. For HTML pages, 301 is still the more common choice simply because it is older and more widely understood by tooling, but 308 is strictly more correct anywhere a method might be non-GET. Older HTTP libraries (curl < 7.49, released May 2016, when RFC 7538 308 support landed; very old .NET) may not handle 308 correctly. If your audience includes legacy clients, test before shipping.

Common causes

How to fix it

Real-world examples

API v1 is sunsetted and POST /v1/orders should permanently move to /v2/orders.
Server returns 308 with Location: /v2/orders. SDKs reissue POST with the same JSON body to the new path. The migration is invisible to callers.
Webhook receiver moves from webhooks.example.com to events.example.com.
Old URL returns 308. Senders that follow redirects reissue the POST with the same payload to the new host and webhook delivery succeeds.
Domain consolidation merges api.legacy.com into api.example.com with the same path structure.
Old domain returns 308 for every request. Clients preserve method and body and the legacy domain can eventually be retired.
PUT endpoint /v1/configs/{id} renamed to /v1/settings/{id} after an internal refactor.
Server returns 308 with the new Location. Clients PUT the same config body to the new URL and the update lands correctly.

Debugging

How it differs from related codes

HTTP 301

Both are permanent. 301 historically allowed clients to downgrade POST to GET; 308 forbids it. Use 308 for APIs and 301 for plain HTML page moves where method is always GET.

HTTP 307

307 is temporary, 308 is permanent. Both preserve the method. Pick based on whether you intend search engines and clients to update the canonical URL.

HTTP 302

302 is temporary and may downgrade method. 308 is permanent and preserves method. Opposite on both axes. They are rarely interchangeable.

Related status codes

301 302 303 307 404 410

See HTTP 308 in your redirect chains?

Check your URLs with checkredirects.io