# 307 Temporary Redirect

> Temporary redirect that preserves the HTTP method. Learn when to use 307 instead of 302 for method-sensitive redirects.

Source: https://howhttpworks.com/status-codes/307
Last reviewed: 2026-10-04

> **TL;DR:** 307 Temporary Redirect is 302 with a guarantee: the client must repeat the same method and body at the new `Location`. Use it for temporary redirects of POST/PUT/DELETE; use 303 when you want the follow-up to be a GET.

## What it means

```http
POST /api/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"sku":"A1","qty":2}

HTTP/1.1 307 Temporary Redirect
Location: https://api-eu.example.com/api/orders
```

The client resends `POST /api/orders` with the same JSON body to the new host (RFC 9110 section 15.4.8). With a 302, browsers and many HTTP libraries switch to GET and drop the body. Like 302, a 307 is not cacheable unless the response carries explicit freshness headers.

## The 307 you did not send

Chrome DevTools shows `307 Internal Redirect` with `Non-Authoritative-Reason: HSTS` when the browser upgrades `http://` to `https://` by itself because of a cached `Strict-Transport-Security` policy. No network request happens and no server is involved, so server config cannot fix it. Clear the entry at `chrome://net-internals/#hsts` or correct the policy. See [Strict-Transport-Security](https://howhttpworks.com/headers/strict-transport-security).

## Redirect behavior matrix

| Code | POST becomes GET? | Permanent | Typical use                      |
| ---- | ----------------- | --------- | -------------------------------- |
| 301  | Usually yes       | Yes       | Moved pages                      |
| 302  | Usually yes       | No        | Login and promo redirects        |
| 303  | Always            | No        | After a POST, show a result page |
| 307  | Never             | No        | Temporary API/endpoint redirect  |
| 308  | Never             | Yes       | Endpoint moved for good          |

Compare in detail: [302 vs 307](https://howhttpworks.com/compare/302-vs-307).

## Gotchas

- **Request bodies must be replayable.** A client that streamed a large upload may be unable to resend it, and some libraries fail with an error rather than follow the 307. curl replays the body.
- **Credentials on cross-origin redirects.** Browsers and most HTTP libraries strip `Authorization` when a redirect leaves the origin, so authenticated calls can arrive at the new host as 401.
- **CORS preflight.** A preflight (OPTIONS) response must not be a redirect; browsers reject it with "Redirect is not allowed for a preflight request". Redirect the actual request, not the OPTIONS.
- **No SEO transfer.** Search engines treat 307 as temporary, like 302.
- **Next.js:** `permanent: false` in `redirects()` sends 307; `permanent: true` sends 308.

## Implementation

### Express

```javascript
app.post('/api/orders', (req, res) => {
  res.redirect(307, 'https://api-eu.example.com/api/orders')
})
```

### nginx

```nginx
location /api/ {
    return 307 https://api-eu.example.com$request_uri;
}
```

### Cloudflare

Choose status code 307 in a Single Redirect rule or a Bulk Redirect to preserve the method.

## Reproduce with curl

```bash
curl -si -L -X POST -H 'Content-Type: application/json' \
  -d '{"sku":"A1","qty":2}' https://api.example.com/api/orders
```

Add `-v` and confirm the second request line still reads `POST` and carries the body.

## Related

- [302 Found](https://howhttpworks.com/status-codes/302)
- [303 See Other](https://howhttpworks.com/status-codes/303)
- [308 Permanent Redirect](https://howhttpworks.com/status-codes/308)
- [Location header](https://howhttpworks.com/headers/location)
