{ }HttpStatus.com

308 Permanent Redirect

The resource has permanently moved, and the request method and body must be repeated exactly at the new URL.

Defined in RFC 9110 §15.4.9

What 308 means

A 308 response indicates the target resource has been permanently assigned a new URL, and, unlike 301, it explicitly requires that the request method and body be repeated exactly when following the redirect. It is effectively 301 with the method-preservation guarantee that 307 provides for temporary redirects, making it the correct choice whenever a permanent move must not risk turning a POST or PUT into a GET.

308 was introduced later than the original HTTP/1.1 redirect codes specifically to close the gap left by 301’s ambiguous, historically inconsistent handling of non-GET methods. Because 301 is universally treated as GET-only in deployed browsers, any API or site migration that needs to permanently move an endpoint accepting POST, PUT, PATCH, or DELETE should use 308 instead, so clients that correctly implement the spec replay the same method and payload at the new location.

Like 301, browsers and caches are permitted to treat 308 as long-lived and cache it aggressively, and search engines treat it the same as 301 for the purpose of transferring ranking signal and consolidating indexing to the new URL. This makes 308 the right tool for permanently moving an API resource or a state-changing endpoint while still getting the SEO and caching benefits associated with permanence.

Support for 308 arrived later in some HTTP client libraries and older browsers than support for 301/302/307, so a small minority of very old clients may not follow it automatically. Modern browsers, CDNs, and virtually all current HTTP libraries handle it correctly, and it is now the recommended status for any permanent, method-preserving redirect in new API designs.

Common causes

  • An API endpoint accepting POST, PUT, or PATCH is permanently renamed or moved to a new path or host.
  • A domain or API version is permanently retired and all requests, including non-GET ones, must move to the replacement without losing method or body.
  • A service migrates from HTTP to HTTPS or across hosts while needing to preserve state-changing request semantics.
  • A CDN or edge configuration enforces a permanent canonical host and must not silently downgrade non-GET requests to GET.
  • A framework’s permanent-redirect helper is deliberately configured to use 308 instead of 301 to protect non-idempotent operations.

How to fix a 308

If you are the client (browser user or API caller)

  • Update stored URLs to the new Location, exactly as you would for a 301, since the move is permanent.
  • Confirm your HTTP client preserves method and body on 308; most modern libraries do, but very old ones may not.
  • Cap the number of redirect hops followed and detect redirect loops, especially in automated or server-to-server clients.
  • Prefer requesting the new canonical URL directly once known, to skip the redirect round trip on future calls.

If you run the server

  • Use 308 instead of 301 whenever the permanently moved resource accepts non-GET methods that must be preserved.
  • Set Location to an absolute, canonical URL and avoid chaining through intermediate redirects.
  • Set explicit Cache-Control if you want finer control than the default aggressive caching browsers may apply to permanent redirects.
  • Update sitemaps, canonical link tags, and internal references to the new URL so traffic does not keep round-tripping through the redirect.

Example

POST /api/v1/subscribe HTTP/1.1
Host: old-api.example.com
Content-Type: application/json

{ "email": "user@example.com" }

HTTP/1.1 308 Permanent Redirect
Location: https://api.example.com/v2/subscribe

POST /v2/subscribe HTTP/1.1
Host: api.example.com
Content-Type: application/json

{ "email": "user@example.com" }
A permanently moved API endpoint redirects a POST while preserving method and body.

Try it live

Our free status responder returns a real HTTP 308 you can point tests, monitors or a browser at.

GET https://mcp.httpstatus.com/status/308

Related status codes

Tools for debugging this