Content negotiation - HTTP | MDN

archived 7 Apr 2017 09:02:41 UTC
Mozilla is working on a new program for developers and other web builders like you. Help shape that program by taking our 10 minute survey: https://goo.gl/forms/Ync2VuTWwAkQFvJx2
Your Search Results

    Content negotiation

    In HTTP, content negotiation is the mechanism that is used for serving different representations of a resource at the same URI, so that the user agent can specify which is best suited for the user (for example, which language of a document, which image format, or which content encoding).

    Principles of content negotiationEdit

    A specific document is called a resource. When a client wants to obtain it, it requests it using its URL. The server uses this URL to choose one of the variants it provides – each variant being called a representation – and returns this specific representation to the client. The overall resource, as well as each of the representations, have a specific URL. How a specific the representation is chosen when the resource is called is determined by content negotiation and there are several ways of negotiating between the client and the server.
    The determination of the best suited representation is made through one of two mechanisms:
    • Specific HTTP headers by the client (server-driven negotiation or proactive negotiation), which is the standard way of negotiating a specific kind of resource.
    • The 300 (Multiple Choices) or 406 (Not Acceptable) HTTP response codes by the server (agent-driven negotiation or reactive negotiation), that are used as fallback mechanisms.
    Over the years, other content negotiation proposals, like transparent content negotiation and the Alternates header, have been proposed. They failed to get traction and got abandoned.

    Server-driven content negotiationEdit

    In server-driven content negotiation, or proactive content negotiation, the browser (or any other kind of user-agent) sends several HTTP headers along with the URL. These headers describe the preferred choice of the user. The server uses them as hints and an internal algorithm chooses the best content to serve to the client. The algorithm is server-specific and not defined in the standard. See, for example, the Apache 2.2 negotiation algorithm.
    The HTTP/1.1 standard defines list of the standard headers that start server-driven negotiation (Accept, Accept-Charset, Accept-Encoding, Accept-Language). Though strictly speaking User-Agent is not in this list, it is sometimes also used to send a specific representation of the requested resource, though this is not considered as a good practice. The server uses the Vary header to indicate which headers it actually used for content negotiation (or more precisely the associated response headers), so that caches can work optimally.
    In addition to these, there is an experimental proposal to add more headers to the list of available headers, called client hints. Client hints advertise what kind of device the user agent runs on (for example,  if it is a desktop computer or a mobile device).
    Even if server-driven content negotiation is the most common way to agree on a specific representation of a resource, it has several drawbacks:
    • The server doesn't have total knowledge of the browser. Even with the Client Hints extension, it has not a complete knowledge of the capabilities of the browser. Unlike reactive content negotiation where the client makes the choice, the server choice is always somewhat arbitrary.
    • The information by the client is quite verbose (HTTP/2 header compression mitigates this problem) and a privacy risk (HTTP fingerprinting)
    • As several representations of a given resource are sent, shared caches are less efficient and server implementations are more complex.

    The Accept header

    The Accept header lists the MIME types of media resources that the agent is willing to process. It is comma-separated lists of MIME types, each combined with a quality factor, a parameter indicating the relative degree of preference between the different MIME types.
    The Accept header is defined by the browser, or any other user-agent, and can vary according to the context, like fetching an HTML page or an image, a video, or a script: It is different when fetching a document entered in the address bar or an element linked via an <img>, <video> or <audio> element. Browsers are free to use the value of the header that they think is the most adequate; an exhaustive list of default values for common browsers is available.

    The Accept-CH header 

    This is part of an experimental technology called Client Hints and currently implemented only in Chrome 46 and later
    The experimental Accept-CH lists configuration data that can be used by the server to select an appropriate response. Valid values are:
    Value Meaning
    DPR Indicates the client's device pixel ratio.
    Viewport-Width Indicates the layout viewport width in CSS pixels. 
    Width Indicates the resource width in physical pixels (in other words the intrinsic size of an image).

    The Accept-Charset header

    The Accept-Charset header indicates to the server what kinds of character encodings are understood by the user-agent. Traditionally, it was set to a different value for each locale for the browser, like ISO-8859-1,utf-8;q=0.7,*;q=0.7 for a Western European locale.
    With UTF-8 now being well-supported, being the preferred way of encoding characters, and to guarantee better privacy through less configuration-based entropy, most browsers omit the Accept-Charset header: Internet Explorer 8, Safari 5, Opera 11 and Firefox 10 have abandoned this header.

    The Accept-Encoding header

    The Accept-Encoding header defines the acceptable content-encoding (supported compressions). The value is a q-factor list (e.g.: br, gzip;q=0.8) that indicates the priority of the encoding values. The default value identity is at the lowest priority (unless otherwise declared).
    Compressing HTTP messages is one of the most important ways to improve the performance of a Web site, it shrinks the size of the data transmitted and makes better use of the available bandwidth; browsers always send this header and the server should be configured to abide to it and to use compression.

    The Accept-Language header

    The Accept-Language header is used to indicate the language preference of the user. It is a list of values with quality factors (like: "de, en;q=0.7"). A default value is often set according the language of the graphical interface of the user agent, but most browsers allow to set different language preferences.
    Due to the configuration-based entropy increase, a modified value can be used to fingerprint the user, it is not recommended to change it and a Web site cannot trust this value to reflect the actual wish of the user. Site designers must not be over-zealous by using language detection via this header as it can lead to a poor user experience:
    • They should always provide a way to overcome the server-chosen language, e.g., by providing a language menu on the site. Most user-agents provide a default value for the Accept-Language header, adapted to the user interface language and end users often do not modify it, either by not knowing how, or by not being able to do it, as in an Internet café for instance.
    • Once a user has overridden the server-chosen language, a site should no longer use language detection and should stick with the explicitly-chosen language. In other words, only entry pages of a site should select the proper language using this header.

    The User-Agent header

    Though there are legitimate uses of this header for selecting content, it is considered bad practice to rely on it to define what features are supported by the user agent.
    The User-Agent header identifies the browser sending the request. This string may contain a space-separated list of product tokens and comments.
    A product token is a name followed by a '/' and a version number, like Firefox/4.0.1. There may be as many of them as the user-agent wants. A comment is a free string delimited by parentheses. Obviously parentheses cannot be used in that string. The inner format of a comment is not defined by the standard, though several browser put several tokens in it, separated by ';'.

    The Vary response header

    In opposition to the previous Accept-* headers which are sent by the client, the Vary HTTP header is sent by the web server in its response. It indicates the list of headers used by the server during the server-driven content negotiation phase. The header is needed in order to inform the cache of the decision criteria so that can reproduce it, allowing the cache to be functional while preventing serving erroneous content to the user.
    The special value of '*' means that the server-driven content negotiation also uses information not conveyed in a header to choose the appropriate content.
    The Vary header was added in the version 1.1 of HTTP and is necessary in order to allow caches to work appropriately. A cache, in order to work with agent-driven content negotiation, needs to know which criteria was used by the server to select the transmitted content. That way, the cache can replay the algorithm and will be able to serve acceptable content directly, without more request to the server. Obviously, the wildcard '*' prevents caching from occurring, as the cache cannot know what element is behind it.

    Agent-driven negotiationEdit

    Server-driven negotiation suffers from a few downsides: it doesn't scale well. There is one header per feature used in the negotiation. If you want to use screen size, resolution or other dimensions, a new HTTP header must be created. Sending of the headers must be done on every request. This is not too problematic with few headers, but with the eventual multiplications of them, the message size would lead to a decrease in performance. The more precise headers are sent, the more entropy is sent, allowing for more HTTP fingerprinting and corresponding privacy concern.
    From the beginnings of HTTP, the protocol allowed another negotiation type: agent-driven negotiation or reactive negotiation. In this negotiation, when facing an ambiguous request, the server sends back a page containing links to the available alternative resources. The user is presented the resources and choose the one to use.
    Unfortunately, the HTTP standard does not specify the format of the page allowing to choose between the available resource, which prevents to easily automatize the process. Besides falling back to the server-driven negotiation, this method is almost always used in conjunction with scripting, especially with JavaScript redirection: after having checked for the negotiation criteria, the script performs the redirection. A second problem is that one more request is needed in order to fetch the real resource, slowing the availability of the resource to the user.

    Document Tags and Contributors

     Last updated by: fscholz,

    Thanks! Please check your inbox to confirm your subscription.

    If you haven’t previously confirmed a subscription to a Mozilla-related newsletter you may have to do so. Please check your inbox or your spam filter for an email from us.
    See also
    1. HTTP
    2. Guides:
    3. Resources and URIs
      1. Identifying resources on the Web
      2. Data URIs
      3. Introduction to MIME Types
      4. Complete list of MIME Types
      5. Choosing between www and non-www URLs
    4. Basics of HTTP
      1. Overview of HTTP
      2. Evolution of HTTP
      3. HTTP Messages
      4. A typical HTTP session
      5. Connection management in HTTP/1.x
    5. HTTP security
      1. Content Security Policy (CSP)
      2. HTTP Public Key Pinning (HPKP)
      3. HTTP Strict Transport Security (HSTS)
      4. Cookie security
      5. X-Content-Type-Options
      6. X-Frame-Options
      7. X-XSS-Protection
      8. Mozilla web security guidelines
      9. Mozilla Observatory
    6. HTTP access control (CORS)
    7. HTTP caching
    8. HTTP compression
    9. HTTP conditional requests
    10. HTTP content negotiation
    11. HTTP cookies
    12. HTTP range requests
    13. HTTP redirects
    14. HTTP specifications
    15. References:
    16. HTTP headers
      1. Accept
      2. Accept-Charset
      3. Accept-Encoding
      4. Accept-Language
      5. Accept-Ranges
      6. Access-Control-Allow-Credentials
      7. Access-Control-Allow-Headers
      8. Access-Control-Allow-Methods
      9. Access-Control-Allow-Origin
      10. Access-Control-Expose-Headers
      11. Access-Control-Max-Age
      12. Access-Control-Request-Headers
      13. Access-Control-Request-Method
      14. Age
      15. Cache-Control
      16. Connection
      17. Content-Disposition
      18. Content-Encoding
      19. Content-Language
      20. Content-Length
      21. Content-Location
      22. Content-Range
      23. Content-Security-Policy
      24. Content-Security-Policy-Report-Only
      25. Content-Type
      26. Cookie
      27. Cookie2
      28. DNT
      29. Date
      30. ETag
      31. Expires
      32. Forwarded
      33. From
      34. Host
      35. If-Match
      36. If-Modified-Since
      37. If-None-Match
      38. If-Range
      39. If-Unmodified-Since
      40. Keep-Alive
      41. Large-Allocation
      42. Last-Modified
      43. Location
      44. Origin
      45. Pragma
      46. Public-Key-Pins
      47. Public-Key-Pins-Report-Only
      48. Range
      49. Referer
      50. Referrer-Policy
      51. Retry-After
      52. Server
      53. Set-Cookie
      54. Set-Cookie2
      55. Strict-Transport-Security
      56. TE
      57. Tk
      58. Trailer
      59. Transfer-Encoding
      60. Upgrade-Insecure-Requests
      61. User-Agent
      62. Vary
      63. Via
      64. WWW-Authenticate
      65. Warning
      66. X-Content-Type-Options
      67. X-DNS-Prefetch-Control
      68. X-Forwarded-For
      69. X-Forwarded-Host
      70. X-Forwarded-Proto
      71. X-Frame-Options
      72. X-XSS-Protection
    17. HTTP request methods
      1. CONNECT
      2. GET
      3. HEAD
      4. OPTIONS
      5. POST
    18. HTTP response status codes
      1. 100 Continue
      2. 200 OK
      3. 201 Created
      4. 204 No Content
      5. 206 Partial Content
      6. 301 Moved Permanently
      7. 302 Found
      8. 303 See Other
      9. 304 Not Modified
      10. 307 Temporary Redirect
      11. 308 Permanent Redirect
      12. 404 Not Found
      13. 406 Not Acceptable
      14. 410 Gone
      15. 412 Precondition Failed
      16. 416 Range Not Satisfiable
      17. 451 Unavailable For Legal Reasons
      18. 500 Internal Server Error
      19. 501 Not Implemented
      20. 502 Bad Gateway
      21. 503 Service Unavailable
      22. 504 Gateway Timeout
    19. CSP directives
      1. CSP: base-uri
      2. CSP: block-all-mixed-content
      3. CSP: child-src
      4. CSP: connect-src
      5. CSP: default-src
      6. CSP: font-src
      7. CSP: form-action
      8. CSP: frame-ancestors
      9. CSP: frame-src
      10. CSP: img-src
      11. CSP: manifest-src
      12. CSP: media-src
      13. CSP: object-src
      14. CSP: plugin-types
      15. CSP: referrer
      16. CSP: report-uri
      17. CSP: require-sri-for
      18. CSP: sandbox
      19. CSP: script-src
      20. CSP: style-src
      21. CSP: upgrade-insecure-requests
      22. CSP: worker-src
    0%
    10%
    20%
    30%
    40%
    50%
    60%
    70%
    80%
    90%
    100%