The server has received the request headers and the client should proceed to send the request body. This interim respons...
The server has received the request headers and the client should proceed to send the request body. This interim response indicates that everything so far is OK and the client should continue with the request, or ignore it if it is already finished.
When you'll see this: Used with large request bodies. The client sends the request headers with an Expect: 100-continue header and waits for this response before sending the body. Avoids sending large payloads to a server that will reject the request anyway.
The server understands and is willing to comply with the client's request, via the Upgrade header field, for a change in...
The server understands and is willing to comply with the client's request, via the Upgrade header field, for a change in the application protocol being used on this connection.
When you'll see this: Sent when upgrading from HTTP/1.1 to WebSocket, or from HTTP/1.1 to HTTP/2 (via Upgrade header). After this response, the connection switches to the new protocol.
Related headers:UpgradeConnection
Laravel
// WebSocket upgrade handled by Laravel Reverb or Pusher
response('', 101)->withHeaders(['Upgrade' => 'websocket', 'Connection' => 'Upgrade']);
A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request....
A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request. This code indicates that the server has received and is processing the request, but no response is available yet.
When you'll see this: WebDAV servers send this to prevent the client from timing out during long operations. Rarely seen outside of WebDAV contexts.
Used to return some response headers before final HTTP message. Allows the client to start preloading resources while th...
Used to return some response headers before final HTTP message. Allows the client to start preloading resources while the server prepares the full response.
When you'll see this: Send Link headers for CSS/JS/fonts before the full HTML response is ready. Modern browsers use this to start preloading critical resources, reducing perceived page load time.
The request has succeeded. The meaning of a success depends on the HTTP request method: GET: The resource has been fetch...
The request has succeeded. The meaning of a success depends on the HTTP request method: GET: The resource has been fetched and is transmitted in the message body. POST: The resource describing the result of the action is transmitted in the message body.
When you'll see this: The standard response for successful HTTP requests. The actual response will depend on the request method used. Return this for successful GET, PUT, or POST requests that return data.
Common Mistake
Never return HTTP 200 with an error message in the body (e.g., {"error": "not found"}). Use the appropriate error status code instead.
Related headers:Content-TypeContent-Length
Laravel
return response()->json($data);
// or return response()->json($data, 200);
PHP
http_response_code(200);
// HTTP 200 is the default, so often not needed explicitly
// Response::HTTP_OK constant = 200
The request has been fulfilled, resulting in the creation of a new resource. The new resource is effectively created bef...
The request has been fulfilled, resulting in the creation of a new resource. The new resource is effectively created before this response is sent and the new resource is returned in the body of the message.
When you'll see this: Return after a successful POST that creates a resource. Include a Location header pointing to the new resource URL. The response body should contain the created resource.
The request has been received but not yet acted upon. It is non-committal, since there is no way for HTTP to later send...
The request has been received but not yet acted upon. It is non-committal, since there is no way for HTTP to later send an asynchronous response indicating the outcome of the request. It is intended for cases where another process or server handles the request, or for batch processing.
When you'll see this: Use when a request has been queued for async processing (dispatching a Laravel Job). The client should poll a status endpoint or wait for a webhook. Common for email sending, report generation, video encoding.
Related headers:Content-Type
Laravel
// Dispatch a job and return 202
ProcessOrderJob::dispatch($order);
return response()->json(['message' => 'Processing', 'job_id' => $jobId], 202);
The returned metadata is not exactly the same as is available from the origin server, but is collected from a local or a...
The returned metadata is not exactly the same as is available from the origin server, but is collected from a local or a third-party copy. Used mainly for mirrors or backups of a resource.
When you'll see this: Sent by a proxy that has transformed the response (e.g., translated, modified headers, or returned cached data from a third party). Rarely used in modern APIs.
The server has successfully fulfilled the request and there is no additional content to send in the response payload bod...
The server has successfully fulfilled the request and there is no additional content to send in the response payload body. The server's current document view should be updated without loading the response body.
When you'll see this: Return after a successful DELETE, or a PUT/PATCH that produces no meaningful output. The browser or API client should not navigate away. Do not return a body with 204.
Common Mistake
Do not return a body with 204 — the body is ignored by clients. If you need to return data, use 200 instead.
The server has fulfilled the request and desires that the user agent reset the document view, which caused the request t...
The server has fulfilled the request and desires that the user agent reset the document view, which caused the request to be sent, to its original state as received from the origin server.
When you'll see this: Used after form submission to tell the browser to clear the form. Rarely used in APIs. Useful for web forms where you want the user to fill in another entry after submission.
The server is delivering only part of the resource due to a range header sent by the client. The range header is used by...
The server is delivering only part of the resource due to a range header sent by the client. The range header is used by HTTP clients to enable resuming of interrupted downloads, or split a download into multiple simultaneous streams.
When you'll see this: Sent when the client requested a byte range (Range: bytes=0-1023). Used for video streaming, resumable file downloads, and pagination of large binary responses.
Related headers:Content-RangeAccept-RangesContent-Type
Laravel
// Laravel handles range requests automatically for file downloads
return response()->download($file)->withHeaders([
'Accept-Ranges' => 'bytes',
]);
Conveys information about multiple resources in situations where multiple status codes might be appropriate. Used in Web...
Conveys information about multiple resources in situations where multiple status codes might be appropriate. Used in WebDAV for operations that involve multiple resources.
When you'll see this: WebDAV responses where a single action affects multiple resources, each potentially having its own status. The body contains XML with individual status for each resource.
The server has fulfilled a request for the resource, and the response is a representation of the result of one or more i...
The server has fulfilled a request for the resource, and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
When you'll see this: Used with delta encoding (RFC 3229). The response contains a delta (diff) from a known base rather than the full resource. Reduces bandwidth for frequently-polled resources.
The request has more than one possible response. The user-agent or the user should choose one of them. There is no stand...
The request has more than one possible response. The user-agent or the user should choose one of them. There is no standardized way of choosing one of the responses, but HTML links to the possibilities are recommended.
When you'll see this: Content negotiation: the resource has multiple representations (different languages, formats). The server offers a list; the client chooses. Rarely used — most APIs return 200 with negotiated content instead.
The URL of the requested resource has been changed permanently. The new URL is given in the response. Search engines upd...
The URL of the requested resource has been changed permanently. The new URL is given in the response. Search engines update their links to the resource. Browsers cache this redirect indefinitely.
When you'll see this: Use when a resource has permanently moved to a new URL: old domain, renamed routes, restructured URLs. The Location header contains the new URL. Search engines pass PageRank through 301s.
Common Mistake
Browsers convert POST to GET on 301 redirects. Use 308 if you need to preserve the HTTP method (e.g., redirecting a POST endpoint permanently).
The URI of requested resource has been changed temporarily. New changes in the URI might be made in the future. Therefor...
The URI of requested resource has been changed temporarily. New changes in the URI might be made in the future. Therefore, this same URI should be used by the client in future requests.
When you'll see this: Temporary redirect. The client should continue using the original URL for future requests. Common use case: redirect to login page, feature flags redirecting to a different version.
Common Mistake
Most browsers convert POST→GET on a 302 redirect. Use 307 if you need to preserve the HTTP method on a temporary redirect.
Related headers:Location
Laravel
return redirect()->to('/temporary-url');
// Laravel's redirect() defaults to 302
The server sent this response to direct the client to get the requested resource at another URI with a GET request. This...
The server sent this response to direct the client to get the requested resource at another URI with a GET request. This is the correct redirect for POST/PUT/DELETE where the response is at a different URL.
When you'll see this: Post/Redirect/Get (PRG) pattern: after a successful form submission (POST), redirect to a result page. Prevents duplicate submissions on browser refresh.
Related headers:Location
Laravel
// After form submission:
return redirect()->route('success.page');
// Laravel uses 302 by default which also works for PRG
This is used for caching purposes. It tells the client that the response has not been modified, so the client can contin...
This is used for caching purposes. It tells the client that the response has not been modified, so the client can continue to use the same cached version of the response. No body is sent with this response.
When you'll see this: The client sent a conditional GET (If-None-Match with ETag, or If-Modified-Since). The resource has not changed, so the server tells the client to use its cached copy. Saves bandwidth.
Common Mistake
Never include a body with 304. The client will use its cached copy — any body you send is ignored and wastes bandwidth.
The server sends this response to direct the client to get the requested resource at another URI with same method that w...
The server sends this response to direct the client to get the requested resource at another URI with same method that was used in the prior request. The method is not allowed to be changed when reissuing the original request.
When you'll see this: Like 302 but the HTTP method is guaranteed to be preserved. Use when temporarily redirecting a POST or PUT endpoint and the client must re-send to the new URL with the same method.
This means that the resource is now permanently located at another URI, specified by the Location: HTTP Response header....
This means that the resource is now permanently located at another URI, specified by the Location: HTTP Response header. This has the same semantics as the 301 Moved Permanently HTTP response code, with the exception that the user agent must not change the HTTP method used.
When you'll see this: Permanent redirect that preserves the HTTP method. Use instead of 301 when the endpoint has moved but clients may be POSTing to it (e.g., webhook URLs that changed).
The server could not understand the request due to invalid syntax, missing required parameters, or malformed request bod...
The server could not understand the request due to invalid syntax, missing required parameters, or malformed request body. The client should not repeat the request without modifications.
When you'll see this: Return when the request is syntactically invalid: malformed JSON body, missing required fields, invalid data types, or invalid query parameters. Different from 422 (semantically invalid).
Common Mistake
Use 422 for validation errors (field values are invalid), 400 for structural errors (request format is wrong). Many APIs return 400 for everything — this reduces debuggability.
Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the cl...
Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. The WWW-Authenticate header contains information on how to authenticate.
When you'll see this: Return when the request lacks valid authentication credentials: missing token, expired session, or invalid API key. The client should authenticate and try again.
Common Mistake
401 means UNAUTHENTICATED (not logged in). Use 403 for UNAUTHORIZED (logged in but not permitted). This is one of the most commonly confused HTTP status codes.
Related headers:WWW-Authenticate
Laravel
// Laravel auth middleware returns 401 automatically
abort(401, 'Unauthenticated');
// or in Sanctum: response()->json(['message' => 'Unauthenticated.'], 401);
Reserved for future use. The original intention was that this code might be used as part of some form of digital cash or...
Reserved for future use. The original intention was that this code might be used as part of some form of digital cash or micropayment scheme. Some services use it to indicate quota exceeded or payment required to access a premium feature.
When you'll see this: Used by some APIs (Stripe, etc.) to indicate a payment or subscription is required. Not formally standardized for this purpose but widely adopted in API design.
The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give th...
The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server.
When you'll see this: Return when the user is authenticated but lacks permission for the requested action. Common for role-based access control (RBAC): user is logged in but tries to access an admin-only resource.
Common Mistake
If exposing the resource's existence is a security risk (e.g., admin-only resource), return 404 instead of 403 to avoid leaking information about what exists.
Related headers:Content-Type
Laravel
abort(403, 'This action is unauthorized.');
// Gates and Policies:
$this->authorize('update', $post);
// or: Gate::authorize('admin-access');
The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can...
The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. This is the most famous HTTP status code.
When you'll see this: Return when the requested URL does not match any resource. Also use when a specific resource (e.g., user #999) does not exist. Intentionally ambiguous — can hide 403 responses to prevent information leaking.
Related headers:Content-Type
Laravel
abort(404);
// Model not found:
$user = User::findOrFail($id); // auto-throws 404
// Custom: throw new ModelNotFoundException();
The request method is known by the server but is not supported by the target resource. For example, an API may not allow...
The request method is known by the server but is not supported by the target resource. For example, an API may not allow calling DELETE to remove a resource. The Allow header must be sent with the allowed methods.
When you'll see this: Return when the HTTP method is wrong for the endpoint: GET on a POST-only endpoint, DELETE on a read-only resource. Always include the Allow header listing valid methods.
This response is sent when the web server, after performing server-driven content negotiation, doesn't find any content...
This response is sent when the web server, after performing server-driven content negotiation, doesn't find any content that conforms to the criteria given by the user agent.
When you'll see this: The client sent an Accept header requesting a content type the server cannot provide (e.g., Accept: application/xml but server only supports JSON). Return with a list of available representations.
This response is sent on an idle connection by some servers, even without any previous request by the client. It means t...
This response is sent on an idle connection by some servers, even without any previous request by the client. It means that the server would like to shut down this unused connection.
When you'll see this: The server timed out waiting for the request. The client did not produce a request within the time the server was prepared to wait. Client should close and reopen the connection.
This response is sent when a request conflicts with the current state of the server. Most likely to occur in response to...
This response is sent when a request conflicts with the current state of the server. Most likely to occur in response to a PUT request, or when using optimistic locking.
When you'll see this: Return when the request cannot be completed due to a conflict with the current state of the resource: duplicate unique field, version mismatch in optimistic locking, concurrent modification.
This response is sent when the requested content has been permanently deleted from server, with no forwarding address. C...
This response is sent when the requested content has been permanently deleted from server, with no forwarding address. Clients are expected to remove their caches and links to the resource.
When you'll see this: Use instead of 404 when you know the resource existed but has been permanently removed. Better for SEO (tells search engines to deindex). Also good for deprovisioned API endpoints or deleted user accounts.
Related headers:Content-Type
Laravel
abort(410, 'Gone');
// or: return response()->json(['error' => 'This resource has been permanently removed'], 410);
The client has indicated preconditions in its headers which the server does not meet. Used with conditional requests (If...
The client has indicated preconditions in its headers which the server does not meet. Used with conditional requests (If-Match, If-None-Match, If-Modified-Since).
When you'll see this: Optimistic concurrency control: client sends If-Match with an ETag; if the resource has changed since the ETag was obtained, return 412. Prevents lost updates.
Request entity is larger than limits defined by server. The server might close the connection or return a Retry-After he...
Request entity is larger than limits defined by server. The server might close the connection or return a Retry-After header field. Previously known as "Request Entity Too Large".
When you'll see this: The request body exceeds the server's limit (e.g., file upload too large, JSON body too big). PHP's post_max_size and upload_max_filesize INI settings trigger this.
Related headers:Retry-AfterContent-Type
Laravel
// Laravel validation:
$request->validate(['file' => 'max:10240']); // 10MB
// Config: client_max_body_size in Nginx, upload_max_filesize in PHP
The media format of the requested data is not supported by the server, so the server is rejecting the request.
The media format of the requested data is not supported by the server, so the server is rejecting the request.
When you'll see this: The client sent a Content-Type the server cannot process: XML to a JSON-only endpoint, or text/plain where multipart/form-data is required. Return a list of supported media types.
Related headers:AcceptAccept-Post
Laravel
// Check Content-Type in middleware or controller:
if ($request->header('Content-Type') !== 'application/json') {
return response()->json(['error' => 'Unsupported Media Type'], 415);
}
The server refuses the attempt to brew coffee with a teapot. This error is a reference to the Hyper Text Coffee Pot Cont...
The server refuses the attempt to brew coffee with a teapot. This error is a reference to the Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) defined in RFC 2324, an April Fools' Day joke RFC published in 1998. Despite being a joke, it is widely implemented. Google returns 418 on google.com/teapot. Many frameworks include it as a named constant.
When you'll see this: Easter egg. Use it when you want to make developers smile. Some teams use it for "I know what you're asking but I'm choosing not to do it" — a more humorous 403. The HTCPCP protocol defined commands like BREW and WHEN for coffee pot control.
Related headers:Content-Type
Laravel
// Laravel includes it:
return response()->json(['message' => "I'm a teapot"], 418);
// or: abort(418, "I'm a teapot");
// Response::HTTP_I_AM_A_TEAPOT = 418
PHP
http_response_code(418);
echo json_encode(['message' => "I'm a teapot"]);
Used by Laravel when a CSRF token is missing or mismatched. This is a Laravel-specific extension — it is not defined in...
Used by Laravel when a CSRF token is missing or mismatched. This is a Laravel-specific extension — it is not defined in any RFC. The official HTTP spec has no status code 419.
When you'll see this: Thrown automatically by Laravel's VerifyCsrfToken middleware when the _token field is missing or doesn't match the session token. Common cause: form submission after session expires, or AJAX request without CSRF token.
Related headers:Content-Type
Laravel
// Thrown automatically by VerifyCsrfToken middleware
// For AJAX: ensure X-CSRF-TOKEN header is sent
// axios.defaults.headers.common['X-CSRF-TOKEN'] = token;
// To disable for specific routes: $except[] = 'api/*';
PHP
// Not a standard PHP/HTTP code. Laravel-specific only.
422📝 Unprocessable Content4xx
The request was well-formed (correct syntax) but was unable to be followed due to semantic errors. The server understand...
The request was well-formed (correct syntax) but was unable to be followed due to semantic errors. The server understands the Content-Type of the request entity and the syntax is correct, but it was unable to process the contained instructions.
When you'll see this: The default response for Laravel form validation failures. Use when the request is syntactically valid JSON but the data fails business rules: required fields missing, invalid email format, value out of range.
Common Mistake
Use 422 for semantic validation errors (values are invalid), not for structural errors (use 400). Laravel uses 422 by default for $request->validate() failures.
Indicates that the server is unwilling to risk processing a request that might be replayed, which can create replay atta...
Indicates that the server is unwilling to risk processing a request that might be replayed, which can create replay attack vulnerability in the context of TLS 1.3 0-RTT.
When you'll see this: TLS 1.3 0-RTT (Zero Round Trip Time) allows the client to send data before the handshake completes, but this data can be replayed by an attacker. Servers return 425 to reject 0-RTT requests for sensitive endpoints.
The server refuses to perform the request using the current protocol but will be willing to do so after the client upgra...
The server refuses to perform the request using the current protocol but will be willing to do so after the client upgrades to a different protocol.
When you'll see this: The server requires the client to switch protocols (e.g., from HTTP/1.1 to HTTP/2, or to TLS). The Upgrade header specifies the required protocol.
The origin server requires the request to be conditional. This response is intended to prevent the lost update problem,...
The origin server requires the request to be conditional. This response is intended to prevent the lost update problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict.
When you'll see this: The server requires conditional requests (If-Match) but the client did not send one. Forces clients to use optimistic concurrency to prevent lost updates.
The user has sent too many requests in a given amount of time ("rate limiting"). The Retry-After header provides guidanc...
The user has sent too many requests in a given amount of time ("rate limiting"). The Retry-After header provides guidance on when to try again.
When you'll see this: Rate limit exceeded. Return with Retry-After header indicating when the client can retry. Include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers for client guidance.
Related headers:Retry-AfterX-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
Laravel
// Built-in rate limiting via throttle middleware:
Route::middleware('throttle:60,1')->group(function () {
Route::post('/api/endpoint', ...);
});
// Returns 429 automatically when limit exceeded
The server is unwilling to process the request because its header fields are too large. The request may be resubmitted a...
The server is unwilling to process the request because its header fields are too large. The request may be resubmitted after reducing the size of the request header fields.
When you'll see this: Request headers are too large (e.g., cookies grown too large, custom headers exceeding Nginx limits). Common fix: clear cookies, or increase large_client_header_buffers in Nginx.
Laravel
return response()->json(['error' => 'Request Header Fields Too Large'], 431);
A non-standard Nginx status code. The server returns no response and closes the connection. Used to deter malicious clie...
A non-standard Nginx status code. The server returns no response and closes the connection. Used to deter malicious clients — bots, port scanners, and unauthorized access attempts receive a connection drop rather than an HTTP error.
When you'll see this: Nginx-specific. Configure in Nginx to silently drop requests from bad actors without wasting resources returning an HTTP response. Useful for blocking known malicious IPs or bots.
Laravel
// Not applicable — handled at Nginx level, not in PHP
PHP
// Nginx config: return 444;
451⚖️ Unavailable For Legal Reasons4xx
The user agent requested a resource that cannot legally be provided, such as a web page censored by a government or a pi...
The user agent requested a resource that cannot legally be provided, such as a web page censored by a government or a piece of content blocked by a DMCA takedown. The status code is a reference to the novel "Fahrenheit 451" by Ray Bradbury.
When you'll see this: Return when content is blocked due to legal requirements: GDPR compliance (blocking users in certain regions), DMCA takedowns, government-mandated censorship, or court orders.
Related headers:Link
Laravel
abort(451, 'Unavailable For Legal Reasons');
// Include Link header pointing to explanation:
return response()->json(['error' => 'Legal restriction'], 451)
->withHeaders(['Link' => '<https://example.com/legal>; rel="blocked-by"']);
A non-standard Nginx status code used when the client closes the connection while the server is still processing the req...
A non-standard Nginx status code used when the client closes the connection while the server is still processing the request. The server logs this as 499 to distinguish client-initiated disconnects from server errors.
When you'll see this: Nginx-specific log code. Appears when the user navigates away, closes the browser, or a timeout causes the client to disconnect before the server finishes. Useful for identifying slow endpoints causing user abandonment.
Laravel
// Not a PHP/Laravel concept — Nginx logs this automatically
PHP
// Nginx-internal only. Not returnable from PHP.
500💥 Internal Server Error5xx
The server has encountered a situation it does not know how to handle. This is a generic "catch-all" response for when t...
The server has encountered a situation it does not know how to handle. This is a generic "catch-all" response for when the server throws an unexpected exception. It is the most common server-side error and typically indicates a bug in the application code.
When you'll see this: Thrown automatically by Laravel when an unhandled exception occurs: uncaught exceptions, fatal PHP errors, database connection failures. Check Laravel logs (storage/logs/laravel.log) for the actual exception.
The request method is not supported by the server and cannot be handled. The only methods that servers are required to s...
The request method is not supported by the server and cannot be handled. The only methods that servers are required to support (and therefore that must not return this code) are GET and HEAD.
When you'll see this: The server does not recognize or support the HTTP method. Distinct from 405 (method not allowed for this resource) — 501 means the server literally does not implement the method at all.
This error response means that the server, while working as a gateway to get a response needed to handle the request, go...
This error response means that the server, while working as a gateway to get a response needed to handle the request, got an invalid response. Common when a reverse proxy (Nginx, Cloudflare) cannot reach the upstream PHP-FPM or application server.
When you'll see this: Nginx cannot reach PHP-FPM, PHP-FPM crashed, or an upstream API returned garbage. Check: is PHP-FPM running? Are there port conflicts? Did a deploy kill the old process before the new one started?
Related headers:Content-Type
Laravel
// Laravel itself doesn't return 502 — this comes from your reverse proxy
// Check: docker-compose logs php
// Check: sudo systemctl status php8.3-fpm
The server is not ready to handle the request. Common causes are a server that is down for maintenance or that is overlo...
The server is not ready to handle the request. Common causes are a server that is down for maintenance or that is overloaded. The Retry-After header indicates how long the service is expected to be unavailable.
When you'll see this: Return during planned maintenance, when the server is overloaded, or when a dependency (database, cache) is unavailable. Include Retry-After so clients know when to try again.
Related headers:Retry-AfterContent-Type
Laravel
// Enable maintenance mode:
php artisan down --retry=60
// Custom maintenance view: resources/views/errors/503.blade.php
// Secret bypass: php artisan down --secret=mytoken
This error response is given when the server is acting as a gateway and cannot get a response in time. Different from 40...
This error response is given when the server is acting as a gateway and cannot get a response in time. Different from 408 (client timeout) — 504 is a server-to-server timeout.
When you'll see this: Nginx waited for PHP-FPM (or an upstream API) too long. Common causes: slow database query, external API timeout, long-running script hitting PHP max_execution_time.
Related headers:Content-Type
Laravel
// Not returned by Laravel directly — comes from Nginx
// Increase: fastcgi_read_timeout in Nginx
// Increase: max_execution_time in php.ini
// Move slow work to queued jobs
The HTTP version used in the request is not supported by the server. The server should send a message describing why tha...
The HTTP version used in the request is not supported by the server. The server should send a message describing why that version is not supported and what other protocols are supported by that server.
When you'll see this: The client requested an HTTP version the server does not support (e.g., HTTP/3 on a server that only supports HTTP/1.1). Extremely rare in practice.
Related headers:Content-Type
Laravel
return response()->json(['error' => 'HTTP Version Not Supported'], 505);
The method could not be performed on the resource because the server is unable to store the representation needed to suc...
The method could not be performed on the resource because the server is unable to store the representation needed to successfully complete the request. This is a WebDAV response, but also used when a server runs out of disk space.
When you'll see this: Server disk is full and cannot save the uploaded file or complete a WebDAV operation. Monitor disk usage on production servers to catch this before users experience it.
The server detected an infinite loop while processing a request with "Depth: infinity". Used in WebDAV to indicate that...
The server detected an infinite loop while processing a request with "Depth: infinity". Used in WebDAV to indicate that the server encountered an infinite loop while processing a request.
When you'll see this: WebDAV only. Occurs when traversing a collection that creates a circular reference. Prevents infinite recursion from crashing the server.
Indicates that the client needs to authenticate to gain network access. This status is not generated by origin servers,...
Indicates that the client needs to authenticate to gain network access. This status is not generated by origin servers, but by intercepting proxies that control access to the network (captive portals).
When you'll see this: Hotel WiFi, airport networks, and corporate intranets use captive portals that intercept HTTP traffic and return 511 to redirect users to a login page. Not applicable to regular API servers.
Related headers:Content-Type
Laravel
// Not used in typical Laravel apps — captive portal use only
520☁️ Web Server Returned an Unknown Error5xxUnofficial
Cloudflare-specific. The origin web server returned an empty, unknown, or unexpected response to Cloudflare. Often cause...
Cloudflare-specific. The origin web server returned an empty, unknown, or unexpected response to Cloudflare. Often caused by the origin returning an HTTP response code that Cloudflare doesn't recognize, or an improperly formatted response.
When you'll see this: Check origin server logs for errors. Common causes: PHP fatal error with output buffering, malformed HTTP response headers, or mod_security blocking the response.
Cloudflare-specific. The origin web server refused the connection from Cloudflare. The origin server is either offline,...
Cloudflare-specific. The origin web server refused the connection from Cloudflare. The origin server is either offline, or blocking Cloudflare's IP addresses.
When you'll see this: Your origin server is not accepting connections on port 80/443. Check: is Nginx/Apache running? Is the firewall blocking Cloudflare IPs? Did the server go down?
Laravel
// Ensure Cloudflare IPs are whitelisted in your firewall\n// Check: systemctl status nginx
PHP
// Cloudflare-specific — not returnable from PHP
522⏱️ Connection Timed Out5xxUnofficial
Cloudflare-specific. Cloudflare was able to connect to the origin server but the connection timed out. The origin server...
Cloudflare-specific. Cloudflare was able to connect to the origin server but the connection timed out. The origin server did not respond within Cloudflare's 15-second timeout window.
When you'll see this: The origin server accepted the TCP connection but did not send an HTTP response in time. Usually indicates a very slow or hung application. Move long-running work to queued jobs.
Laravel
// Move slow operations to Laravel Queues:\nProcessReportJob::dispatch(\$data)->onQueue('reports');
PHP
// Cloudflare-specific — not returnable from PHP
523📡 Origin Is Unreachable5xxUnofficial
Cloudflare-specific. Cloudflare could not reach the origin server. This is typically a DNS failure or network routing is...
Cloudflare-specific. Cloudflare could not reach the origin server. This is typically a DNS failure or network routing issue between Cloudflare and your origin server.
When you'll see this: Check DNS records for your origin domain. Verify the origin IP in Cloudflare's DNS settings is correct and reachable. Check for network outages or firewall rules blocking Cloudflare.
Laravel
// Verify Cloudflare DNS settings point to the correct origin IP
PHP
// Cloudflare-specific — not returnable from PHP
524⏰ A Timeout Occurred5xxUnofficial
Cloudflare-specific. Cloudflare established a TCP connection to the origin server, but the origin server did not reply w...
Cloudflare-specific. Cloudflare established a TCP connection to the origin server, but the origin server did not reply with an HTTP response before the connection timed out (100 second Cloudflare timeout).
When you'll see this: Long-running requests (report generation, bulk imports) exceed Cloudflare's 100-second timeout. Use Laravel Queues for async processing and return 202 Accepted immediately.
Laravel
// Return 202 and queue the work:
GenerateReportJob::dispatch();
return response()->json(['message' => 'Report queued', 'poll_url' => route('report.status', $jobId)], 202);
PHP
// Cloudflare-specific — not returnable from PHP
525🔒 SSL Handshake Failed5xxUnofficial
Cloudflare-specific. Cloudflare could not negotiate an SSL/TLS handshake with the origin server. This indicates an SSL c...
Cloudflare-specific. Cloudflare could not negotiate an SSL/TLS handshake with the origin server. This indicates an SSL configuration mismatch between Cloudflare and your origin.
When you'll see this: Check: is SSL correctly installed on the origin? Is the SSL mode in Cloudflare set correctly (Full vs Full Strict)? Is the certificate expired or self-signed with Full Strict mode?
Laravel
// Ensure a valid SSL certificate on origin\n// Check Cloudflare SSL mode: Full (Strict) requires a valid cert
PHP
// Cloudflare-specific — not returnable from PHP
526🚨 Invalid SSL Certificate5xxUnofficial
Cloudflare-specific. Cloudflare could not validate the SSL certificate on the origin web server. Used in Full SSL (Stric...
Cloudflare-specific. Cloudflare could not validate the SSL certificate on the origin web server. Used in Full SSL (Strict) mode when the certificate is self-signed, expired, or uses a hostname that doesn't match.
When you'll see this: Install a valid, CA-signed SSL certificate on your origin (Let's Encrypt is free). Or switch Cloudflare SSL mode from "Full (Strict)" to "Full" to allow self-signed certificates.
Laravel
// Use Let's Encrypt: certbot --nginx -d example.com
// Or switch Cloudflare SSL mode to 'Full' instead of 'Full Strict'
PHP
// Cloudflare-specific — not returnable from PHP
No status codes match your search.
About This Reference
Covers all HTTP status codes defined in RFC 9110 plus widely-used unofficial codes (Cloudflare 52x, Nginx 444/499, Laravel 419, Twitter 420).
Use the search to jump to a specific code. Share a direct link by adding the code as a hash, e.g. /tool/http-status-codes#404.
Bạn gọi API và nhận về 403. Là lỗi gì? Sai token hay bị block hẳn? Còn 422 khác 400 ở chỗ nào? Và tại sao có khi redirect lại dùng 301, có khi lại 302? Nếu bạn đã từng phân vân với những câu hỏi đó — trang này là tài liệu tham khảo nhanh bạn cần bookmark lại ngay.
HTTP status code là gì?
HTTP Status Code là mã số 3 chữ số mà server trả về trong mỗi HTTP response để cho client biết kết quả của request. Mã này được chuẩn hoá bởi IETF (RFC 9110) và được dùng thống nhất trên toàn bộ internet — từ trình duyệt, API, CDN cho đến load balancer.
Cấu trúc của một HTTP response bao giờ cũng có status code ở dòng đầu tiên, ví dụ: HTTP/1.1 200 OK hay HTTP/2 404 Not Found. Client (trình duyệt, mobile app, script…) đọc mã này để quyết định xử lý response như thế nào tiếp theo.
Toàn bộ status code được chia thành 5 nhóm theo chữ số đầu tiên:
Nhóm
Phạm vi
Ý nghĩa chung
1xx
100–199
Informational — Request đang được xử lý, chờ thêm
2xx
200–299
Success — Request thành công
3xx
300–399
Redirection — Cần thêm hành động để hoàn tất
4xx
400–499
Client Error — Lỗi từ phía client
5xx
500–599
Server Error — Lỗi từ phía server
Nhóm 2xx — thành công
Đây là những gì bạn muốn thấy — server đã nhận, hiểu và xử lý thành công request.
Mã
Tên
Ý nghĩa & khi nào dùng
200
OK
Request thành công. Mã phổ biến nhất — dùng cho GET, PUT, PATCH trả về dữ liệu.
201
Created
Resource mới được tạo thành công. Dùng sau POST tạo mới dữ liệu — nên kèm header Location trỏ đến resource vừa tạo.
202
Accepted
Request được chấp nhận nhưng chưa xử lý xong (async). Dùng cho các tác vụ nền như gửi email, export file lớn.
204
No Content
Thành công nhưng không có body trả về. Dùng sau DELETE hoặc PUT/PATCH không cần trả dữ liệu.
206
Partial Content
Trả về một phần nội dung — dùng cho download từng chunk, video streaming với Range request.
Nhóm 3xx — redirect
Server yêu cầu client truy cập đến URL khác. Chọn sai mã redirect ảnh hưởng đến SEO và caching.
Mã
Tên
Ý nghĩa & khi nào dùng
301
Moved Permanently
URL cũ đã chuyển vĩnh viễn sang URL mới. Trình duyệt và Google sẽ cache và cập nhật index. Dùng khi migrate domain hoặc đổi cấu trúc URL.
302
Found (Moved Temporarily)
Chuyển tạm thời — client không nên cache. Dùng cho redirect sau khi login, A/B testing, maintenance.
304
Not Modified
Resource không thay đổi kể từ lần cache cuối. Client dùng bản cache đang có — tiết kiệm bandwidth. Cơ chế của ETag và Last-Modified.
307
Temporary Redirect
Giống 302 nhưng bắt buộc giữ nguyên HTTP method (POST redirect vẫn là POST). Dùng khi method quan trọng.
308
Permanent Redirect
Giống 301 nhưng giữ nguyên method. Dùng thay 301 khi cần đảm bảo POST không bị chuyển thành GET.
Nhóm 4xx — lỗi từ phía client
Client gửi request sai — sai URL, sai dữ liệu, thiếu quyền, hoặc request không được phép.
Mã
Tên
Ý nghĩa & khi nào dùng
400
Bad Request
Request sai cú pháp hoặc dữ liệu không hợp lệ — server không thể hiểu. Dùng khi thiếu field bắt buộc, sai kiểu dữ liệu ở mức parse.
401
Unauthorized
Chưa xác thực — cần đăng nhập hoặc cung cấp token hợp lệ. Tên gọi hơi misleading: thực ra là unauthenticated, không phải unauthorized.
403
Forbidden
Đã xác thực nhưng không có quyền truy cập resource này. Khác 401 ở chỗ: server biết bạn là ai, nhưng vẫn từ chối.
404
Not Found
Resource không tồn tại tại URL này. Mã nổi tiếng nhất internet. Cũng có thể dùng thay 403 khi muốn ẩn sự tồn tại của resource.
405
Method Not Allowed
HTTP method không được hỗ trợ — ví dụ gửi DELETE đến endpoint chỉ chấp nhận GET. Nên kèm header Allow liệt kê method hợp lệ.
408
Request Timeout
Client gửi request quá chậm, server hết kiên nhẫn ngắt kết nối.
409
Conflict
Request xung đột với trạng thái hiện tại của resource — ví dụ tạo user với email đã tồn tại, hoặc version conflict khi update đồng thời.
410
Gone
Resource đã tồn tại nhưng bị xóa vĩnh viễn — khác 404 ở chỗ khẳng định chắc chắn đã bị xóa, không phải chưa bao giờ tồn tại.
422
Unprocessable Entity
Request đúng cú pháp nhưng dữ liệu không hợp lệ về mặt logic — ví dụ email sai định dạng, số âm khi cần số dương. Phổ biến trong REST API validation.
429
Too Many Requests
Client gửi quá nhiều request trong thời gian ngắn — bị rate limiting. Nên kèm header Retry-After cho biết chờ bao lâu.
Nhóm 5xx — lỗi từ phía server
Request hợp lệ nhưng server gặp sự cố khi xử lý — đây là lỗi cần developer fix phía backend.
Mã
Tên
Ý nghĩa & khi nào dùng
500
Internal Server Error
Lỗi chung phía server — exception không được handle, bug trong code. Đây là mã bạn không bao giờ muốn thấy trên production.
501
Not Implemented
Server không hỗ trợ chức năng cần thiết để xử lý request — thường dùng cho tính năng chưa phát triển.
502
Bad Gateway
Server đóng vai proxy/gateway nhận response không hợp lệ từ upstream server. Thường gặp khi app server bị crash hoặc khởi động lại.
503
Service Unavailable
Server tạm thời không khả dụng — quá tải hoặc đang maintenance. Nên kèm header Retry-After.
504
Gateway Timeout
Proxy/gateway không nhận được response từ upstream trong thời gian cho phép. Khác 502: không phải response sai, mà là không có response.
Phân biệt các cặp dễ nhầm
Cặp dễ nhầm
Điểm khác biệt mấu chốt
400 vs 422
400: request sai cú pháp, server không parse được. 422: parse được nhưng dữ liệu sai logic (validation error).
401 vs 403
401: chưa đăng nhập (unauthenticated). 403: đã đăng nhập nhưng không có quyền (unauthorized).
404 vs 410
404: không tìm thấy (có thể chưa tồn tại hoặc đã xóa). 410: chắc chắn đã tồn tại và đã bị xóa vĩnh viễn.
301 vs 302
301: redirect vĩnh viễn — Google chuyển link juice, trình duyệt cache. 302: redirect tạm thời — không cache, Google giữ index trang gốc.
Hiểu đúng HTTP status code không chỉ giúp bạn debug nhanh hơn mà còn giúp thiết kế API chuẩn hơn — trả đúng mã cho đúng tình huống là một phần của good API design. Bookmark trang này để tra cứu nhanh mỗi khi cần.