307 Temporary Redirect
What a 307 Temporary Redirect is, how it strictly preserves the HTTP method unlike a 302, where it shows up (HSTS, temporary moves), and how Google treats it for SEO.
1 evidence signal on this page
- Related live toolHTTP Status & Redirect Checker
A 307 Temporary Redirect means the same thing to Google as a 302 — a weak, temporary signal that doesn't hand the original URL's ranking over to the target — so there's no ranking reason to prefer one over the other. Its one real difference from a 302 is a spec guarantee: a 307 must not change the request method or body, so a POST stays a POST. That matters for forms, APIs, and modern frameworks (Next.js defaults to 307), and it's irrelevant for ordinary GET page redirects. The 307 that confuses most people isn't a redirect at all: it's the browser-only artifact HSTS produces when it upgrades http to https, with a 0-byte body the server never sent — a redirect checker or a plain curl request (not just a fresh incognito session, which can't override a preloaded HSTS domain) shows the real status code.
TL;DR — A 307 is a temporary redirect, just like a 302 — it sends people and search engines to a new URL for now, without telling Google to move the old URL’s ranking to the new one. The one thing that makes it different from a 302: a 307 promises not to change the type of request. If someone submitted a form (a POST), it stays a POST. For plain page-to-page links that’s invisible; it only matters for forms and apps. And the “307” you sometimes spot in your browser for an https upgrade isn’t a real redirect at all.
What a 307 redirect is
When a URL has moved somewhere else for now — not permanently — the server can answer with a 307 Temporary Redirect and point the browser to the new location. That’s the same basic idea as a 302: it’s temporary, so Google doesn’t treat it as a signal to hand the original URL’s ranking over to the new one, the way it does with a permanent redirect. That’s a weak, non-canonicalizing signal, not a guarantee that the original URL keeps its rankings or stays indexed forever. You’d use a temporary redirect for a page that’s down for maintenance, a seasonal campaign, or anything you plan to switch back later.
Evidence for this claim Google treats 307 as equivalent to 302 for Search while noting that the HTTP semantics differ. Scope: Google Search redirect handling; clients still need the semantically appropriate status code. Confidence: high · Verified: Google: HTTP status codes and SearchWhat makes a 307 different from a 302
There’s really only one difference, and most people never bump into it. A web request has a method — usually GET (just fetching a page) but sometimes POST (sending data, like submitting a form). A 307 guarantees the browser keeps the same method when it follows the redirect. Old browsers used to sometimes turn a POST into a GET on a 302, which could break a form submission. A 307 removes that risk by the rulebook. Evidence for this claim RFC 9110 defines 307 Temporary Redirect as a temporary move and requires clients not to change the request method when following it automatically. Scope: HTTP semantics for real server 307 responses, not browser-internal HSTS displays. Confidence: high · Verified: IETF: RFC 9110 §15.4.8 — 307 Temporary Redirect
For the vast majority of redirects — someone clicking a link to a page — this makes no difference at all, because those are GET requests either way.
Does a 307 hurt SEO?
No. Google’s own documentation says a 307 is “equivalent to” a 302. Both are temporary, so neither one hands the old page’s ranking over to the new page the way a permanent redirect (a 301) does. There’s no secret penalty and no secret boost — a 307 is treated exactly like a 302.
The “307” that isn’t a redirect
Here’s the part that trips people up. If your site forces https (a security feature called HSTS), your browser will sometimes show a “307” in its developer tools when you visit the http version of a page. Your server never sent that — the browser made it up to explain that it jumped straight to the secure version on its own. It even shows a 0-byte response, which is the giveaway.
So if an audit tool or your browser flags a surprise 307, don’t panic that your
server is misconfigured. A fresh incognito window usually clears the browser’s
learned HSTS memory and shows the real status code — but not always: some domains
ship on browsers’ built-in HSTS preload list, which incognito doesn’t clear.
A redirect checker or curl request is the more reliable way to see what your
server actually returns.
Want the spec language, what John Mueller has said, the HSTS mechanics in full, and how to actually return a 307? Switch to the Advanced tab.
TL;DR — A 307 is a temporary redirect that, per RFC 9110, “MUST NOT change the request method” — the one hard guarantee a 302 doesn’t make. For SEO it’s a non-event: Google’s docs list it as “Equivalent to
302” (a weak, temporary signal), and Mueller has said the 307-vs-302 choice “doesn’t really matter” for search — it’s about whether the redirect has to work for POST/API traffic. The 307 that actually confuses people is the HSTS artifact: a browser-only, 0-byte “redirect” the server never sent, produced when the browser upgrades http to https on its own. It has two functionally unrelated cases, and keeping them apart is the whole job.
A 307 has two completely different cases
This is the organizing idea for everything below, and it comes straight from my own status-codes guide, where 307 gets two separate entries: “307 Temporary Redirect – Has the same functionality as a 302 redirect, except you can’t switch between POST and GET” and “307 HSTS Policy – Forces the client to use HTTPS when making requests instead of HTTP.” They share a number and almost nothing else:
- 307 as a real, server-issued temporary redirect — deliberately chosen (or defaulted-to by a framework) to preserve the HTTP method and body on a non-GET request.
- 307 as an HSTS browser artifact — not a server response at all. The browser upgrades http to https internally and labels that upgrade a 307.
Conflating these two is the single most common source of 307 confusion. I’ll take them one at a time.
Case 1: the real 307 — what the spec actually requires
RFC 9110 (the current HTTP semantics spec) is unambiguous in §15.4.8:
Evidence for this claim RFC 9110 defines 307 Temporary Redirect as a temporary move and requires clients not to change the request method when following it automatically. Scope: HTTP semantics for real server 307 responses, not browser-internal HSTS displays. Confidence: high · Verified: IETF: RFC 9110 §15.4.8 — 307 Temporary Redirect“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.”
That “MUST NOT” is a hard requirement, not a suggestion. Compare it to the 302 section (§15.4.3), which openly documents the historical mess 307 was created to fix: “For historical reasons, a user agent MAY change the request method from POST to GET for the subsequent request. If this behavior is undesired, the 307 (Temporary Redirect) status code can be used instead.” In other words, 307 exists specifically to remove the POST→GET ambiguity that older clients had with 302s.
MDN states the practical version of the same distinction:
“The difference between
307and302is that307guarantees that the client will not change the request method and body when the redirected request is made. With302, older clients incorrectly changed the method toGET.307and302responses are identical when the request method isGET.”
That last sentence is the one that matters most for SEO. Almost every redirect an SEO cares about — an old page to a new page — is a GET request, and for GET requests a 307 and a 302 are literally identical. The method-preservation guarantee only bites when the method isn’t GET: form resubmissions, API endpoints, webhook targets, checkout or auth POST handoffs. What the spec guarantees is the method and body — it doesn’t by itself pin down every client’s exact handling of headers, credentials, or cross-origin requests on replay, so verify those against your actual client rather than assuming byte-for-byte behavior. If you’re comparing the two codes head to head for a normal page move, that comparison is covered in depth in the dedicated 302 vs. 307 piece — this article assumes you already know the base temporary-redirect concept from the 302 redirect deep-dive and leans into what’s unique about 307.
302 vs. 303 vs. 307, in one table
All three sit in the RFC’s “temporary” bucket, but they don’t behave the same on the two axes that actually matter — method preservation and caching:
| Code | Method on automatic redirect | Heuristically cacheable? |
|---|---|---|
| 302 Found | May change POST to GET (historical client behavior; not an RFC requirement) | No |
| 303 See Other | Deliberately retrieves the target with GET or HEAD | No |
| 307 Temporary Redirect | MUST NOT change the method | No |
None of the three is heuristically cacheable by default — a 307 (like 302 and
303) needs an explicit freshness signal (Cache-Control, Expires, etc.) before
a cache will store it without asking again.
Case 1, continued: how Google treats a real 307 for SEO
Short version: exactly like a 302. Google’s HTTP Status Codes documentation
lists the 307 row as “Equivalent to 302,” and the 302 row it inherits from
spells out what that means:
“By default, Google’s crawlers follow the redirect, and Google systems use the redirect as a weak signal that the redirect target should be processed.”
“Weak” is the operative word — a temporary redirect doesn’t consolidate canonicalization onto the target the way a permanent one does. Google’s Redirects and Google Search doc groups 302, 303, and 307 together under “temporary” and describes the behavior directly: “Googlebot follows the redirect, but the indexing pipeline doesn’t use the redirect as a signal that the redirect target should be canonical.” Same page, same intent framing: “If you just want to send users to a different page temporarily, use a temporary redirect.”
Evidence for this claim Google's indexing pipeline does not use a temporary 302, 303, or 307 redirect as a signal that the redirect target should be canonical. Scope: redirect crawling, indexing, and canonicalization Confidence: high · Verified: Redirects and Google SearchImmediately after both the 307 and 308 rows, Google adds the caveat worth tattooing on the wall:
“While Google treats these status codes the same way, keep in mind that they’re semantically different. Use the status code that’s appropriate for the redirect so other clients (for example, e-readers, other search engines) may benefit from it.”
So Google buckets 307 and 302 together for ranking, but still tells you to pick the semantically correct code. That’s the whole SEO answer. Evidence for this claim Google treats 307 as equivalent to 302 for Search while noting that the HTTP semantics differ. Scope: Google Search redirect handling; clients still need the semantically appropriate status code. Confidence: high · Verified: Google: HTTP status codes and Search John Mueller put it even more bluntly on Search Off the Record episode 51 (“Let’s talk redirects”), explaining that “with 307, 308, it also forwards POST requests” — unlike 301/302, which forward GET requests — and then landing the point:
“I think for SEO, it doesn’t really matter. It’s more like, I don’t know… Does it work for APIs or not? And usually, APIs are not something that you need to have indexed directly in Search.”
There’s no ranking upside to switching your temporary redirects to 307. The only valid reason to choose it is method/body preservation — or, as a general future-proofing preference, which I’ll get to at the end.
Case 1, continued: framework and CDN defaults
A growing share of “why is this a 307?” questions aren’t deliberate choices at
all — they’re framework defaults. Next.js’s redirect() function defaults to
a 307, and the docs are explicit about why, under a heading literally titled “Why
does redirect use 307 and 308?”: “The redirect() method uses a 307 by
default, instead of a 302 temporary redirect, meaning your requests will always
be preserved as POST requests.” (Next.js uses a 303 specifically inside Server
Actions, and ships a separate permanentRedirect() for the 308 case.) If you’re
seeing 307s you didn’t hand-write, check whether your framework or edge platform
is defaulting to them for non-GET redirects — that’s usually the answer, and
usually correct.
Case 2: the HSTS “phantom 307” your server never sent
This is the genuinely under-covered territory, and where a dedicated 307 article
earns its keep. When a site sends a Strict-Transport-Security (HSTS) header, it
tells the browser: from now on, only ever load me over https. On the next
request to the http version, the browser upgrades to https itself, without
talking to the server — and displays that internal upgrade as a “307” in dev
tools and crawlers.
John Mueller explained the mechanic on his personal site:
“After seeing the HTTPS URL with the HSTS header (for example, with any redirect from the HTTP version), Chrome will act like it’s seeing a 307 redirect the next time you try to access the HTTP page. Your server’s not returning a 307, Chrome is just showing it to you as such to explain that it’s doing the redirect for you.”
The 0-byte body is the tell — as Mueller adds, “the 307 isn’t actually a redirect at all, it’s just a placeholder.” My own redirects guide frames the practical consequence for auditing: “When web servers require clients to only use HTTPS connections (HSTS policy), Google won’t see the 307 because it’s cached in the browser. The initial hit (without cache) will have a server response code that’s likely a 301 or a 302. But your browser will show you a 307 for subsequent requests which makes it more difficult to troubleshoot. You will need to use a fresh Incognito session to see the returned status code.”
What Googlebot actually sees for HSTS (and how the story evolved)
Two Google statements, five years apart, worth reading together. Back in December 2015, Zineb Ait Bahajji (then at Google) said, per Search Engine Roundtable, “With HSTS implemented, Googlebot sees a 301 redirect (try it with Fetch as Google). The 307 is just an ‘internal redirect’.” By October 2020, Mueller’s framing in an Ask Google Webmasters video (via Search Engine Journal) was slightly different: “In short, [Googlebot] doesn’t interact with them. 307 redirects are generally not real redirects.” Either way, the crawler is not seeing the same “307” a human sees in dev tools — the tooling and crawl infrastructure changed (Fetch as Google was retired for URL Inspection), but the underlying point held for at least a decade: there’s no real server-issued 307 in the HSTS case. Treat the 2020 statement as current guidance; the 2015 one is useful history.
The important operational takeaway: HSTS is a browser convenience, not a crawl-discovery mechanism. Site owners still need a real server-side redirect (a genuine 301) for http→https if they want that path to work for crawlers.
How Bing treats a 307
Honestly? There’s a documentation gap. I found no public Bing statement that addresses 307 by name, or the HSTS-driven 307 specifically. Bing’s redirect guidance (the 2011 Managing redirects – 301s, 302s and canonicals post and the 2020 Website Migration with Bing post) only covers the 301/302 permanent-vs- temporary split — no mention of 307, 308, or HSTS. So rather than assume parity with Google, treat it plainly: Bing hasn’t said anything 307-specific publicly. The phenomenon is still real and crawler-relevant regardless of engine — Screaming Frog’s SEO Spider ships a “Respect HSTS Policy” toggle precisely because HSTS affects crawling — but that’s tooling documentation, not a Bing statement.
When to deliberately choose a 307
Pick a 307 (over a 302) whenever losing the original method or body would break something:
- API endpoints and webhook targets that receive POST/PUT/PATCH.
- Form-submission (POST) flows that redirect after processing.
- Checkout / login POST handoffs between hosts.
- Anything where the request carries a body you can’t afford to drop.
For a plain page-to-page move, a 302 and a 307 are indistinguishable to Google, so either is fine on the SEO axis. If you’re dealing with a permanent version of this same method-preservation logic, that’s the 301-vs-308 relationship — 308 is to 301 what 307 is to 302.
My own stated preference, from the redirects guide, is more opinionated than the usual “it doesn’t matter”: “my preferred order would be: 307 / 302 / 303 > Meta refresh 0 / HTTP refresh 0.” I put 307 first among the temporary options — using it consistently means you’re always safe on the method-preservation front, which is roughly the “completeness” argument Mueller made too. And whichever you choose, watch that a real 307 (or the HSTS artifact) doesn’t become one hop in a longer redirect chain — every extra hop is latency and lost efficiency.
AI summary
A condensed take on the Advanced version:
- A 307 has two unrelated cases. (1) A real, server-issued temporary redirect that preserves the HTTP method/body; (2) an HSTS browser artifact — a 0-byte “307” the server never sent, produced when the browser upgrades http→https on its own. Keeping them apart is the whole job.
- Case 1 — the spec guarantee: RFC 9110 says a 307 “MUST NOT change the request method.” MDN adds that “307 and 302 responses are identical when the request method is GET” — so it only matters for POST/PUT/PATCH (forms, APIs). The guarantee covers method and body; header/credential/cross-origin handling on replay still depends on the client.
- 302 vs. 303 vs. 307: 302 may (historically) change POST to GET, 303 deliberately retrieves the target with GET/HEAD, 307 must not change the method — and none of the three is heuristically cacheable by default.
- SEO answer: Google’s docs list 307 as “Equivalent to
302” — a weak, temporary signal that doesn’t consolidate onto the target. Mueller: for SEO “it doesn’t really matter”; the real question is “does it work for APIs.” - Framework defaults: Next.js
redirect()defaults to 307 (303 in Server Actions,permanentRedirect()for 308) to preserve POST — a common source of “accidental” 307s that’s usually correct. - Case 2 — HSTS: the browser shows a 307 with a 0-byte body; the real server
code is usually a 301/302. Googlebot doesn’t see that 307 (Mueller 2020: “doesn’t
interact with them”; Zineb 2015: “sees a 301”). You still need a real server-side
301 for http→https. Audit with a redirect checker or plain
curl— a fresh incognito session usually works too, but not for domains on the browser’s built-in HSTS preload list. - Bing: no public 307-specific statement — a documentation gap, not parity.
- Preference: no ranking reason to switch to 307; Patrick’s own order puts 307 first among temporary options for future-proofing.
Official documentation
Primary-source documentation and specs.
- HTTP Status Codes, Network and DNS Errors, and Google Search — the “307 (temporary redirect) — Equivalent to
302” row, the 302 “weak signal” language, and the “semantically different” caveat. - Redirects and Google Search — groups 302/303/307 under “temporary”; “the indexing pipeline doesn’t use the redirect as a signal that the redirect target should be canonical.”
Bing / Microsoft
- Managing redirects – 301s, 302s and canonicals — Bing’s redirect guidance (301/302 only; no 307/HSTS mention).
- Website Migration with Bing — migration guidance, again 301/302-only.
HTTP spec
- RFC 9110 §15.4.8 — 307 Temporary Redirect — “MUST NOT change the request method.”
- RFC 9110 §15.4.3 — 302 Found — the historical POST→GET note that cross-references 307.
Technical reference
- MDN — 307 Temporary Redirect — method/body preservation; “identical when the request method is GET.”
Framework
- Next.js —
redirect()function reference — the “Why doesredirectuse 307 and 308?” FAQ; defaults to 307 (303 in Server Actions).
Crawler tooling
- Screaming Frog — An SEO’s Guide To Crawling HSTS & 307 Redirects — the “Respect HSTS Policy” config and HSTS mechanics.
Quotes from the source
On-the-record statements. Each link jumps to (or documents) the quoted passage.
Google docs — the SEO treatment
- “307 (temporary redirect) — Equivalent to
302.” — Google Search Central, HTTP Status Codes, Network and DNS Errors, and Google Search. Jump to quote - “By default, Google’s crawlers follow the redirect, and Google systems use the redirect as a weak signal that the redirect target should be processed.” (the 302 row 307 inherits from) Jump to quote
- “While Google treats these status codes the same way, keep in mind that they’re semantically different. Use the status code that’s appropriate for the redirect so other clients (for example, e-readers, other search engines) may benefit from it.” Jump to quote
- “Googlebot follows the redirect, but the indexing pipeline doesn’t use the redirect as a signal that the redirect target should be canonical.” — Google Search Central, Redirects and Google Search. Jump to quote
HTTP spec / MDN — the technical guarantee
- “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.” — RFC 9110, §15.4.8. Read the section
- “For historical reasons, a user agent MAY change the request method from POST to GET for the subsequent request. If this behavior is undesired, the 307 (Temporary Redirect) status code can be used instead.” — RFC 9110, §15.4.3 (the 302 section). Read the section
- “The difference between
307and302is that307guarantees that the client will not change the request method and body when the redirected request is made…307and302responses are identical when the request method isGET.” — MDN, 307 Temporary Redirect. Jump to quote
John Mueller, Google — SEO and method preservation
- “I think for SEO, it doesn’t really matter. It’s more like, I don’t know… Does it work for APIs or not? And usually, APIs are not something that you need to have indexed directly in Search.” — Search Off the Record, ep. 51, “Let’s talk redirects” (Nov 17, 2022). Transcript PDF
- “And with 307, 308, it also forwards POST requests” (vs. 301/302, which forward GET requests). — Same episode.
John Mueller, Google — the HSTS “phantom 307”
- “Your server’s not returning a 307, Chrome is just showing it to you as such to explain that it’s doing the redirect for you… the 307 isn’t actually a redirect at all, it’s just a placeholder.” — John Mueller, HTTPS & HSTS: 301, 302, or 307? (johnmu.com, originally Google+, June 2016). Jump to quote
- “In short, [Googlebot] doesn’t interact with them. 307 redirects are generally not real redirects.” — John Mueller, Ask Google Webmasters (Oct 2020), via Search Engine Journal. Jump to quote
Zineb Ait Bahajji, Google — HSTS, 2015 (relayed)
- “With HSTS implemented, Googlebot sees a 301 redirect (try it with Fetch as Google). The 307 is just an ‘internal redirect’.” — Zineb Ait Bahajji (Google), via Twitter, reported by Search Engine Roundtable (Dec 2015). Jump to quote
Which 307 am I actually looking at?
Nearly every 307 question resolves to one of two totally different things. Walk it through.
Diagnosing a 307 you didn't expect
Myths and mistakes to avoid
“A 307 doesn’t pass link equity the way a 302 does.”
False on the “307 is worse than 302” framing — and it’s actively circulating on
major SEO blogs. Google’s own docs process 307 and 302 the same way: both are
non-canonicalizing “weak signal” temporary redirects, and Google’s HTTP Status
Codes doc calls 307 “Equivalent to 302” outright. There’s no documented basis
for singling out 307 as passing less than 302. Google’s own framing is really that
temporary redirects in general aren’t meant to consolidate ranking signals onto
the target the way a permanent redirect is — so don’t let a “307 specifically
withholds equity” claim push you into needless changes.
“A 307 in my Network tab means my server misconfigured a redirect.”
Often false. If HSTS is enabled and the browser previously saw the
Strict-Transport-Security header, it displays an http→https upgrade as a 307
purely as its own explanation — the server never returned it (0-byte body is the
tell). A fresh incognito session usually shows the real code, but not for domains
on a browser’s built-in HSTS preload list — for those, test with a redirect
checker or curl (unconfigured for HSTS) before you go hunting for a
misconfiguration that isn’t there.
“Googlebot sees the same 307 my browser shows me for an HSTS site.” Not quite. Google’s reps have said Googlebot either sees a 301 (Zineb, 2015) or doesn’t interact with the 307/HSTS mechanism at all (Mueller, 2020). Either way it’s not the human-visible “307.” You still need a real server-side 301 for http→https if crawl discovery of that path matters.
“303 and 307 are basically interchangeable.” They’re opposites on the one axis that matters. A 303 always switches the method to GET (the Post/Redirect/Get pattern); a 307 guarantees the method is not changed. They’re easy to conflate only because both sit in the “temporary” bucket next to 302.
“Switch all your temporary redirects to 307 for a rankings boost.” There’s no boost. The only valid reason to prefer 307 over 302 is genuine method/body preservation (or general future-proofing). Churning every 302 into a 307 buys you nothing and risks introducing errors.
“302s always convert POST to GET, so 302 is fundamentally broken for forms.” Overstated. The POST→GET conversion was a real problem for older, inconsistent clients — which is exactly why 307 exists as the guaranteed option — but modern browsers are far more consistent. A 307 removes the ambiguity by spec rather than relying on current client behavior; it doesn’t mean 302 is “broken.”
See the real status code (not the HSTS artifact)
The browser hides a real 301/302 behind a phantom 307 once HSTS is cached. curl
doesn’t apply HSTS by default, so a plain invocation talks straight to the server
and shows the truth — just don’t run it with an --hsts cache file configured, or
you’ve reintroduced the same client-side rewrite you’re trying to rule out.
Trace the full redirect chain, headers only
# -s silent, -I headers-only, -L follow redirects, cap the hops
curl -sIL --max-redirs 10 http://example.com/old-page 2>&1 \
| grep -Ei '^(HTTP/|location:)'
# Each "HTTP/…" line is one hop's real status code; each "location:" is where it points.
# An HSTS "307" never appears here — it's browser-only.Check one URL’s status code without following
curl -s -o /dev/null -w "%{http_code}\n" http://example.com/old-pageChrome DevTools Console — spot a phantom 307
Paste into the Console tab. A real server redirect exposes a redirected flag and
a resolved URL; the HSTS upgrade happens before the request even leaves the browser.
// Fetch and report what the network actually did.
fetch("http://example.com/old-page", { redirect: "manual" })
.then(r => console.log("type:", r.type, "status:", r.status, "url:", r.url))
.catch(e => console.log("blocked before request (often HSTS upgrade):", e.message));You can also read Chrome’s own HSTS record directly at
chrome://net-internals/#hsts — query a domain to see whether
static_upgrade_mode/dynamic_upgrade_mode is forcing https (that’s what produces
the 307 you see in the Network tab).
Bookmarklet — quick header peek for the current tab
Drag a bookmark with this as the URL, then click it on any page to log the current URL’s status and redirect state to the Console:
javascript:(function(){fetch(location.href,{redirect:"manual"}).then(function(r){console.log("[status]",r.status,"[type]",r.type,"[redirected]",r.redirected,"[url]",r.url);}).catch(function(e){console.log("[error]",e.message);});})();Note: browser fetch() can’t read cross-origin opaque redirect bodies, so for
authoritative multi-hop tracing, curl -sIL above is the ground truth.
Returning a real 307
The point of returning a 307 (rather than letting a framework default to it) is to guarantee the method and body survive. A few common ways to do it explicitly.
Apache (.htaccess)
# mod_rewrite with an explicit 307 (R=307). Preserves POST body.
RewriteEngine On
RewriteRule ^old-endpoint$ https://example.com/new-endpoint [R=307,L]nginx
# 307 keeps the method; 302 would risk POST→GET on older clients.
location = /old-endpoint {
return 307 https://example.com/new-endpoint;
}Node / Express
app.post("/old-endpoint", (req, res) => {
// res.redirect defaults to 302; pass 307 to preserve the POST + body.
res.redirect(307, "https://example.com/new-endpoint");
});Next.js (App Router) — 307 is the default, so you often don’t write the code at all:
import { redirect } from "next/navigation";
// redirect() returns a 307 by default (303 inside a Server Action),
// preserving the request as a POST. Use permanentRedirect() for a 308.
export default function Page() {
redirect("/new-endpoint");
}What a raw 307 response looks like
HTTP/1.1 307 Temporary Redirect
Location: https://example.com/new-endpoint
Content-Length: 0What the HSTS “phantom 307” looks like (browser-only)
Same status line in dev tools, but note the giveaways — it originates from the browser, not the server, and carries a 0-byte body:
HTTP/1.1 307 Internal Redirect
Location: https://example.com/old-page
Non-Authoritative-Reason: HSTSIf you see Non-Authoritative-Reason: HSTS (Chrome) or a 0-byte “307” that
vanishes when tested with a client that doesn’t apply HSTS, that’s the artifact —
not a redirect your server sent. The exact header name and DevTools label are
Chrome-specific implementation details, not an HTTP or HSTS spec guarantee, so
treat them as illustrative rather than something to build automation against
across browsers or versions.
The method, duration, and source framework
I evaluate a 307 on three axes before changing it:
- Method: must the destination receive the original method and request body?
If yes, 307 is the temporary redirect that preserves both. A plain page-to-page
GETusually does not need that property. - Duration: is the move genuinely temporary? Keep 307 only while the original URL is expected to return. A permanent move needs a permanent redirect decision, not an indefinitely temporary status.
- Source: did the server send the 307, did a framework choose it, or did the browser synthesize an internal HSTS upgrade? A DevTools “Internal Redirect” is not an origin rule to rewrite.
Patrick's relevant free tools
- Website Down Checker — Check whether one URL or a small sample is reachable right now from one Cloudflare location, with response timing, redirects, DNS fallback evidence, and connection-status details.
- Redirect Map Builder — Plan a site migration: paste old and new URLs and get a suggested 301 map — each row scored into a confidence tier with a plain reason, an override dropdown, a first-class unmatched bucket, a 410 kill-list, chain-flattening so the map never creates the chains it prevents, and platform-accurate exports for Apache, nginx, and Cloudflare. Optional metadata-only content matching closes the last-mile gaps. Structural matching runs entirely in your browser.
Tools for separating real and phantom 307s
- Redirect Checker: see the server-observable status, destination, and every hop without relying on one browser’s HSTS state.
- Redirect Chain Mapper: use the per-hop view when a 307 is part of a longer redirect path.
- HTTP Header Checker: inspect
LocationandStrict-Transport-Securityand compare edge versus origin clues. - curl: run
curl -I http://example.com/pathoutside the browser’s internal HSTS display. Test POST preservation only against a safe endpoint you control. - Browser DevTools: check whether the entry says “Internal Redirect” and has a zero-byte transfer, which points to a browser-generated HSTS upgrade.
Validate a 307 after deployment
Status and destination test
Test to run: check the source with the Redirect Checker
or curl -I. Expected result: one 307 with the intended Location.
Failure interpretation: another layer changed the rule or target. Monitoring
window: immediate. Rollback trigger: a loop, broken destination, or unintended
hostname appears.
Method-preservation test
Test to run: send a harmless POST to a controlled test route and inspect what the destination receives. Expected result: the destination receives POST with the original body. Failure interpretation: an intermediary converted the method or served another code. Monitoring window: immediate. Rollback trigger: a form, webhook, or checkout request loses its method or body.
HSTS separation test
Test to run: compare DevTools (or a fresh incognito session) with a curl -I
request that has no HSTS cache configured. Expected result: a browser
“Internal Redirect” is distinguishable from the real server response, and HTTP
still has a server-side redirect. Failure interpretation: HSTS is masking a
missing origin rule — note that incognito alone isn’t sufficient for domains on a
browser’s built-in HSTS preload list, since that state persists independent of
browsing history. Monitoring window: immediate. Rollback trigger: the
origin change removes the working HTTP-to-HTTPS redirect.
Test yourself: 307 Temporary Redirect
Five quick questions on what a 307 is, how Google treats it, and the HSTS artifact. Pick an answer for each, then check.
Resources worth your time
My related writing
- 11 Types Of Redirects & Their SEO Impact — where the 307 definition, the HSTS caveat, and my preferred-order ranking (307 / 302 / 303 first) come from.
- HTTP Status Codes & Their SEO Impact — my piece with 307’s two distinct entries: the temporary-redirect case and the HSTS-policy case.
- The Beginner’s Guide to Technical SEO — where redirects fit in the bigger picture.
My speaking
- How Search Works (SlideShare) — my walkthrough of crawling, rendering, indexing, and ranking, including how redirects are handled. (My standing disclaimer applies: “This is my understanding of systems… not going to be 100% complete or accurate.”)
From around the industry
- John Mueller — HTTPS & HSTS: 301, 302, or 307? — the clearest first-party explanation of the HSTS “phantom 307” (“your server’s not returning a 307”).
- Search Off the Record, ep. 51 — “Let’s talk redirects” (transcript PDF) — Mueller and Splitt on why 307/308 exist and why “for SEO, it doesn’t really matter.”
- Google on 307/HSTS Redirects (Search Engine Journal) — recap of Mueller’s “307 redirects are generally not real redirects” video.
- GoogleBot Treats 307 Redirects As 301s? (Search Engine Roundtable) — Zineb Ait Bahajji’s 2015 statement on what Googlebot sees for HSTS.
- MDN — 307 Temporary Redirect — the gold-standard technical reference for the method/body guarantee.
- An SEO’s Guide To Crawling HSTS & 307 Redirects (Screaming Frog) — the best crawler-configuration treatment of HSTS-driven 307s.
- Next.js —
redirect()reference — why a major framework defaults non-GET redirects to 307.
307 redirect
A 307 ("Temporary Redirect") is a temporary redirect that, unlike a 302, is guaranteed by the HTTP spec to preserve the original request method and body — so a POST stays a POST. For SEO, Google treats it as equivalent to a 302. Browsers/tools also sometimes represent an HSTS-driven internal scheme upgrade as a 307, though the server never actually sent it and RFC 6797 doesn't require that specific code.
Related: 302 redirect, 303 See Other
307 redirect
A 307 redirect (HTTP status code “307 Temporary Redirect”) tells the client that a resource has moved to a different URL for now — the same meaning as a 302 — with one strict guarantee a 302 doesn’t make: the client must not change the request method or body when it follows the redirect. RFC 9110 requires method preservation, and MDN explains that the practical behavior of 307 and 302 is identical for GET requests. So the distinction bites for forms, APIs, and other POST/PUT/PATCH flows, not for everyday page-to-page redirects.
For SEO, there’s nothing special to it: Google’s redirect documentation classifies both 302 and 307 as temporary server-side redirects. The meaningful difference is whether your redirected request must preserve its method and body, which matters most for APIs and forms.
Confusingly, a 307 also appears in a second, unrelated context. When a site has sent a Strict-Transport-Security (HSTS) header, the browser internally rewrites a later HTTP request to HTTPS before any request goes out — RFC 6797 §8.3 requires the scheme substitution but doesn’t mandate a specific status code for it, and in practice many dev tools and crawlers display that internal step as a “307” with a 0-byte body. The server never issued it; it’s a client/tool-specific placeholder, not a guaranteed spec behavior. To see the real underlying status code, use a redirect checker or a plain curl request with no HSTS state configured — a fresh incognito session usually works too, but not for domains on a browser’s built-in HSTS preload list, since that state isn’t tied to browsing history.
Related: 302 redirect, 303 See Other
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Revision history
Compare the published article with an archived editorial snapshot. Added and removed words are shown only after you open a comparison.
Updated Jul 17, 2026.
Editorial summary and recorded change details.Summary
Qualified replay, HSTS display, and link-signal claims with client and platform boundaries.
Change details
-
Added that a 307’s method/body guarantee does not independently guarantee credential, header, or cross-origin replay behavior.
Try it live
This is a real endpoint on this site — not a simulation. Hit it from the button, open it in a new tab, or curl -i from your terminal, and the server answers with the actual status code this article is about.