{ }HttpStatus.com

300 Multiple Choices

The requested resource has several representations, and the server cannot pick one automatically.

Defined in RFC 9110 §15.4.1

What 300 means

A 300 response tells the client that the target resource has more than one representation, each with its own more specific identifier, and that content negotiation could not settle on a single one automatically. The server is expected to return a list of the available representations, along with the location information for each, so the user (or the user agent) can pick one. If the server has a preferred representation, it can point to it with a Location header, and RFC 9110 also allows a machine-readable Link header field carrying the same choices.

In practice this status code is one of the least implemented in the entire HTTP specification. Most servers that face an ambiguous request resolve it internally, either by picking a default representation via server-driven negotiation or by redirecting to a canonical URL with a 302 or 303 instead of exposing the ambiguity to the client. 300 shows up mostly in academic examples, API design exercises, and a handful of file-format or localization endpoints that genuinely offer multiple equally valid representations, such as a document available as PDF, HTML, and plain text with no default.

Because there is no browser-native handling for 300 (unlike 301/302, which browsers follow automatically), a user hitting this status in a plain browser navigation typically sees a raw, unstyled body unless the server crafts an HTML page with links. This makes 300 mostly useful for machine-to-machine APIs where the client is expected to parse the response body or Link headers programmatically and choose the best match itself, for example by content type or language.

Common causes

  • A URL maps to a resource that exists in multiple formats (JSON, XML, PDF) with no default representation configured.
  • Content negotiation via the Accept header is ambiguous and the server has no fallback rule.
  • A localized resource is requested without an Accept-Language header and multiple translations are equally valid.
  • A custom API deliberately exposes version or format choices to the caller instead of picking one.
  • Static site generators or file servers list multiple index files (index.html, index.json) without a priority order.

How to fix a 300

If you are the client (browser user or API caller)

  • Send an explicit Accept header (and Accept-Language, if relevant) so the server can negotiate a single representation instead of listing choices.
  • Parse the response body or Link header for the list of alternatives and follow the one that matches your needs.
  • If you control the request, hit the more specific URL for the representation you want instead of the ambiguous one.
  • Cache the choice you make so repeat requests can go straight to the specific representation and skip the 300 round trip.

If you run the server

  • Prefer transparent content negotiation (return the best match directly, often with a Vary header) over surfacing 300 to callers.
  • If 300 is genuinely useful, set a Location header to the server-preferred choice so simple clients still get a usable destination.
  • Return a small HTML or JSON body listing every alternative with its absolute URL so machine clients can parse it reliably.
  • Document the negotiation dimensions (format, language, version) clearly so API consumers can avoid triggering the ambiguity.

Example

GET /report HTTP/1.1
Host: api.example.com
Accept: */*

HTTP/1.1 300 Multiple Choices
Content-Type: application/json
Location: https://api.example.com/report.pdf

{
  "message": "Multiple representations available",
  "choices": [
    { "type": "application/pdf", "href": "/report.pdf" },
    { "type": "text/html", "href": "/report.html" },
    { "type": "text/plain", "href": "/report.txt" }
  ]
}
A server exposing format choices instead of negotiating one automatically.

Try it live

Our free status responder returns a real HTTP 300 you can point tests, monitors or a browser at.

GET https://mcp.httpstatus.com/status/300

Related status codes

Tools for debugging this