HTTP Status Codes Reference
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.
response('', 100);http_response_code(100);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.
UpgradeConnection// WebSocket upgrade handled by Laravel Reverb or Pusher
response('', 101)->withHeaders(['Upgrade' => 'websocket', 'Connection' => 'Upgrade']);http_response_code(101);
header('Upgrade: websocket');
header('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.
response('', 102);http_response_code(102);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.
Linkresponse('', 103)->withHeaders(['Link' => '</style.css>; rel=preload; as=style']);http_response_code(103);
header('Link: </style.css>; rel=preload; as=style');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.
Content-TypeContent-Lengthreturn response()->json($data);
// or return response()->json($data, 200);http_response_code(200);
// HTTP 200 is the default, so often not needed explicitly
// Response::HTTP_OK constant = 200The 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.
LocationContent-Typereturn response()->json($resource, 201);
// With Location header:
return response()->json($resource, 201)
->withHeaders(['Location' => route('resource.show', $resource)]);http_response_code(201);
header('Location: /api/resources/' . $newId);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.
Content-Type// Dispatch a job and return 202
ProcessOrderJob::dispatch($order);
return response()->json(['message' => 'Processing', 'job_id' => $jobId], 202);http_response_code(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.
Content-Typereturn response()->json($transformedData, 203);http_response_code(203);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.
return response()->noContent();
// or: return response('', 204);http_response_code(204);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.
return response('', 205);http_response_code(205);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.
Content-RangeAccept-RangesContent-Type// Laravel handles range requests automatically for file downloads
return response()->download($file)->withHeaders([
'Accept-Ranges' => 'bytes',
]);http_response_code(206);
header('Content-Range: bytes 0-1023/2048');
header('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.
Content-Typereturn response()->json(['results' => $multipleStatuses], 207);http_response_code(207);
header('Content-Type: application/xml; charset=utf-8');Used inside a DAV: propstat response element to avoid enumerating the internal members of multiple bindings to the same...
Used inside a DAV: propstat response element to avoid enumerating the internal members of multiple bindings to the same collection repeatedly.
When you'll see this: WebDAV only. Avoids infinite loops when reporting on collections that contain themselves through bindings.
return response('', 208);http_response_code(208);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.
IMDelta-Basereturn response($deltaContent, 226);http_response_code(226);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.
LocationContent-Typereturn response()->json(['options' => $options], 300);http_response_code(300);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.
Locationreturn redirect()->to('/new-url', 301);
// or: return redirect()->route('new.route', [], 301);http_response_code(301);
header('Location: https://example.com/new-url');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.
Locationreturn redirect()->to('/temporary-url');
// Laravel's redirect() defaults to 302http_response_code(302);
header('Location: https://example.com/temporary-url');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.
Location// After form submission:
return redirect()->route('success.page');
// Laravel uses 302 by default which also works for PRGhttp_response_code(303);
header('Location: /success');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.
ETagCache-ControlLast-Modified// Laravel handles ETags automatically with Response macros
return response($content)->setEtag(md5($content))->isNotModified($request)
? response(null, 304)
: response($content);http_response_code(304);
header('ETag: "abc123"');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.
Locationreturn redirect()->to('/new-url', 307);http_response_code(307);
header('Location: https://example.com/new-url');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).
Locationreturn redirect()->to('/new-url', 308);http_response_code(308);
header('Location: https://example.com/new-url');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).
Content-Typeabort(400, 'Bad Request');
// or: return response()->json(['error' => 'Invalid request format'], 400);http_response_code(400);
echo json_encode(['error' => 'Bad Request']);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.
WWW-Authenticate// Laravel auth middleware returns 401 automatically
abort(401, 'Unauthenticated');
// or in Sanctum: response()->json(['message' => 'Unauthenticated.'], 401);http_response_code(401);
header('WWW-Authenticate: Bearer realm="API"');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.
Content-Typeabort(402, 'Payment Required');
// or: return response()->json(['error' => 'Subscription required'], 402);http_response_code(402);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.
Content-Typeabort(403, 'This action is unauthorized.');
// Gates and Policies:
$this->authorize('update', $post);
// or: Gate::authorize('admin-access');http_response_code(403);
echo json_encode(['error' => 'Forbidden']);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.
Content-Typeabort(404);
// Model not found:
$user = User::findOrFail($id); // auto-throws 404
// Custom: throw new ModelNotFoundException();http_response_code(404);
echo json_encode(['error' => 'Not Found']);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.
Allow// Laravel returns 405 automatically for incorrect methods
// Manual: return response()->json(['error' => 'Method Not Allowed'], 405)
// ->withHeaders(['Allow' => 'GET, POST']);http_response_code(405);
header('Allow: GET, POST');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.
Content-Typereturn response()->json(['error' => 'Not Acceptable', 'supported' => ['application/json']], 406);http_response_code(406);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.
Connectionreturn response()->json(['error' => 'Request Timeout'], 408);http_response_code(408);
header('Connection: close');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.
Content-Typereturn response()->json(['error' => 'Conflict', 'message' => 'Email already exists'], 409);http_response_code(409);
echo json_encode(['error' => 'Conflict']);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.
Content-Typeabort(410, 'Gone');
// or: return response()->json(['error' => 'This resource has been permanently removed'], 410);http_response_code(410);Server rejected the request because the Content-Length header field is not defined and the server requires it.
Server rejected the request because the Content-Length header field is not defined and the server requires it.
When you'll see this: The server requires a Content-Length header in the request. The client must add it and retry.
Content-Lengthreturn response()->json(['error' => 'Content-Length header required'], 411);http_response_code(411);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.
ETagIf-Matchif ($request->header('If-Match') !== $resource->etag) {
return response()->json(['error' => 'Precondition Failed'], 412);
}http_response_code(412);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.
Retry-AfterContent-Type// Laravel validation:
$request->validate(['file' => 'max:10240']); // 10MB
// Config: client_max_body_size in Nginx, upload_max_filesize in PHPhttp_response_code(413);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.
AcceptAccept-Post// Check Content-Type in middleware or controller:
if ($request->header('Content-Type') !== 'application/json') {
return response()->json(['error' => 'Unsupported Media Type'], 415);
}http_response_code(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.
Content-Type// 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 = 418http_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.
Content-Type// 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/*';// Not a standard PHP/HTTP code. Laravel-specific only.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.
Content-Type// Laravel validation returns 422 automatically:
$request->validate([
'email' => 'required|email',
'name' => 'required|max:255',
]);
// JSON response: {"message": "...", "errors": {"email": ["..."]}}http_response_code(422);
echo json_encode(['errors' => ['email' => ['The email field is required.']]]);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.
return response()->json(['error' => 'Too Early'], 425);http_response_code(425);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.
UpgradeConnectionreturn response()->json(['error' => 'Upgrade Required'], 426)
->withHeaders(['Upgrade' => 'TLS/1.3', 'Connection' => 'Upgrade']);http_response_code(426);
header('Upgrade: TLS/1.3, HTTP/2');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.
Content-Typeif (!$request->hasHeader('If-Match')) {
return response()->json(['error' => 'If-Match header required'], 428);
}http_response_code(428);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.
Retry-AfterX-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset// Built-in rate limiting via throttle middleware:
Route::middleware('throttle:60,1')->group(function () {
Route::post('/api/endpoint', ...);
});
// Returns 429 automatically when limit exceededhttp_response_code(429);
header('Retry-After: 60');
header('X-RateLimit-Limit: 100');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.
return response()->json(['error' => 'Request Header Fields Too Large'], 431);http_response_code(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.
// Not applicable — handled at Nginx level, not in PHP// Nginx config: return 444;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.
Linkabort(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"']);http_response_code(451);
header('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.
// Not a PHP/Laravel concept — Nginx logs this automatically// Nginx-internal only. Not returnable from PHP.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.
Content-Type// Triggered automatically for uncaught exceptions
// Custom 500 view: resources/views/errors/500.blade.php
// Handler: app/Exceptions/Handler.php
// Debug mode: APP_DEBUG=true shows exception detailshttp_response_code(500);
echo json_encode(['error' => 'Internal Server Error']);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.
return response()->json(['error' => 'Not Implemented'], 501);http_response_code(501);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?
Content-Type// Laravel itself doesn't return 502 — this comes from your reverse proxy
// Check: docker-compose logs php
// Check: sudo systemctl status php8.3-fpm// Returned by Nginx/proxy, not PHPThe 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.
Retry-AfterContent-Type// Enable maintenance mode:
php artisan down --retry=60
// Custom maintenance view: resources/views/errors/503.blade.php
// Secret bypass: php artisan down --secret=mytokenhttp_response_code(503);
header('Retry-After: 3600');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.
Content-Type// 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// Returned by reverse proxy (Nginx), not PHPThe 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.
Content-Typereturn response()->json(['error' => 'HTTP Version Not Supported'], 505);http_response_code(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.
return response()->json(['error' => 'Insufficient Storage'], 507);http_response_code(507);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.
return response()->json(['error' => 'Loop Detected'], 508);http_response_code(508);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.
Content-Type// Not used in typical Laravel apps — captive portal use onlyhttp_response_code(511);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.
// Check Laravel logs: storage/logs/laravel.log\n// Check PHP-FPM logs for fatal errors// Cloudflare-specific — not returnable from PHPCloudflare-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?
// Ensure Cloudflare IPs are whitelisted in your firewall\n// Check: systemctl status nginx// Cloudflare-specific — not returnable from PHPCloudflare-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.
// Move slow operations to Laravel Queues:\nProcessReportJob::dispatch(\$data)->onQueue('reports');// Cloudflare-specific — not returnable from PHPCloudflare-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.
// Verify Cloudflare DNS settings point to the correct origin IP// Cloudflare-specific — not returnable from PHPCloudflare-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.
// Return 202 and queue the work:
GenerateReportJob::dispatch();
return response()->json(['message' => 'Report queued', 'poll_url' => route('report.status', $jobId)], 202);// Cloudflare-specific — not returnable from PHPCloudflare-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?
// Ensure a valid SSL certificate on origin\n// Check Cloudflare SSL mode: Full (Strict) requires a valid cert// Cloudflare-specific — not returnable from PHPCloudflare-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.
// Use Let's Encrypt: certbot --nginx -d example.com
// Or switch Cloudflare SSL mode to 'Full' instead of 'Full Strict'// Cloudflare-specific — not returnable from PHPCovers 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.