300 Multiple Choices
When more than one representation exists for a requested resource, the server responds with 300 Multiple Choices. The client is responsible for selecting the option best fitting its requirements.
The response is cacheable by default. To override this behavior, include appropriate Cache-Control headers.
Usage
300 Multiple Choices exists for reactive negotiation: the server hands the client a list of available representations, and the client picks the one fitting its needs, the counterpart to the proactive Content-Negotiation the Accept family drives. The 300 response invites the client to redirect its request to one of the listed identifiers.
When the 300 Multiple Choices status code is received, the message body contents differ depending on the request method. A HEAD request includes no message body. For other methods, the body contains a list from which the client selects the most appropriate response.
For non-HEAD responses, the body contains
the list of available choices. The specification
mentions the Link
header with rel="alternate" as a possible way to
list the options, while noting deployment never
took hold. If a default response exists
or the server has a preferred choice, the
Location header identifies this
preference.
Example
The client requests a resource and the server offers multiple options. The headers include paths to each resource. Because this follows a GET request, the body provides a clickable list of options.
Request
GET /tech-news HTTP/1.1
Host: www.example.re
Response
HTTP/1.1 300 Multiple Choices
Link: </leading/news.html>; rel="alternate"
Link: </bleeding/news.html>; rel="alternate"
Location: /leading/news.html
Content-Type: text/html
Content-Length: 154
<h2>Choose from one of the following</h2>
<ul>
<li><a href=/leading/news.html>Leading edge</a>
<li><a href=/bleeding/news.html>Bleeding edge</a>
</ul>
Why 300 stayed rare
The specification never defines a format for the list of choices. HTTP stays deliberately orthogonal to the content it carries, so a client wanting to select automatically has no standard structure to parse, and automatic selection is exactly what would have made 300 useful. Each server invents a body format, each client would need to understand each format, and the loop never closed.
The history reinforces the point. Early proposals
defined dedicated URI and Alternates header fields
for carrying the list, and both were dropped for
lack of deployment and disagreement over syntax.
The Link header with rel="alternate"
remains the closest available convention, with the
specification itself calling the deployment
situation a chicken-and-egg problem.
Code references
.NET
HttpStatusCode.MultipleChoices
Rust
http::StatusCode::MULTIPLE_CHOICES
Rails
:multiple_choices
Go
http.StatusMultipleChoices
Symfony
Response::HTTP_MULTIPLE_CHOICES
Python3.5+
http.HTTPStatus.MULTIPLE_CHOICES
Java
java.net.HttpURLConnection.HTTP_MULT_CHOICE
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_MULTIPLE_CHOICES
Angular
@angular/common/http/HttpStatusCode.MultipleChoices