HTTP 302 Found: przekierowanie 302, 302 vs 301 i błąd 302

Kluczowy wniosek

HTTP 302 Found to tymczasowe przekierowanie, a nie błąd: serwer informuje, że strona jest na razie pod innym adresem URL, podanym w nagłówku Location. Przeglądarka od razu wczytuje ten adres, a linki i wyszukiwarki zostają przy oryginalnym. Przy trwałej zmianie używaj 301 lub 308: spośród 20 dużych witryn, które sprawdziliśmy, żadna nie używała do tego 302. Z 302 spotkasz się najczęściej, gdy strona wymaga logowania. Idąc za przekierowaniem 302, przeglądarki zamieniają POST na GET: użyj 307, by zachować metodę, albo 303 po wysłaniu formularza.

Sprawdź teraz

Infografika kodu statusu HTTP 302 — przepływ tymczasowego przekierowania z nagłówkiem Location oraz porównanie 301 vs 302 vs 307
Infografika kodu statusu HTTP 302 — przepływ tymczasowego przekierowania z nagłówkiem Location oraz porównanie 301 vs 302 vs 307
Zacznij czytać
  1. Czym jest kod statusu 302?
  2. Budowa odpowiedzi 302
  3. Dlaczego dostaję 302 zamiast 200?
  4. 302 vs 301 vs 307 vs 308: której przekierowania użyć?
  5. Kiedy używać przekierowania 302?
  6. Jak wysłać kod statusu 302
  7. Jak przetestować kod statusu 302
  8. Przekierowania 302 a SEO
  9. Dlaczego 302 zmienia żądania POST na GET
  10. Najczęstsze błędy 302 i jak je naprawić
  11. Pętle przekierowań 302: jak je zdiagnozować
  12. Dobre praktyki dla kodu statusu 302
  13. Jak przeglądarki i narzędzia obsługują 302
  14. Często Zadawane Pytania

Czym jest kod statusu 302?

HTTP 302 Found to tymczasowe przekierowanie. Serwer odpowiada: „to, o co prosisz, jest na razie gdzie indziej” i podaje drugi adres URL w nagłówku Location. Przeglądarka od razu wczytuje ten adres, ale zakładki, linki i wyszukiwarki powinny nadal używać oryginalnego (RFC 9110 §15.4.3).

To „na razie” jest całą różnicą wobec 301 Moved Permanently, które mówi, że stary adres zniknął na stałe. HTTP/1.0 nazywał 302 „Moved Temporarily” (RFC 1945); RFC 2616 zmieniła nazwę na „Found” w 1999 roku, ale znaczenie zostało to samo.

Jako użytkownik rzadko widzisz 302, bo przeglądarka podąża za nim, zanim cokolwiek się pojawi. Spotkasz go w DevTools, w curl, w klientach API i w audytach SEO.

Zobacz każde przekierowanie i jego kod statusu

Budowa odpowiedzi 302

Odpowiedź 302 jest niewielka. Jej części:

  • Linia statusu — HTTP/1.1 302 Found albo samo HTTP/2 302 (HTTP/2 nie ma frazy opisowej)
  • Location — adres docelowy. RFC 9110 mówi, że serwer POWINIEN go wysłać; bez niego przeglądarka nie ma dokąd iść i pokazuje treść samego 302, zwykle pustą
  • Treść — RFC 9110 mówi, że „zwykle zawiera krótką notatkę hipertekstową” z linkiem. Przeglądarki ją ignorują; nginx, Apache i Express domyślnie wysyłają jednowierszową notatkę, a wiele dużych witryn wysyła pustą treść
  • Nagłówki pamięci podręcznej — niepotrzebne. Przeglądarki nie zapisują 302 w pamięci podręcznej, chyba że dodasz Cache-Control: max-age albo Expires; 301 i 308 są natomiast zapisywane domyślnie. CDN nadal może go zapisać (zobacz „302, który się przykleja” poniżej)
http
HTTP/1.1 302 Found
Location: https://www.example.com/login?next=%2Fdashboard
Content-Length: 0
Date: Mon, 26 Oct 2026 14:00:00 GMT

Location może być pełnym adresem URL albo ścieżką względną, jak /login: RFC 9110 dopuszcza dowolne odwołanie URI, a przeglądarki rozwiązują je względem adresu, o który prosiły. W kodzie aplikacji (np. Express) ścieżka względna pozwala nie ujawniać wewnętrznej nazwy hosta ani http:// zza proxy; nginx i Apache i tak zamieniają ją na adres bezwzględny, chyba że ustawisz absolute_redirect off albo RedirectRelative On.

Dlaczego dostaję 302 zamiast 200?

Bo strona chce czegoś, czego twoje żądanie nie przyniosło, albo adres URL, którego użyłeś, nie jest tym, który serwuje witryna. Najczęstsze powody:

  • Nie jesteś zalogowany — strony za logowaniem odpowiadają 302 na stronę logowania, a stronę, którą chciałeś, przekazują w parametrze powrotu. Bez zalogowania github.com/settings odsyła do /login?return_to=…. W curl lub kliencie API wyślij ciasteczko sesji albo token.
  • Twój klient nie podąża za przekierowaniami — przeglądarki, fetch() i requests z Pythona robią to automatycznie. curl nie, chyba że dodasz -L; zatrzymuje się na 302 i wypisuje tylko jego treść, często nic (dodaj -i, by zobaczyć status i Location).
  • Adres URL nie jest tym, który serwuje witryna — brakujący lub dodatkowy ukośnik na końcu, ścieżka językowa albo link śledzący, który cię odsyła dalej. res.redirect() w Expressie, return w nginx tylko z adresem URL i Redirect w Apache wysyłają 302, o ile nie podasz innego kodu.
  • Coś przed serwerem dodaje przekierowanie — jeśli serwer źródłowy odpowiada 200, gdy testujesz go bezpośrednio, a publiczny adres daje 302, to przekierowuje reguła CDN, load balancera lub proxy.

API zwykle odpowiadają na brak logowania kodem 401 Unauthorized, a nie przekierowaniem. Aby zobaczyć każdy skok i jego kod statusu, przepuść adres URL przez Checker przekierowań.

302 vs 301 vs 307 vs 308: której przekierowania użyć?

Pięć kodów przekierowań obejmuje prawie wszystkie przypadki. Różnią się pod dwoma względami: czy zmiana jest trwała i czy POST pozostaje POST-em:

KodTrwałe?POST w przeglądarkachDomyślnie w pamięci podręcznej?Najlepsze do
301 Moved PermanentlyTakZmienia się w GETTakTrwałe zmiany adresu URL, przeprowadzki domeny
302 FoundNieZmienia się w GETNieLogowania, krótkotrwałe zmiany, testy A/B
303 See OtherNieZmienia się w GETNieStrona wyświetlana po wysłaniu formularza
307 Temporary RedirectNiePozostaje POSTNieTymczasowe zmiany, które muszą zachować metodę
308 Permanent RedirectTakPozostaje POSTTakTrwałe zmiany, które muszą zachować metodę

303 i 307 istnieją z powodu 302. HTTP/1.1 dodał 303 w 1997 roku, a w 1999 RFC 2616 przyznała, że „większość istniejących implementacji klientów traktuje 302 tak, jakby był odpowiedzią 303”, dodała 307 i zmieniła nazwę 302 na „Found” (RFC 2616 §10.3.3). Jeśli tymczasowe przekierowanie może dostać POST, użyj 307, by go zachować, albo 303, by następną stronę wczytać metodą GET.

Kiedy używać przekierowania 302?

Użyj 302, gdy spodziewasz się, że przekierowanie zniknie. Typowe przypadki:

  • Przekierowania do logowania — wysłanie niezalogowanego użytkownika z /dashboard do /login, a po zalogowaniu z powrotem
  • Testy A/B — wysyłanie części odwiedzających na stronę wariantu; własne wskazówki Google dotyczące testów mówią, by użyć tu 302, a nie 301 (Google Search Central)
  • Strony w naprawie — odsyłanie odwiedzających na kilka dni do strony z komunikatem, gdy strona jest przebudowywana
  • Krótkotrwałe adresy kampanii — /black-friday wskazujący na tegoroczną wyprzedaż tylko na czas wyprzedaży
  • Konserwacja — tylko dla odwiedzających; dla wyszukiwarek lepszą odpowiedzią podczas planowanej niedostępności jest 503 z Retry-After

Jeśli któryś z tych przypadków stanie się trwały, zmień go na 301.

Jak wysłać kod statusu 302

Większość serwerów i frameworków ma jednowierszowy sposób wysłania 302. Każdy z poniższych wysyła 302 Found z nagłówkiem Location, czyli wszystko, czego 302 potrzebuje.

Nginx

W nginx użyj return z kodem. return tylko z adresem URL też wysyła 302 (dokumentacja nginx):

nginx
server {
    listen 80;
    server_name example.com;

    # Temporary redirect (302 Found)
    location /old-page {
        return 302 https://example.com/new-page;
    }
}

Apache (.htaccess)

W Apache użyj Redirect (302 to jego domyślny kod, gdy nie podasz statusu) albo RewriteRule z [R=302,L]:

apache
# 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)

res.redirect() w Expressie domyślnie używa 302, gdy nie podasz kodu statusu:

javascript
// 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')

Jak przetestować kod statusu 302

Najszybszy test to curl w terminalu: pokazuje kod statusu i nagłówek Location, a pamięć podręczna przeglądarki nie wchodzi w grę.

bash
# 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:)'

Nie masz terminala? Checker przekierowań DNS Robot podąża za każdym skokiem (301, 302, 303, 307, 308 i meta refresh) z naszego serwera i pokazuje każdy kod statusu oraz końcowy adres URL, a Checker nagłówków HTTP pokazuje surowe nagłówki każdego skoku w sekcji Redirects.

Przekierowania 302 a SEO

Google traktuje oba rodzaje przekierowań jako różne instrukcje. Przy przekierowaniu tymczasowym (302, 303, 307) Googlebot za nim podąża, ale Google nie uznaje go za sygnał, że adres docelowy powinien być kanoniczny, więc strona źródłowa zwykle zostaje w wynikach wyszukiwania. Adres docelowy nadal może zostać zaindeksowany, jeśli wskazują na niego inne sygnały (Google Search Central).

Przekierowanie trwałe (301, 308) mówi coś przeciwnego: pokaż nowy adres URL. Prawdziwe pytanie brzmi więc nie „czy 302 przekazuje PageRank?”, lecz „który adres URL chcę mieć w wynikach wyszukiwania?”. Znacznik rel=canonical to jeden z pozostałych sygnałów; Sprawdzanie meta tagów pokazuje, jaki adres deklaruje strona.

  • Do zmian trwałych używaj 301 lub 308 — nowa domena, nowa struktura adresów, połączone strony
  • Do tymczasowych używaj 302 — logowania, testy A/B, kampanie
  • Nie zostawiaj trwałej zmiany na 302 — Google może nadal pokazywać stary adres URL
  • Trzymaj łańcuchy krótko — każdy skok to kolejne zapytanie w obie strony, a Googlebot domyślnie podąża za maksymalnie 10 skokami (Google)

Dlaczego 302 zmienia żądania POST na GET

To najbardziej zaskakująca cecha 302. Wczesne specyfikacje nigdy nie pozwalały klientom zmieniać metody, ale przeglądarki i tak zamieniały POST na GET przy 302. Dziś Fetch Standard, który implementują przeglądarki, spisuje ten nawyk: przy 301 lub 302 POST staje się GET, a jego treść jest odrzucana (Fetch Standard).

Gdy więc przeglądarka wysyła POST /submit-form, a serwer odpowiada 302 Found, przeglądarka podąża z GET /thank-you, a dane formularza przepadają. Przeglądarki zachowują PUT i DELETE bez zmian; inni klienci zachowują się różnie: requests z Pythona zamienia każdą metodę poza HEAD na GET przy 302, a curl -L zamienia POST na GET przy 301, 302 i 303 (--post302 zachowuje POST przy 302).

http
# 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.com

Jeśli przekierowanie ma zachować oryginalną metodę (POST pozostaje POST, PUT pozostaje PUT), użyj 307 Temporary Redirect. Jeśli celowo chcesz odrzucić treść i przejść na GET — klasyczny wzorzec POST/Redirect/GET — użyj 303 See Other. Oba są jednoznaczne; 302 nie jest.

Najczęstsze błędy 302 i jak je naprawić

Gdy 302 sprawia kłopot, zwykle chodzi o jedną z tych rzeczy:

  • 302 zamiast 200 — strona za logowaniem, klient, który nie podąża za przekierowaniami, albo wariant adresu URL (zobacz „Dlaczego dostaję 302” powyżej)
  • 302 bez nagłówka Location — nic nie może za nim podążyć, a przeglądarka pokazuje treść samego 302, zwykle pustą. Ustaw Location przed wysłaniem statusu
  • 302 wskazujący na samego siebie — pętla przekierowań: reguła uruchamia się na własnym celu. Dodaj brakujący warunek
  • Formularz, który traci dane — POST → 302 → GET odrzuca treść. Użyj 303, by celowo pokazać stronę wyniku, albo 307, by zachować POST
  • 302, który się przykleja — serwer wysłał z nim Cache-Control: max-age lub Expires, więc przeglądarki zapisały go w pamięci podręcznej, albo zrobił to twój CDN (przy treściach, które Cloudflare zapisuje, trzyma 302 przez 20 minut, o ile nagłówki nie mówią inaczej, dokumentacja Cloudflare). Usuń te nagłówki, wyczyść pamięć CDN i przeglądarki
  • 302 na produkcji, ale nie lokalnie — często reguła CDN, load balancera lub proxy dodająca przekierowania. Przetestuj serwer źródłowy bezpośrednio, żeby się przekonać

Pętle przekierowań 302: jak je zdiagnozować

Pętla przekierowań to sytuacja, gdy adres A odsyła do B, a B odsyła z powrotem do A. Po 20 przekierowaniach, czyli limicie z Fetch Standard, Chrome rezygnuje z ERR_TOO_MANY_REDIRECTS, a Firefox z komunikatem „Pętla przekierowań”.

Klasyczną przyczyną jest tryb szyfrowania Flexible w Cloudflare: Cloudflare łączy się z twoim serwerem przez zwykły HTTP, serwer przekierowuje HTTP na HTTPS, a Cloudflare znów pyta przez HTTP (dokumentacja Cloudflare).

bash
# 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 confirmed

Jeśli ten sam adres URL wciąż wraca w Location, wskazując na siebie albo dwa adresy przekazują się nawzajem, masz pętlę (przy trybie Flexible w Cloudflare https://example.com/ przekierowuje do samego siebie). Pełne rozwiązanie znajdziesz w naszym poradniku o ERR_TOO_MANY_REDIRECTS. Checker przekierowań DNS Robot prześledzi łańcuch z naszego serwera i zatrzyma się tam, gdzie zaczyna się pętla.

Dobre praktyki dla kodu statusu 302

Kilka nawyków pozwala uniknąć większości problemów z 302:

  • Zawsze wysyłaj nagłówek Location — bez niego nic nie podąży za przekierowaniem
  • Nie dodawaj nagłówków pamięci podręcznej — 302 bez max-age lub Expires nie jest zapisywany, i o to chodzi
  • Uważaj na adresy bezwzględne za proxy — w kodzie aplikacji względne /login pozwala nie ujawniać wewnętrznej nazwy hosta ani http:// w Location; nginx i Apache budują adresy bezwzględne ze swoich ustawień
  • Ogranicz się do jednego skoku — A → B jest w porządku; A → B → C dodaje kolejne zapytanie w obie strony dla każdego odwiedzającego
  • Nigdy nie przekierowuj POST-a na inną stronę kodem 302 — użyj 303, by pokazać stronę wyniku, albo 307, by zachować POST
  • Przeglądaj stare przekierowania tymczasowe — często przeżywają swój powód. Sprawdź je Checkerem przekierowań
  • Zmień na 301, gdy tylko zmiana stanie się trwała

Jak przeglądarki i narzędzia obsługują 302

Klienci zgadzają się co do podążania za 302, ale różnią się limitami i tym, co dzieje się z metodą:

KlientCo robi z 302Limit przekierowań
Chrome, Edge, Firefox, SafariPodąża od razu; POST zmienia się w GET20 (Fetch Standard)
fetch() w JavaScriptDomyślnie podąża (redirect: "follow"); ta sama reguła dla POST20
curlNie podąża; wypisuje tylko treść 302, często pustą (dodaj -i lub -I, by zobaczyć status i Location)Brak (nie podąża)
curl -LPodąża; POST zmienia się w GET przy 301, 302 i 303 (--post301, --post302, --post303 go zachowują)50 (--max-redirs)
wgetPodąża20 (--max-redirect)
Python requestsPodąża; każda metoda poza HEAD zmienia się w GET30
GooglebotPodąża; zachowuje adres źródłowy jako wynik wyszukiwaniaDomyślnie 10 skoków

Dokładne brzmienie znajdziesz w definicji 302 w RFC 9110 i na stronie MDN o 302.

Prześledź dowolny łańcuch przekierowań w kilka sekund

Użyj darmowego Checkera przekierowań DNS Robot, aby zobaczyć każdy skok w łańcuchu przekierowań: kody statusu, nagłówki Location i adres docelowy widziany z neutralnego serwera (bez pamięci podręcznej przeglądarki).

Źródła

  1. RFC 9110: HTTP Semantics, 302 Found, IETF
  2. Fetch Standard: HTTP-redirect fetch, WHATWG
  3. Redirects and Google Search, Google Search Central
  4. Configure cache by status code (default 20 minutes for 302), Cloudflare

Często Zadawane Pytania

Co oznacza HTTP 302?

HTTP 302 Found to tymczasowe przekierowanie: zasób jest na razie pod innym adresem URL, podanym w nagłówku Location odpowiedzi. Przeglądarka od razu za nim podąża, ale linki, zakładki i wyszukiwarki powinny nadal używać oryginalnego adresu. Jego trwałym odpowiednikiem jest 301 Moved Permanently.

Dlaczego dostaję 302 zamiast 200?

Zwykle dlatego, że strona wymaga logowania (przekierowuje do strony logowania), twój klient nie podąża za przekierowaniami (curl potrzebuje -L), adres URL nie jest dokładnie tym, który serwuje witryna (ukośnik na końcu lub ścieżka językowa) albo przekierowanie dodaje reguła CDN lub proxy przed serwerem. Checker przekierowań pokazuje każdy skok i jego status.

„Błąd 302”: czy to naprawdę błąd?

Nie. Według RFC 9110 kody 3xx to przekierowania, a błędy to kody 4xx (po stronie klienta) i 5xx (po stronie serwera). 302 mówi tylko, że strona jest na razie gdzie indziej. O „błędzie 302” mówi się, gdy przekierowanie nie działa: strona wymaga logowania, narzędzie nie podąża za przekierowaniami (curl bez -L), odpowiedź nie ma nagłówka Location albo przekierowanie wpada w pętlę. W tym ostatnim przypadku Chrome pokazuje ERR_TOO_MANY_REDIRECTS, a w Pythonie urllib zgłasza „HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop”. Checker przekierowań pokazuje, na którym skoku łańcuch się łamie.

Czy 302 jest lepszy od 301?

Żaden nie jest lepszy; mówią co innego. Użyj 301 (lub 308), gdy strona przeniosła się na stałe i chcesz, by wyszukiwarki pokazywały nowy adres URL. Użyj 302, gdy zmiana jest tymczasowa, a oryginalny adres ma zostać w wynikach wyszukiwania, np. przy przekierowaniach do logowania, testach A/B i kampaniach.

Czy przekierowanie 302 szkodzi SEO?

Nie, jeśli zmiana naprawdę jest tymczasowa. Google podąża za 302, ale nie uznaje go za sygnał, że adres docelowy powinien być kanoniczny, więc oryginalny adres URL zwykle zostaje w wynikach wyszukiwania. Szkodzi dopiero użycie go przy zmianie trwałej: wtedy Google może nadal pokazywać stary adres zamiast nowego.

Jaka jest różnica między 302 a 307?

Oba są przekierowaniami tymczasowymi. Przeglądarki zamieniają POST na GET, idąc za 302, i odrzucają treść; 307 zachowuje metodę i treść, więc POST pozostaje POST-em. Używaj 307 zawsze, gdy tymczasowe przekierowanie może dostać formularz lub wywołanie API inne niż GET.

Dlaczego mój POST zmienia się w GET po 302?

Przeglądarki robią tak od lat 90., a Fetch Standard teraz tego wymaga: przy 301 lub 302 POST jest ponownie wysyłany jako GET bez treści. Zwróć 307 Temporary Redirect, aby zachować POST, albo 303 See Other, jeśli GET jest zamierzony, jak we wzorcu post/redirect/get po formularzu.

Czy przeglądarki zapisują przekierowania 302 w pamięci podręcznej?

Domyślnie nie. RFC 9110 nie czyni 302 możliwym do zapisania bez jawnej świeżości, więc przeglądarki zapisują go tylko wtedy, gdy serwer doda Cache-Control: max-age lub Expires. CDN może się różnić: przy treściach, które zapisuje, Cloudflare trzyma 302 przez 20 minut, o ile nagłówki nie mówią inaczej. 301 i 308 to przeciwieństwo: przeglądarki zapisują je, chyba że powiedziano inaczej.

Jak wysłać przekierowanie 302?

Wyślij linię statusu HTTP/1.1 302 Found oraz nagłówek Location z nowym adresem URL. W nginx: return 302 https://example.com/new-page; W Apache: Redirect 302 /old https://example.com/new. W Expressie: res.redirect('/new'), co domyślnie wysyła 302.

Jak sprawdzić, czy adres URL zwraca 302?

Uruchom w terminalu curl -sI https://example.com/twoj-adres: wypisze kod statusu i Location bez podążania za przekierowaniem. Bez terminala wklej adres do darmowego Checkera przekierowań DNS Robot, który podąża za każdym skokiem i pokazuje każdy kod statusu oraz końcowy adres URL.

O autorze

Shaik Vahid

Założyciel DNS Robot. Vahid przez lata pracował we wsparciu hostingu, naprawiając klientom domeny, rekordy DNS, certyfikaty SSL i dostarczanie poczty. Tworzy narzędzia DNS Robot i pisze te poradniki na podstawie błędów, które ludzie naprawdę widzą.

Sprawdzanie Przekierowań

Sprawdź przekierowania URL, łańcuchy przekierowań i kody statusu HTTP dla SEO