DEVESSENTIALS

HTTP 302 Found

A 302 sends the client to the Location URL for this request only. The original URL stays authoritative, so clients shouldn't update bookmarks, and caches don't store the redirect unless Cache-Control or Expires explicitly allows it.

3xx · RedirectionRFC 9110 §15.4.3

302 Found

The resource is temporarily at a different URL; keep using the original URL for future requests.

Who fixes it: Server config. Clients follow it automatically. Problems come from servers using 302 where a 301, 307 or 401 was meant.

What 302 means

The name "Found" is a leftover from HTTP/1.0, where it was "Moved Temporarily". As with 301, user agents may change a POST to a GET when following it, and browsers do. That ambiguity is why HTTP/1.1 added 303 See Other (always switch to GET) and 307 Temporary Redirect (never switch).

302 is the default in many frameworks: Express res.redirect(), PHP header('Location: ...'), Flask redirect() and Django redirect() all send 302 unless told otherwise.

Source: RFC 9110 §15.4.3.

Typical reasons you get a 302

  • Login walls: an unauthenticated request to /dashboard is redirected to /login?next=/dashboard. For an API this is a bug, because a JSON client wants a 401, not an HTML login page.
  • Post/Redirect/Get after a form submission. 303 is the precise code; 302 is what most frameworks send.
  • Geo, language or device redirects (/ to /en-gb/).
  • Temporary maintenance or campaign redirects.
  • A permanent move implemented with the framework default. This is the most common SEO mistake involving 302.

How to debug a 302

See the redirect with curl

curl doesn't follow redirects unless you pass -L, so you see the 302 and its Location.

curl -sI https://example.com/dashboard

HTTP/2 302
location: /login?next=%2Fdashboard

# Follow it and print every hop
curl -sIL https://example.com/dashboard | grep -iE '^(HTTP|location)'

Express: be explicit, and send 401 to API clients

Don't rely on the 302 default for permanent moves, and don't redirect API calls to an HTML login page.

// Permanent move
app.get('/old', (req, res) => res.redirect(301, '/new'));

// Auth: redirect browsers, 401 for API calls
function requireAuth(req, res, next) {
  if (req.user) return next();
  if (req.path.startsWith('/api/')) {
    return res.status(401).json({ error: 'unauthenticated' });
  }
  res.redirect(302, `/login?next=${encodeURIComponent(req.originalUrl)}`);
}

Detect silent redirects in fetch()

fetch() follows redirects without telling you. res.redirected and res.url reveal it. With redirect: 'manual' a browser gives you an opaque response with status 0, so you can't read Location from JavaScript.

const res = await fetch('/api/me');
if (res.redirected) {
  console.warn('Redirected to', res.url); // often a login page returning HTML
}

Headers that matter with 302

Location
The temporary target.
Cache-Control
A 302 is only cached if explicitly allowed. Send Cache-Control: no-store on redirects that depend on login state.

302 vs similar status codes

  • 301 Moved Permanently: Permanent. Clients and search engines move to the new URL.
  • 307 Temporary Redirect: Also temporary, but the method and body must be kept. Use it when a POST must stay a POST.
  • 303 See Other: Always fetch the target with GET. The precise code for Post/Redirect/Get.

SEO impact of 302

Google treats a 302 as a weak signal that the target should be canonical, so the original URL usually stays in the index. That's correct for genuinely temporary moves. If the move is permanent, switch to 301 or 308; Google may eventually treat a long-lived 302 as permanent, but you're leaving the decision to it.

Related status codes

Looking for another code? Search the full HTTP status codes list, or read which code your API should return in the REST API status codes guide.

Learn more

Browse all developer guides →

Frequently Asked Questions

What is the difference between 302 and 307?▾

Both are temporary. With 302, browsers change a POST to a GET when following the redirect. With 307 the method and body must stay the same. Use 307 when a redirected POST, PUT or DELETE has to reach the new URL intact.

Is a 302 redirect bad for SEO?▾

Not when the redirect really is temporary. It becomes a problem when a permanent move is left on 302, because Google may keep showing the old URL. Use 301 or 308 for permanent moves.

Why does my API return 302 instead of 401?▾

Usually session-based auth set up for web pages, such as Spring Security form login, ASP.NET Core cookie authentication or Passport's failureRedirect, redirects every unauthenticated request to the login page. Configure it to return 401 for API routes or for requests that send Accept: application/json.