A long aisle between rows of black server racks in a brightly lit data center.
8 min read

HTTP Status Codes Explained: A Guide for Webmasters

Every HTTP response starts with a three-digit status code, and that number decides how browsers, search engine crawlers and uptime monitors treat your page. Most webmasters only ever deal with about twenty of the dozens of defined codes, but misreading one (a maintenance page served as 200, a permanent move served as 302) can cost traffic or hide an outage. This guide groups the codes you will actually meet, explains the usual cause of each, and shows how to treat them in monitoring.

How to read a status code

The first digit tells you the class:

  • 2xx success: the server understood the request and returned what was asked for.
  • 3xx redirection: the content is somewhere else, or the client's cached copy is still valid.
  • 4xx client error: the request was wrong, unauthorized or pointed at something that doesn't exist.
  • 5xx server error: the request may have been fine, but the server (or something behind it) failed.

The quickest way to see a code is curl:

# status code only
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/

# full redirect chain with each hop's status
curl -sIL https://example.com/ | grep -iE '^(HTTP|location)'

The status code reference table

CodeMeaningTypical causeSEO noteMonitoring note
200 OKSuccess, body returnedNormal page loadIndexable. Error pages served as 200 become "soft 404s"Up, but only proves the server answered; pair with a keyword check
201 CreatedResource createdSuccessful API POSTNot relevant to pagesAccept it for API checks that create something
204 No ContentSuccess, empty bodyAPI DELETE, health endpoints, beaconsNothing to indexUp; keyword checks cannot work on an empty body
301 Moved PermanentlyNew permanent URLHTTP to HTTPS, domain or URL changeGoogle treats it as a strong signal that the target is canonicalFollow redirects, or accept 301 if you monitor the old URL on purpose
302 FoundTemporary redirectLogin walls, geo or language redirects, frameworks' default redirect()Weak canonical signal; the original URL tends to stay indexedOften a sign of a session or login redirect you didn't expect
304 Not ModifiedCached copy is still validConditional request with If-None-Match / If-Modified-SinceNormal and saves crawl resourcesA plain monitor request won't get it unless it sends conditional headers
307 Temporary RedirectLike 302, method must not changeHSTS internal redirect in browsers, API redirectsTreated like 302Same as 302
308 Permanent RedirectLike 301, method must not changePermanent moves of API endpoints or form targetsTreated like 301Same as 301
400 Bad RequestMalformed requestBroken query string, oversized cookie, invalid JSONNot indexedUsually a problem with the check itself (URL, headers)
401 UnauthorizedAuthentication requiredHTTP Basic Auth, missing API tokenNot indexedExpected on protected staging sites; supply credentials or accept 401
403 ForbiddenAuthenticated or not, access refusedFile permissions, WAF or bot protection, IP allowlistNot indexed; if Googlebot gets 403 sitewide, pages drop outOften a firewall blocking the monitor; investigate before accepting
404 Not FoundNothing at this URLDeleted page, typo, broken deploy, missing rewrite rulesRemoved from the index over time; normal for genuinely gone pagesOn a URL that should exist, this is an outage
410 GoneRemoved on purpose, permanentlyDeliberately retired contentClear "gone" signal; Google has said the difference from 404 is small in practiceRarely something to monitor
429 Too Many RequestsRate limitedAPI quotas, WAF rate rules, aggressive crawlingGoogle's crawlers slow down when they receive itYour monitor interval may be tripping a rate limit
500 Internal Server ErrorUnhandled application errorCode exception, bad config, failed migration, .htaccess syntax errorCrawlers back off; prolonged 5xx can lead to URLs being droppedDown
502 Bad GatewayProxy got an invalid response from upstreamPHP-FPM, Node or Gunicorn down or crashed; socket misconfiguredSame as 500Down; usually fixable by restarting the upstream
503 Service UnavailableTemporarily unable to serveMaintenance mode, overload, no healthy backendsThe correct code for planned maintenance, ideally with Retry-AfterDown, unless inside a planned maintenance window
504 Gateway TimeoutProxy gave up waiting for upstreamSlow queries, stuck workers, long-running requestsSame as 500Down; check response-time trends before it happened

2xx: success, but not necessarily a working page

A 200 tells you the server produced a response. It says nothing about whether that response is your product page or a blank template, a database error message or a "Welcome to nginx!" placeholder. Google calls error pages served with 200 soft 404s and reports them in Search Console; they waste crawl budget and can be dropped from the index. For uptime purposes the risk is the opposite: the monitor shows green while customers see a broken site. That is why a status check alone is not enough for important pages; see keyword monitoring for broken pages that return 200 OK.

3xx: pick the right redirect

The practical rule is simple: if the move is permanent, use 301 (or 308 when the HTTP method must be preserved, for example a POST endpoint). If it is temporary, use 302 or 307. Google's documentation describes permanent redirects as a strong signal that the target should be shown in search results and temporary ones as a weak signal. A common mistake is that many frameworks issue 302 by default, so an HTTP-to-HTTPS or old-URL redirect implemented in application code may be temporary without anyone deciding so. Check with curl -sI.

Also watch out for redirect chains (HTTP → HTTPS → www → trailing slash). Each hop adds a round trip; collapse them into one redirect straight to the final URL.

304 is not an error and not a redirect in the usual sense. It only appears when the client sent a conditional header, and it means "use your cached copy".

4xx: the request didn't work

401 vs 403 confuses people. 401 means "who are you?": the client should authenticate and retry, and the response includes a WWW-Authenticate header. 403 means "I know, or don't care, who you are, and the answer is no". In practice 403s on a public site usually come from a web application firewall, a bot-protection service, a geo block or wrong file permissions (the web server user can't read the file).

404 vs 410: both tell search engines the page is gone. 410 is more explicit, and some people use it to speed up removal of deliberately retired content, though Google has said the difference is minor. What matters more is not serving a 200 "Page not found" template, which creates soft 404s.

429 means rate limiting. If a monitor starts getting 429s, the check interval or the shared IP of the monitoring service may be tripping a rule; allowlist the monitor or relax the rule rather than ignoring the alerts.

5xx: the server failed

5xx is what uptime monitoring exists to catch. The codes point to different layers:

  • 500 comes from the application itself. Look at the application log (Laravel's storage/logs, PHP's error log, your framework's stderr).
  • 502 and 504 come from a proxy (nginx, Apache, a load balancer, a CDN) talking to an upstream. 502 means the upstream answered badly or not at all; 504 means it took too long. The guides on fixing 502 Bad Gateway and diagnosing 504 Gateway Timeout go through the causes.
  • 503 is the honest "come back later". Use it for maintenance, and add a Retry-After header. Google's crawler documentation says 5xx and 429 responses make Googlebot temporarily slow its crawl, and that URLs persistently returning server errors can eventually be removed from the index. A short planned 503 is the safe way to take a site down; serving a maintenance page with 200 risks it being indexed as your content.

Configuring a monitor: what counts as "up"

A sensible default is: 2xx is up, 3xx is followed, 4xx and 5xx are down. Real sites need exceptions, and that is what an "accepted status codes" setting is for.

SituationSetting
Public websiteFollow redirects on; accept 200
Staging site behind Basic AuthProvide the credentials, or accept 401 if you only care that the server answers
Checking that a redirect itself exists (old domain, short link)Follow redirects off; accept 301 (or 308)
API health endpoint returning 204Accept 204; skip keyword checks
Admin login that bounces to /loginMonitor the login page itself instead of accepting 302

Avoid accepting 403 or 5xx codes to silence noise. If a firewall blocks your monitor, fix the firewall rule; otherwise you will also miss the day the 403 is real.

FAQ

Is a 301 or a 302 better for SEO?

Neither is "better"; they mean different things. Use 301 (or 308) for permanent moves so search engines transfer to the new URL, and 302 (or 307) only for genuinely temporary detours.

What status code should a maintenance page return?

503 Service Unavailable, ideally with a Retry-After header. A 200 maintenance page can be indexed in place of your content and hides the outage from monitors.

Why does my browser show the page but my monitor reports 403?

Bot protection and WAF rules often treat requests without a browser fingerprint, or from data-center IP ranges, differently. Allowlist the monitoring service's requests or relax the rule for your check URL.

Key takeaways

  • The first digit tells you the layer: 2xx success, 3xx redirect, 4xx client, 5xx server.
  • A 200 only proves the server answered; error pages served as 200 are soft 404s and invisible outages.
  • Use 301/308 for permanent moves and 302/307 for temporary ones; check what your framework actually sends.
  • 502 and 504 come from a proxy and point at the upstream; 500 points at the application.
  • Serve maintenance as 503 with Retry-After.
  • Accept extra status codes in monitoring only when they are expected (401 on staging, 301 on a redirect check), never to mute a real problem.

Uptime Monitor records the status code of every check and tags each failure with a cause such as server_5xx, not_found_404, client_4xx or redirect_3xx, so an alert tells you which layer broke. Per site you can set accepted status codes, turn redirect following on or off, add Basic Auth credentials and require a keyword in the response. The free Starter plan covers one website with checks every five minutes.

Keep reading