How to check if a redirect is 301 or 302
Run curl -sI <url> without -L and read the status line. HTTP/2 301 is permanent and browsers cache it, HTTP/2 302 is temporary and they ask again. For a one-line answer use curl -s -o /dev/null -w '%{http_code} %{redirect_url}' <url>.
Why check this
The code decides how long the redirect lives in other people's caches. A 301 that should have been a 302 is close to permanent: browsers store it, and a visitor who hit the wrong version keeps being sent there after the rule is removed. That is the failure this check prevents, and it takes a cache clear on every affected client to undo.
Run it whenever a route moves, a domain is merged, or a marketing redirect is added for a campaign with an end date. A campaign redirect must be a 302.
Prerequisites
- curl 7.52 or later. See the curl manual for
-I,-Land--write-out. - The URL as the client requests it. A missing trailing slash is often the thing that redirects.
- The MDN reference on redirections for the full code list.
Steps
- Step 1.
Ask for the headers only, and do not follow. Without
-L, curl shows the redirect itself instead of the destination.curl -sI 'https://httpbin.org/redirect-to?url=https://example.com/&status_code=301' | grep -i -E '^HTTP|location'HTTP/2 301 location: https://example.com/ - Step 2.
Repeat against the temporary form of the same redirect and compare the status line.
curl -sI 'https://httpbin.org/redirect-to?url=https://example.com/&status_code=302' | grep -i -E '^HTTP|location'HTTP/2 302 location: https://example.com/The
locationis identical. Only the code differs, and only the code tells a client whether to remember it. - Step 3.
Get the code and the destination on one line, which is the form to paste into a bug report.
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' 'https://httpbin.org/redirect-to?url=https://example.com/&status_code=301'301 https://example.com/ - Step 4.
Check what the code does to a POST. Send a body through a 302, then through a 307.
curl -sL -d 'a=b' -o /dev/null -w '%{num_redirects} redirects, final %{http_code}, method %{method}\n' 'https://httpbin.org/redirect-to?url=/post&status_code=302'1 redirects, final 405, method GETThe 302 turned the POST into a GET, and
/postanswered 405. Withstatus_code=307the same command returned1 redirects, final 200, method POST. - Step 5.
Follow a chain and count the hops, so a single check covers every code on the way.
curl -sIL https://httpbin.org/redirect/2 | grep -i -E '^HTTP|^location'HTTP/2 302 location: /relative-redirect/1 HTTP/2 302 location: /get HTTP/2 200
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| 301 or 308 | Permanent. Clients and search engines may cache it without an expiry | Correct only when the old URL is never coming back. |
| 302, 303 or 307 | Temporary. The client asks the original URL again next time | Correct for campaigns, maintenance pages and locale guesses. |
| 301 with no location | The redirect is broken | The client has nowhere to go. Treat it as a failure, not a redirect. |
| 200 where a redirect was expected | The rule did not fire | Check the exact path, the trailing slash and the scheme you requested. |
Common mistakes
What to check next
- How to check redirect chain: the full hop list, and the place a mixed 301 and 302 chain shows up.
- How to check HTTP to https redirect: the one redirect that should always be permanent.
- How to check cache-control header: the only way to put an expiry on a 301 a client already stored.
- How to check HTTP status code: the same reading applied to an API response.
FAQ
What is the difference between a 301 and a 302 redirect?
A 301 says the resource moved for good, so clients and search engines may cache the mapping and pass ranking signals to the new URL. A 302 says the move is temporary, so the client keeps using the original URL and asks again next time.
How to test 301 redirects?
Request the URL with curl -sI and read the status line, then confirm location points where you expect. Repeat from a fresh browser profile, because an old 301 may still be cached.
Does a 302 hurt search rankings?
It tells the crawler to keep indexing the original URL. That is correct for a temporary move and wrong for a permanent one, where the old URL stays in the index instead of the new one.
Which code should a campaign redirect use?
302, or 307 if the request may carry a body. The rule is removed when the campaign ends, and a permanent code would outlive it in client caches.
Does curl follow redirects by default?
No. Without -L it prints the redirect response and stops, which is what this check needs. A production example: curl -sI http://www.cloudflare.com/ returned HTTP/1.1 301 Moved Permanently with Location: https://www.cloudflare.com/.
Verified
Verified by Maks Vernycurl 8.21.0
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
basic4 minpublished updated Maks Verny