307 Temporary Redirect

A temporary redirect that preserves the request method and body — a POST stays a POST at the new URL.

Quick Reference

Category3xx Redirection
RFCRFC 9110, Section 15.4.8
CacheableNo by default; cacheable if response includes explicit expiry headers
Method preservedYes — POST stays POST, PUT stays PUT
PermanentNo — clients must not update bookmarks or links

What 307 Temporary Redirect Means

HTTP 307 Temporary Redirect tells the client to repeat the exact same request — same method, same body — at the URL in the Location header. The original URL has not permanently moved; the redirect is a temporary detour. Clients should continue using the original URL for future requests.

307 was introduced to fix an ambiguity in 302. The HTTP/1.0 spec said 302 meant temporary redirect, but browsers historically treated a 302 response to a POST by re-sending the request as a GET to the new URL. This was convenient for form submissions but broke APIs that expected method preservation. 307 makes method preservation explicit and mandatory: a 307 to a POST must be re-sent as a POST.

The distinction from 308 is permanence. 307 = temporary redirect with method preservation. 308 = permanent redirect with method preservation. The same relationship as 302 (temporary, may change method) to 301 (permanent, may change method).

Why Method Preservation Matters

For browser navigation and GET requests, method preservation is irrelevant — any redirect code produces the same behavior. Method preservation becomes critical when:

  • An API client sends a POST with a JSON payload to an endpoint that has temporarily moved. The payload must be re-sent to the new URL. A 302 might cause some clients to lose the body and send a GET instead.
  • A PUT request to update a resource is redirected temporarily while maintenance is in progress. The client must PUT to the new URL, not GET from it.
  • A DELETE request hits a temporarily relocated endpoint. The delete must happen at the new URL, not a silent failure.

Modern HTTP clients (curl, Python requests, the Go HTTP client, browser fetch API) follow 307 correctly by re-sending with the original method. Older HTTP libraries and some HTTP/1.0 clients may not; always verify behavior when working with legacy integrations.

Wire Format

HTTP/1.1 307 Temporary Redirect
Location: https://api.example.com/v2/orders
Cache-Control: no-store

The Location header must be an absolute URI. Relative URIs are not valid in redirect responses per RFC 9110, though most clients accept them in practice.

No response body is required, but including a brief HTML body with a link to the new URL helps users whose browsers do not follow redirects automatically:

HTTP/1.1 307 Temporary Redirect
Location: https://api.example.com/v2/orders
Content-Type: text/html

<a href="https://api.example.com/v2/orders">Redirecting...</a>

Server Configuration Examples

nginx

# Temporary redirect, preserves method
location /api/v1/ {
    return 307 https://api.example.com/v2/;
}

Apache

# Redirect directive always sends 302 unless status is specified
Redirect 307 /api/v1/ https://api.example.com/v2/

Express.js

// Default res.redirect() sends 302 — specify 307 explicitly
app.post('/api/v1/orders', (req, res) => {
  res.redirect(307, 'https://api.example.com/v2/orders');
});

Cloudflare Workers

export default {
  async fetch(request) {
    if (request.url.includes('/api/v1/')) {
      const newUrl = request.url.replace('/api/v1/', '/api/v2/');
      return Response.redirect(newUrl, 307);
    }
    return fetch(request);
  }
}

Client Behavior

When a client receives a 307, it must:

  • Re-send the request to the URL in the Location header
  • Use the same HTTP method as the original request
  • Re-send the original request body (for POST, PUT, PATCH)
  • Re-send relevant request headers (Content-Type, Authorization, etc.)
  • Not cache the redirect unless explicit caching headers are present

Curl follows 307 by default when using -L, and it preserves the method. Python requests follows 307 with allow_redirects=True and preserves the method. Browser fetch follows 307 automatically in the same-origin case; cross-origin 307 redirects from a POST will trigger a CORS preflight at the new origin.

One edge case: if a 307 response includes no body hint and the client sends a POST with a large body, the client may need to buffer the entire body before the redirect to be able to re-send it. Most HTTP client libraries handle this transparently for in-memory payloads; streaming uploads need special handling.

Practical Use Cases

API versioning transitions: When deprecating v1 of an API while keeping it operational, redirect v1 endpoints to v2 with 307. Clients that assume POST stays POST will work correctly.

Maintenance windows: During a database migration, redirect write operations (POST, PUT, DELETE) to a secondary endpoint or a write-buffer service. 307 ensures the write is retried at the new location rather than being silently dropped.

Load balancing between clusters: A gateway can send 307 to redistribute a specific request to a less loaded cluster. This is unusual — transparent proxying is more common — but valid for specific overflow scenarios.

OAuth flows: OAuth authorization servers sometimes issue 307 redirects during the authorization code flow. The redirect must preserve any POST body containing credentials or tokens.

307 vs Related Redirect Codes

CodeTemporary?Preserves method?Typical use
301 Moved PermanentlyNoMay not (browsers change POST to GET)Permanent URL change for GET resources
302 FoundYesMay not (browsers change POST to GET)Temporary redirect; legacy form submissions
303 See OtherYesNo — always GETPost/Redirect/Get pattern after form submission
307 Temporary RedirectYesYes, mandatoryTemporary redirect where method must be preserved
308 Permanent RedirectNoYes, mandatoryPermanent redirect where method must be preserved

Frequently Asked Questions

Why do most web frameworks default to 302 instead of 307?

Historical inertia. 302 was in HTTP/1.0, and the browser behavior of converting POST to GET on a 302 turned out to be useful for form submissions (the Post/Redirect/Get pattern). 307 came later in HTTP/1.1. Framework defaults were set in the 302 era and most have not changed them. Always specify 307 explicitly when you need method preservation.

Does 307 affect SEO?

307 is temporary, so search engines do not transfer PageRank or update indexed URLs when they follow a 307. If a URL has permanently moved, use 301 or 308 instead. Using 307 for a permanent change causes search engines to continue indexing the old URL.

Can I cache a 307 response?

Not by default. 307 is not cacheable without explicit Cache-Control or Expires headers. To allow caching, add Cache-Control: max-age=3600 (or similar). Be careful: a cached 307 means clients will be redirected repeatedly without contacting the original server, which may be undesirable if the redirect is truly temporary.

What is the difference between 307 and 302 in practice today?

For GET and HEAD requests: no practical difference. For POST, PUT, PATCH, DELETE: 307 guarantees the method is preserved. Modern browsers and HTTP libraries treat 302 as a de-facto method-preserving redirect as well, but this behavior is not guaranteed by the spec. Use 307 when method preservation is a correctness requirement.