307 Temporary Redirect Explained

What the HTTP 307 Temporary Redirect status code means, how it differs from 302 by preserving the request method, HSTS internal 307s, and when to use 307 vs 302.

A 307 Temporary Redirect tells the browser: "The resource you requested is temporarily at a different URL. Go there instead, and use the exact same HTTP method you used for this request." If the original request was a POST, the redirected request must also be a POST. If it was a PUT, it stays a PUT. The method and request body are preserved.

That method preservation is the entire reason 307 exists. The older 302 status code was supposed to do the same thing, but browsers historically changed POST requests to GET when following a 302. The 307 code was introduced in HTTP/1.1 to give developers a temporary redirect that guarantees the method stays the same.

For a comparison of all redirect status codes, see our HTTP Redirect Guide and HTTP Redirect Status Codes.

What the spec says

RFC 9110 defines the 307 status code in Section 15.4.8: [1]

The 307 (Temporary Redirect) status code indicates that the target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI.

The key word is "MUST NOT." This is not a suggestion. Clients are required to keep the same method. Compare this to the 302 definition, which says clients "might" change the method. 307 removes the ambiguity.

The spec also says:

If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

In practice, browsers do follow 307 redirects for POST requests without asking the user. But the spec's caution reflects a real concern: automatically resubmitting a POST to a different URL could have side effects (like processing a payment twice). Some older or more cautious HTTP clients may prompt the user before following a 307 on a POST.

The difference from 302

Both 302 and 307 are temporary redirects. They tell the client that the resource has temporarily moved and that future requests should still go to the original URL. The difference is what happens to the HTTP method.

With a 302:

POST /api/submit  -->  302 Found  -->  GET /api/new-submit
                                        (method changed, body dropped)

The browser changes the POST to a GET. The request body is gone. This is how every major browser handles 302 responses to POST requests, even though the original spec said not to.

With a 307:

POST /api/submit  -->  307 Temporary Redirect  -->  POST /api/new-submit
                                                     (method preserved, body intact)

The browser sends the same POST request to the new URL. The method and body are preserved.

Here is what these look like at the protocol level:

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

{"order_id": 12345, "action": "confirm"}

Server responds with a 307:

HTTP/1.1 307 Temporary Redirect
Location: https://example.com/api/v2/submit

The browser resends the exact same request to the new URL:

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

{"order_id": 12345, "action": "confirm"}

For GET requests, 302 and 307 behave identically. GET stays GET in both cases. The distinction only matters for POST, PUT, PATCH, DELETE, and other non-GET methods.

For a broader comparison of temporary vs permanent redirects, see 301 vs 302 Redirects.

The HSTS internal 307

If you have ever opened your browser's developer tools and seen a "307 Internal Redirect" with a note about HSTS, that is a different thing from a normal 307.

HTTP Strict Transport Security (HSTS) is a mechanism where a website tells the browser: "From now on, always use HTTPS to connect to me. Never use plain HTTP." The browser stores this instruction and enforces it locally.

When you try to visit http://example.com and the browser has an HSTS policy for that domain, the browser does not send the HTTP request to the server at all. Instead, it internally redirects itself to https://example.com and shows this as a "307 Internal Redirect" in the developer tools.

http://example.com  --307 (internal)--> https://example.com

This 307 never touches the network. No request goes to the server. The browser handles it entirely on its own. You will see it in Chrome's Network tab with a note like "(Internal Redirect)" or "HSTS" in the initiator column.

The HSTS 307 is faster than a server-side redirect because there is no network round trip. It is also more secure because the browser never sends an unencrypted HTTP request, even briefly. For details on setting up HTTPS redirects, see HTTP to HTTPS Redirect Guide.

When to use 307

API redirects

When an API endpoint temporarily moves and clients may be sending POST, PUT, PATCH, or DELETE requests, a 307 ensures those requests reach the new endpoint with their method and body intact.

HTTP/1.1 307 Temporary Redirect
Location: https://api.example.com/v2/orders

An API client sending a POST to create an order will have that POST forwarded correctly. With a 302, the POST would become a GET, and the order creation would fail.

Form handling during migrations

You are migrating your form processing endpoint to a new server. During the transition, you redirect form submissions from the old endpoint to the new one. A 307 preserves the POST and the form data.

POST /old-form-handler  --307-->  POST /new-form-handler

A 302 here would turn the POST into a GET, losing all the form data.

Load balancing and failover

When a server is temporarily overloaded or down, a load balancer might redirect traffic to a backup server. For API traffic that includes POST and PUT requests, a 307 ensures those requests are forwarded correctly.

Temporary API maintenance

You need to temporarily route API traffic to a different server or endpoint while performing maintenance. A 307 keeps all request methods working correctly during the redirection.

HSTS enforcement

As described above, browsers use 307 internally to enforce HSTS policies. You do not configure this directly. It happens automatically when the browser has stored an HSTS header from a previous visit to your site. The server-side setup is adding the Strict-Transport-Security header to your HTTPS responses:

Strict-Transport-Security: max-age=31536000; includeSubDomains

When 302 is fine instead

For the majority of web redirects, you do not need 307. Here is when 302 is the better choice:

Regular page redirects. If you are redirecting one web page to another and all traffic is browser-based GET requests, 302 and 307 are functionally identical. Use 302 because it is more widely recognized and has better compatibility with older clients.

Temporary landing page changes. Redirecting your homepage to a seasonal sale page, a maintenance page, or a campaign page. These are all GET-to-GET redirects where method preservation is irrelevant.

Geolocation routing. Sending visitors to a regional version of your site. These are GET redirects in a browser context. 302 works perfectly.

A/B testing. Routing visitors to test variants of a page. Standard GET traffic, no method preservation needed.

The rule: if the original request is always a GET (which it is for any URL that users visit in a browser), 302 and 307 produce the same result. Use 302 for simplicity. Reach for 307 when non-GET methods are involved.

Browser support

307 is supported by all modern browsers:

  • Chrome 1+ (2008)
  • Firefox 1+ (2004)
  • Safari 1+ (2003)
  • Edge 12+ (2015)
  • Opera 6+ (2001)

The 307 status code was introduced in RFC 2616 (HTTP/1.1) in 1999. It has had over 25 years of browser support. There are no practical compatibility concerns.

Modern HTTP client libraries (axios, fetch, requests, HttpClient, OkHttp) all handle 307 correctly, preserving the method and body when following the redirect.

Implementation examples

Nginx

# Temporary redirect preserving method
location = /api/orders {
    return 307 https://backup-api.example.com/api/orders;
}

Apache

# Temporary redirect preserving method
Redirect 307 /api/orders https://backup-api.example.com/api/orders

# Pattern-based
RewriteEngine On
RewriteRule ^api/v1/(.*)$ https://backup-api.example.com/api/v1/$1 [R=307,L]

Node.js / Express

app.all('/api/orders', (req, res) => {
  res.redirect(307, 'https://backup-api.example.com/api/orders');
});

Note the use of app.all() to match every HTTP method. If you used app.post(), only POST requests would be caught. Since the point of 307 is to handle any method, app.all() is the right choice.

Python / Flask

from flask import redirect

@app.route('/api/orders', methods=['GET', 'POST', 'PUT', 'DELETE'])
def orders():
    return redirect('https://backup-api.example.com/api/orders', code=307)

307 vs 308

The relationship between 307 and 308 mirrors the relationship between 302 and 301:

                    May change method       Must preserve method
                    -----------------       --------------------
Permanent:          301 Moved Permanently   308 Permanent Redirect
Temporary:          302 Found               307 Temporary Redirect

Both 307 and 308 preserve the HTTP method. The difference is permanence:

  • 307: Temporary. The original URL is still the official one. Clients should keep using it.
  • 308: Permanent. The original URL should be updated to the new one. Clients should switch.

Use 307 when the redirect will eventually be removed. Use 308 when it is permanent and method preservation matters (like an API version migration).

Caching behavior

307 responses are not cached by default. [1] Each time a client hits the original URL, it checks with the server, which can then decide whether to redirect again or serve the resource directly.

If you want to cache a 307 (unusual, but possible for reducing server load), set explicit cache headers:

HTTP/1.1 307 Temporary Redirect
Location: https://backup.example.com/api/orders
Cache-Control: max-age=300

That would cache the redirect for five minutes. For most use cases, you want the default no-cache behavior so you can remove the redirect at any time and have clients immediately see the change.

SEO implications

Search engines treat 307 the same way they treat 302: as a temporary redirect. [2] The original URL stays in the index. Ranking signals are not permanently transferred to the new URL.

For standard website pages, there is no SEO difference between 302 and 307. Google processes both as "this is temporary, keep the old URL." If you are using 307 for API endpoints (the primary use case), SEO is typically not a concern because APIs are not indexed by search engines.

307 is for method preservation, not SEO

You should never choose between 302 and 307 based on SEO. They are treated identically by search engines. The only reason to pick 307 over 302 is when you need the HTTP method to be preserved through the redirect. For GET-only browser traffic, stick with 302.

Common mistakes

Using 307 for regular page redirects

If every request to the URL is a GET (which is true for any page that users visit in a browser), 307 adds no value over 302. It is not wrong, but it signals to other developers that method preservation is important for this redirect, which is misleading when all traffic is GET.

Mixing 307 and 301 in a chain

If you chain a 307 into a 301, the 301 hop can change the method to GET. Method preservation only applies to the specific hop that uses 307 or 308.

POST /a  --307-->  POST /b  --301-->  GET /c
                                       (method changed at the 301)

If method preservation matters across the full chain, every hop needs to be 307 or 308. Better yet, avoid chains entirely and redirect directly to the final destination. See Redirect Chains Explained.

Confusing HSTS 307 with server 307

The HSTS "307 Internal Redirect" in browser developer tools is not a real server response. It is the browser redirecting itself. If you see a 307 in the Network tab and are confused about where it came from, check if it is labeled as an internal redirect. If so, it is HSTS, not your server configuration.

Forgetting that POST resubmission has side effects

A 307 redirect on a POST request means the browser will resend the POST to a different URL. If the new endpoint processes the POST (like creating an order or charging a credit card), make sure that is what you intended. The POST is not just forwarded as data; it is executed at the new destination.

The bottom line

307 Temporary Redirect exists for one specific job: temporary redirects that must preserve the HTTP method and request body. If your original request is a POST and the temporary destination needs to receive that POST, use 307. If all your traffic is GET requests in a browser, use 302. The choice is straightforward once you know what kind of requests your URL handles.

References

  1. IETF, "RFC 9110 - HTTP Semantics, Section 15.4.8: 307 Temporary Redirect," June 2022. https://httpwg.org/specs/rfc9110.html#status.307
  2. Google, "Redirects and Google Search," Google Search Central, 2024. https://developers.google.com/search/docs/crawling-indexing/301-redirects

Never miss a broken redirect

Trace redirect chains and detect issues before they affect your users and SEO. Free instant tracing.

Try Redirect Tracer