HTTP 300 Multiple Choices

Multiple Choices

HTTP 300 is Multiple Choices: the target has several representations, each with its own URL, and the server wants the user or user agent to choose one (RFC 9110 section 15.4.1). That’s reactive negotiation, the reverse of the usual proactive kind, where the server picks from the request’s Accept headers. The body should list the choices, and a server with a favorite should name it in Location.

The exchange

GET /docs/manual HTTP/1.1
Host: example.com

HTTP/1.1 300 Multiple Choices
Location: https://example.com/docs/manual.en.html
Content-Type: text/html

<ul>
  <li><a href="/docs/manual.en.html">English</a></li>
  <li><a href="/docs/manual.de.html">Deutsch</a></li>
</ul>

Browsers don’t follow it

RFC 9110 lets a user agent follow a 300’s Location and leaves the format of the list undefined. Chrome and Firefox treat it as a page, not a redirect: the visitor sees the body, and the Location is ignored. The Fetch standard’s redirect statuses are 301, 302, 303, 307 and 308, so fetch() hands your code the 300 itself. curl -L, on the other hand, follows any 3xx that carries a Location.

RFC 9110 also tells a client to treat a 3xx code it doesn’t recognize as a 300, which is why a client older than 308 may stop at a 308 instead of following it.

Who sends it

  • Apache’s mod_negotiation (MultiViews or type maps) answers 300 when several variants are equally acceptable, unless ForceLanguagePriority Prefer lets it pick one. When no variant is acceptable it sends 406, unless ForceLanguagePriority Fallback is set.
  • Apache’s mod_speling answers a misspelled URL with a 300 and a list when more than one file is a close match; a single close match gets a 301.

Caching

A 300 is heuristically cacheable: with no Cache-Control or Expires, a cache may store it and reuse it. If the list of choices can change, send explicit freshness.

What to send instead

the server can choose from Accept-Language or Accept     200, with Vary on that header
one variant is the right answer for this visitor          302 to it
the content moved for good                                301 or 308

When the choice depends on request headers, send Vary: Accept-Language (or whichever header you used) so caches keep the variants apart. RFC 9110 also mentions a Link header with rel="alternate" for listing alternatives, and calls its deployment a chicken-and-egg problem. For search engines, mark language versions with hreflang alternate links instead.

Search 300 308 in the tool below to compare the two.

Try it in the HTTP Status Codes

300 Multiple Choices

  1. 300Multiple Choices3xx Redirection

    The target has several representations and the server is leaving the choice to the client, often listing them in the body.

    When to use it

    Content negotiation where the alternatives are genuinely different resources, not one canonical URL.

    Common mistakes

    Reaching for it where a 301 or a 302 would do: Chrome and Firefox do not follow its Location header, so visitors stay on the 300’s own page, and no standard says how its list of choices is written.

    Cacheable by defaultRFC 9110

Every code, by class

Codes marked unofficial come from one server’s own convention — nginx, Cloudflare, cPanel, Microsoft — and are not in the IANA registry.

Runs in your browser. Nothing you enter is sent anywhere.