HTTP 302 Status Code: What It Means & 302 vs 301
Key takeaway
HTTP 302 Found is a temporary redirect: the server says the page is at another URL for now, given in the Location header. The browser loads that URL at once, while links and search engines keep the original. Use 301 or 308 when a move is permanent; of 20 big sites we checked, none used a 302 for that. You usually meet a 302 when a page needs a login. Browsers turn a POST into a GET when following a 302, so use 307 to keep the method, or 303 after a form.
Check it now

Start reading
- What Is the 302 Status Code?
- Anatomy of a 302 Response
- Why Am I Getting a 302 Instead of a 200?
- 302 vs 301 vs 307 vs 308: Which Redirect Should You Use?
- When Should You Use a 302 Redirect?
- How to Send a 302 Status Code
- How to Test a 302 Status Code
- 302 Redirects and SEO
- Why a 302 Changes POST Requests to GET
- Common 302 Errors and How to Fix Them
- 302 Redirect Loops: How to Diagnose
- 302 Status Code Best Practices
- How Browsers and Tools Handle a 302
- Frequently Asked Questions
What Is the 302 Status Code?
HTTP 302 Found is a temporary redirect. The server answers "what you asked for is somewhere else for now" and names the other URL in the Location header. The browser loads that URL straight away, but bookmarks, links and search engines should keep using the original one (RFC 9110 §15.4.3).
That "for now" is the whole difference from 301 Moved Permanently, which says the old URL is gone for good. HTTP/1.0 called 302 "Moved Temporarily" (RFC 1945); RFC 2616 renamed it "Found" in 1999, but the meaning didn't change.
As a visitor you rarely see one, because the browser follows it before anything appears. You meet it in DevTools, in curl, in API clients and in SEO audits.
See every redirect and its status code
Anatomy of a 302 Response
A 302 response is small. Its parts:
- Status line —
HTTP/1.1 302 Found, or justHTTP/2 302(HTTP/2 has no reason phrase) - Location — the URL to go to. RFC 9110 says the server SHOULD send it; without one, the browser has nowhere to go and shows the 302's own body, usually blank
- Body — RFC 9110 says it "usually contains a short hypertext note" with a link. Browsers ignore it; nginx, Apache and Express send a one-line note by default, while many large sites send an empty body
- Caching headers — none needed. Browsers don't cache a 302 unless you add
Cache-Control: max-ageorExpires; 301 and 308, by contrast, are cached by default. A CDN may still cache it (see "A 302 that sticks" below)
HTTP/1.1 302 Found
Location: https://www.example.com/login?next=%2Fdashboard
Content-Length: 0
Date: Mon, 26 Oct 2026 14:00:00 GMTLocation can be a full URL or a relative path such as /login: RFC 9110 allows any URI reference, and browsers resolve it against the URL they asked for. In app code (Express, say) a relative path avoids leaking an internal host name or http:// from behind a proxy; nginx and Apache turn it into an absolute URL anyway unless you set absolute_redirect off or RedirectRelative On.
Why Am I Getting a 302 Instead of a 200?
Because the page wants something your request didn't bring, or the URL you used isn't the one the site serves. The usual reasons:
- You're not signed in — pages behind a login answer 302 to the sign-in page, with the page you wanted in a return parameter. Signed out,
github.com/settingssends you to/login?return_to=…. In curl or an API client, send the session cookie or token. - Your client doesn't follow redirects — browsers,
fetch()and Python's requests follow them automatically. curl doesn't unless you add-L; it stops at the 302 and prints only its body, often nothing (add-ito see the status and Location). - The URL isn't the one the site serves — a missing or extra trailing slash, a language path, or a tracking link that bounces you on. Express's
res.redirect(), nginx'sreturnwith only a URL and Apache'sRedirectall send 302 unless told otherwise. - Something in front of the server adds it — if the origin answers 200 when you test it directly but the public URL gives 302, a CDN, load balancer or proxy rule is redirecting.
APIs usually answer a missing login with 401 Unauthorized instead of a redirect. To see every hop and its status code, run the URL through the Redirect Checker.
302 vs 301 vs 307 vs 308: Which Redirect Should You Use?
Five redirect codes cover nearly every case. They differ in two ways: whether the move is permanent, and whether a POST stays a POST:
| Code | Permanent? | A POST in browsers | Cached by default? | Best for |
|---|---|---|---|---|
| 301 Moved Permanently | Yes | Becomes GET | Yes | Permanent URL changes, domain moves |
| 302 Found | No | Becomes GET | No | Logins, short-term moves, A/B tests |
| 303 See Other | No | Becomes GET | No | The page after a form is submitted |
| 307 Temporary Redirect | No | Stays POST | No | Temporary moves that must keep the method |
| 308 Permanent Redirect | Yes | Stays POST | Yes | Permanent moves that must keep the method |
303 and 307 exist because of 302. HTTP/1.1 added 303 in 1997, and in 1999 RFC 2616 admitted that "most existing user agent implementations treat 302 as if it were a 303 response", added 307 and renamed 302 "Found" (RFC 2616 §10.3.3). If a temporary redirect might receive a POST, use 307 to keep it, or 303 to load the next page with a GET.
When Should You Use a 302 Redirect?
Use a 302 when you expect the redirect to go away. Typical cases:
- Login redirects — sending a signed-out user from
/dashboardto/login, then back after sign-in - A/B tests — sending some visitors to a variant page; Google's own testing advice says to use 302, not 301, here (Google Search Central)
- Pages under repair — sending visitors to a notice page for a few days while a page is rebuilt
- Short-lived campaign URLs —
/black-fridaypointing at this year's sale page only during the sale - Maintenance — for visitors only; for search engines, a 503 with Retry-After is the better answer during planned downtime
If any of these becomes permanent, switch it to a 301.
How to Send a 302 Status Code
Most servers and frameworks have a one-line way to send a 302. Each of these sends 302 Found with a Location header, all a 302 needs.
Nginx
In nginx, use return with the code. return with only a URL also sends a 302 (nginx docs):
server {
listen 80;
server_name example.com;
# Temporary redirect (302 Found)
location /old-page {
return 302 https://example.com/new-page;
}
}Apache (.htaccess)
On Apache, use Redirect (302 is its default when you give no status) or a RewriteRule with [R=302,L]:
# Simple temporary redirect
Redirect 302 /old-page https://example.com/new-page
# Or with mod_rewrite for pattern matching
RewriteEngine On
RewriteRule ^maintenance$ /maintenance.html [R=302,L]Node.js (Express)
Express's res.redirect() defaults to 302 when no status code is provided:
// Temporary redirect (302 Found by default)
app.get('/dashboard', (req, res) => {
if (!req.user) {
return res.redirect('/login') // sends 302
}
// ...render dashboard
})
// Or be explicit:
res.redirect(302, '/login')How to Test a 302 Status Code
The fastest check is curl from a terminal: it shows the status code and Location header with no browser cache in the way.
# Status and headers, without following the redirect
curl -sI https://example.com/old-page
# -I sends HEAD, which some servers answer differently; this sends a real GET
curl -s -o /dev/null -D - https://example.com/old-page
# Expected:
# HTTP/2 302
# location: https://example.com/new-page
# Follow the whole chain and print each hop's status and Location
curl -sL -o /dev/null -D - https://example.com/old-page | grep -iE '^(HTTP/|location:)'No terminal? DNS Robot's Redirect Checker follows every hop (301, 302, 303, 307, 308 and meta refresh) from our server and shows each status code and the final URL, and the HTTP Header Checker shows each hop's raw headers under Redirects.
302 Redirects and SEO
Google treats the two kinds of redirect as different instructions. For a temporary redirect (302, 303, 307), Googlebot follows it, but Google doesn't take it as a sign that the target should be the canonical URL, so the source page normally stays in search results. The target can still be indexed if other signals point to it (Google Search Central).
A permanent redirect (301, 308) says the opposite: show the new URL. So the real question isn't "does a 302 pass PageRank?" but "which URL do I want in search results?" Your rel=canonical tag is one of the other signals; the Meta Tag Checker shows which URL a page declares.
- Use 301 or 308 for permanent moves — new domain, new URL structure, merged pages
- Use 302 for temporary ones — logins, A/B tests, campaigns
- Don't leave a permanent move on 302 — Google may keep showing the old URL
- Keep chains short — every hop costs a round trip, and Googlebot follows up to 10 hops by default (Google)
Why a 302 Changes POST Requests to GET
This is the most surprising part of 302. The early specs never let clients change the method, but browsers turned POST into GET on a 302 anyway. Today the Fetch Standard that browsers implement writes the habit down: on a 301 or 302, a POST becomes a GET and its body is dropped (Fetch Standard).
So when a browser sends POST /submit-form and the server answers 302 Found, the browser follows with GET /thank-you, and the form data is gone. Browsers keep PUT and DELETE as they are; other clients differ: Python's requests turns every method except HEAD into a GET on a 302, and curl -L turns a POST into a GET on 301, 302 and 303 (--post302 keeps the POST on a 302).
# What you send:
POST /submit-form HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
name=Alice&email=alice@example.com
# Server responds with 302:
HTTP/1.1 302 Found
Location: /thank-you
# Browser follows with GET (form data dropped!):
GET /thank-you HTTP/1.1
Host: example.comIf you need the redirect to preserve the original method (POST stays POST, PUT stays PUT), use 307 Temporary Redirect instead. If you intentionally want to drop the body and switch to GET — the classic POST/Redirect/GET pattern — use 303 See Other. Both are unambiguous; 302 is not.
Common 302 Errors and How to Fix Them
When a 302 goes wrong, it's usually one of these:
- A 302 instead of a 200 — a login wall, a client that doesn't follow redirects, or a URL variant (see "Why am I getting a 302" above)
- A 302 with no Location header — nothing can follow it, and the browser shows the 302's own body, usually blank. Set
Locationbefore sending the status - A 302 that points at itself — a redirect loop: the rule fires on its own target. Add the missing condition
- A form that loses its data — POST → 302 → GET drops the body. Use 303 to show a result page on purpose, or 307 to keep the POST
- A 302 that sticks — the server sent
Cache-Control: max-ageorExpireswith it, so browsers cached it, or your CDN cached it (on content Cloudflare caches, it keeps a 302 for 20 minutes unless the headers say otherwise, Cloudflare docs). Remove those headers, purge the CDN and clear the browser cache - A 302 in production but not locally — often a CDN, load balancer or proxy rule adding redirects. Test the origin directly to find out
302 Redirect Loops: How to Diagnose
A redirect loop is URL A sending you to B and B sending you back to A. After 20 redirects, the limit in the Fetch Standard, Chrome gives up with ERR_TOO_MANY_REDIRECTS and Firefox with "The page isn't redirecting properly".
A classic cause is Cloudflare's Flexible encryption mode: Cloudflare reaches your server over plain HTTP, your server redirects HTTP to HTTPS, and Cloudflare asks over HTTP again (Cloudflare docs).
# Trace the full redirect chain (limit to 10 hops to avoid infinite loops)
curl -ILs --max-redirs 10 https://example.com 2>&1 | grep -i 'HTTP/\|location:'
# Example of a loop:
# HTTP/2 302
# location: http://example.com/
# HTTP/1.1 302 Found
# Location: https://example.com/
# HTTP/2 302
# location: http://example.com/ <-- loop confirmedIf the same URL keeps coming back in Location, either pointing at itself or two URLs taking turns, you have a loop (with Cloudflare Flexible mode, https://example.com/ redirects to itself). For the full fix, see our ERR_TOO_MANY_REDIRECTS guide. DNS Robot's Redirect Checker traces the chain from our server and stops where it loops.
302 Status Code Best Practices
A few habits avoid most 302 problems:
- Always send a Location header — without it, nothing follows the redirect
- Don't add caching headers — a 302 without
max-ageorExpiresisn't cached, which is what you want - Mind absolute URLs behind a proxy — in app code a relative
/loginavoids leaking an internal host name orhttp://into Location; nginx and Apache build absolute URLs from their own settings - Keep it to one hop —
A → Bis fine;A → B → Cadds a round trip for every visitor - Never 302 a POST to a different page — use 303 to show a result page, or 307 to keep the POST
- Review old temporary redirects — they often outlive their reason. Check them with the Redirect Checker
- Switch to 301 as soon as a move is permanent
How Browsers and Tools Handle a 302
Clients agree on following a 302 but differ on limits and on what happens to the method:
| Client | What it does with a 302 | Redirect limit |
|---|---|---|
| Chrome, Edge, Firefox, Safari | Follows it at once; a POST becomes a GET | 20 (Fetch Standard) |
| fetch() in JavaScript | Follows by default (redirect: "follow"); same POST rule | 20 |
| curl | Doesn't follow; prints only the 302's body, often empty (add -i or -I to see the status and Location) | None (no following) |
| curl -L | Follows; a POST becomes a GET on 301, 302 and 303 (--post301, --post302, --post303 keep it) | 50 (--max-redirs) |
| wget | Follows | 20 (--max-redirect) |
| Python requests | Follows; every method except HEAD becomes a GET | 30 |
| Googlebot | Follows; keeps the source URL as the search result | 10 hops by default |
For the exact wording, see the RFC 9110 definition of 302 and MDN's 302 page.
Trace any redirect chain in seconds
Use DNS Robot's free Redirect Checker to inspect every hop in a redirect chain — see status codes, Location headers, and the final destination from a neutral server (no browser cache).
Sources
- RFC 9110: HTTP Semantics, 302 Found, IETF
- Fetch Standard: HTTP-redirect fetch, WHATWG
- Redirects and Google Search, Google Search Central
- Configure cache by status code (default 20 minutes for 302), Cloudflare
Frequently Asked Questions
What does HTTP 302 mean?
Why am I getting a 302 instead of a 200?
Is 302 better than 301?
Does a 302 redirect hurt SEO?
What is the difference between 302 and 307?
Why does my POST become a GET after a 302?
Are 302 redirects cached by browsers?
How do I send a 302 redirect?
How do I check if a URL returns a 302?
Related Articles
Related Tools
Redirect Checker
Follow every redirect hop by hop: 301/302 chains, timing and bulk checks
HTTP Header Checker
Response headers exactly as sent, with a Mozilla Observatory security grade
SSL Certificate Check
Verify SSL certificate validity and security details
DNS Lookup
Every DNS record from the domain's own nameservers, beside Google's and Cloudflare's cache



