The resource is temporarily located at a different URL, and the client must repeat the request using the same HTTP method. Unlike 302, a 307 redirect guarantees that a POST request stays a POST and is not changed to GET by the browser.
HTTP 307 Temporary Redirect is a redirection status code introduced in HTTP/1.1 to address a specific problem with the older 302 Found code. When a server returns 307, it instructs the client to resend the request to the URL specified in the Location header using the exact same HTTP method. A POST remains a POST, a PUT remains a PUT, and a DELETE remains a DELETE. This strict method preservation is the key difference between 307 and 302, which historically allowed browsers to change POST to GET.
The creation of 307 was motivated by real-world browser behavior. When HTTP/1.0 defined 302, the intent was for browsers to preserve the request method during redirection. However, early browsers implemented 302 by changing POST requests to GET, dropping the request body entirely. This broke form submissions and API calls that relied on POST data being forwarded to the new URL. By the time HTTP/1.1 was standardized, this method-changing behavior was so entrenched that it could not be corrected for 302, so 307 was introduced as a new code with a strict guarantee.
Modern HTTPS enforcement through HTTP Strict Transport Security (HSTS) uses 307 internally. When a browser has an HSTS policy for a domain, it performs an internal 307 redirect from HTTP to HTTPS before the request even leaves the browser. This ensures that POST requests to an HTTP URL are correctly upgraded to HTTPS without losing their method or body, which is critical for form submissions and API integrations.
HTTP Strict Transport Security forces browsers to redirect HTTP requests to HTTPS using a 307 internal redirect. This preserves the original request method and body during the protocol upgrade.
An API endpoint is temporarily served from a different URL during a deployment or infrastructure change. Using 307 ensures POST, PUT, and DELETE requests maintain their method and body.
A load balancer temporarily routes traffic to a different backend server. 307 ensures the full request, including method and body, reaches the new backend without modification.
During a checkout flow, the server temporarily redirects the client to a payment processor while preserving the POST method and payment data in the request body.
When redirecting POST, PUT, or DELETE requests temporarily, always use 307 instead of 302. This prevents browsers from changing the method to GET, which would lose the request body and cause errors.
Ensure your server or proxy includes appropriate headers so the client retransmits the original request body when following the redirect. The body must be sent to the new URL unchanged.
Since 307 is temporary, set Cache-Control: no-cache or a very short max-age to ensure clients do not cache the redirect and miss when the resource returns to its original location.
Use 307 for temporary method-preserving redirects. Use 302 when method change is acceptable. Use 301 for permanent redirects where method change is okay. Use 308 for permanent method-preserving redirects.
// Express.js — 307 temporary redirect preserving method
const express = require('express');
const app = express();
// Temporary API migration — preserves POST method and body
app.post('/api/v1/orders', (req, res) => {
// Temporarily route to v2 while v1 is being updated
res.redirect(307, '/api/v2/orders');
});
// HTTPS enforcement preserving method
app.use((req, res, next) => {
if (req.headers['x-forwarded-proto'] !== 'https') {
// 307 preserves POST/PUT/DELETE during HTTPS upgrade
return res.redirect(307, `https://${req.hostname}${req.url}`);
}
next();
});
// Temporary maintenance redirect for specific endpoint
app.all('/api/payments', (req, res) => {
if (process.env.PAYMENTS_MAINTENANCE === 'true') {
return res.redirect(307, 'https://backup.example.com/api/payments');
}
// ... normal handler
});
# Flask — 307 temporary redirect preserving method
from flask import Flask, redirect, request
app = Flask(__name__)
# Temporary API migration — preserves POST method and body
@app.route('/api/v1/orders', methods=['POST'])
def orders_v1():
# Temporarily route to v2 while v1 is updated
return redirect('/api/v2/orders', code=307)
# HTTPS enforcement preserving method
@app.before_request
def force_https():
if request.headers.get('X-Forwarded-Proto') == 'http':
url = request.url.replace('http://', 'https://', 1)
return redirect(url, code=307)
# Temporary maintenance redirect
import os
@app.route('/api/payments', methods=['GET', 'POST', 'PUT', 'DELETE'])
def payments():
if os.environ.get('PAYMENTS_MAINTENANCE') == 'true':
return redirect(
'https://backup.example.com/api/payments',
code=307
)
# ... normal handler
The key difference is method preservation. HTTP 307 guarantees the browser will use the same HTTP method for the redirected request. HTTP 302 allows browsers to change POST to GET, which was a historical implementation quirk that became standard behavior.
Use 307 when redirecting POST, PUT, or DELETE requests and you need the method and request body to be preserved. Use 302 when the redirect is temporary and method changing is acceptable, such as redirecting a GET request.
Yes. When a browser has an HSTS policy for a domain, it performs an internal 307 redirect from HTTP to HTTPS. This happens before the request leaves the browser, ensuring POST bodies and methods are preserved during the upgrade.
Like 302, a 307 tells search engines the redirect is temporary and they should continue indexing the original URL. Search engines do not transfer ranking signals for temporary redirects. If the redirect is permanent, use 301 or 308 instead.
No. A 307 redirect requires the client to resend the exact same request, including the method, headers, and body, to the new URL. This is the defining characteristic that distinguishes it from 302.
Get instant alerts when your endpoints go down. 60-second checks, free forever.
Start Monitoring Free →