The purpose of the Accept header from the client is to tell the server what kind of data it will accept as a response to its request. We can set this header in asynchronous HTTP calls in Javascript, but not in HTML.

For example, consider a link such as <a href="/some/resource">Get as CSV</a>. If an attribute like accept="text/csv" were allowed, and the browser interpreted that to send an Accept: text/csv header with that request, the server could respond to the semantics of the request. Without it, we might create a link such as <a href="/some/resource?format=csv">Get as CSV</a>, and the server must respond to the arbitrary query string parameter instead.

What are the reasons, both technical and historical, behind the HTML\DOM specification not allowing the setting of an Accept header through markup?

  • 2
    Web is a legacy platform hindered by a fear of change and a slow standards committee: wtfhtmlcss.com wtfjs.com
    – Den
    Jul 29 '14 at 9:08

Because the headers are not part of the URL. The URL should identify the resource, on it's own, and should do it uniquely. The Accept (and the more useful Accept-Encoding) headers should not affect semantics of the request. They should indicate capabilities of the client so the server can format the response accordingly.

If you do a HTTP call from JavaScript, your JavaScript code is the client and so it gets to set headers. But for HTML link the browser is the client and therefore it gets to choose.

If you want to provide CSV to a user, the linked resource should generally be in a fixed format. Imagine the user does

Copy Link Address

$ wget PasteEnter

That's a legitimate thing for them to do for various reasons. And because the link promised them CSV, that's what they'll expect. But the wget won't get any other attribute of the link. Only the URL. So the information should be encoded in the URL.

In fact there are not many uses for Accept header, because most resources just have their format and don't make much sense in another. The Accept-Encoding is useful; if the client says Accept-Encoding: gzip,deflate it means the client can do transparent decompression. But about the only use I could think of for Accept is image and video formats e.g. to provide alternate for browsers that don't support say image/svg+xml or video/webm. Except browsers don't seem to actually advertise which media formats they support, so it does not work. And HTML chose to implement different, slightly more flexible mechanism anyway. And few other kinds of data have several widely implemented alternate formats to choose from.

  • Plus, with audio and video there are the audio and video tags. So that problem is now (hopefully) mitigated to the point of being fixed. Well, for HTML5-compatible browsers. Jul 29 '14 at 14:39
  • @ParthianShot: True. I don't do web apps, so I didn't remember how it works. It is apparently more suitable to provide the client a list to choose from (which is usually short) than having the client list all the things it supports.
    – Jan Hudec
    Jul 29 '14 at 18:16
  • The URL should identify the resource this is exactly why I wanted to add parameters as header that are useful for tracking user stuff, like where he was when he clicked, or if he was previously redirected from somewhere, is there then a better way to do this? Aug 19 '19 at 21:19
  • "That's a legitimate thing for them to do ". Who says it has to work? It doesn't work with POST requests, for instance.
    – Florian F
    Jul 2 at 7:27
  • @FlorianF it does work with post requests as long as the user knows what they want to post.
    – Jan Hudec
    Jul 2 at 7:41

Because the Accept: header is intended to indicate what types of documents the user's browser is able to handle correctly, and this is not information that you, as the author of the web page, have.

Specifically, the reason the HTTP protocol provides an Accept: header is to allow selecting an appropriate file type when the same document is available in more than one form. Let's suppose I am linking to an image, for instance; my browser may be able to display JPEG, or Tiff images, but might not have the capability to display a RAW image. The browser would indicate this by sending the following headers with an image request:

Accept: image/jpeg,image/tiff

Now, if the server is able to serve a given image as RAW or as TIFF, it would respond with a TIFF version of the image (and set the Content-Type: header to indicate the type it chose).

What would it mean for the author of the web page to override the choices the browser sends? If I were to add a hypothetical accept="image/raw" attribute, the browser would still not be able to display a raw image -- but the server would send it.

  • Bingo. The app can't decide what MIME types the browser accepts.
    – svidgen
    Jul 29 '14 at 15:15

A URI is intended to identify a resource.

Resource refers to the actual thing being retrieved. On a web site, that's typically a page. In a REST API, it would normally be an entity - person, profile, widget, photo, etc.

HTTP headers tell the server things about the client - they don't describe anything about the resource itself, or provide any help in locating that resource.

For example:

  • Accept-Encoding tells the server that the client knows how to convert or decompress certain content.
  • Accept-Language tells the server that the client is in a certain locale and prefers content in that locale.
  • Authorization tells the server that the client thinks it is authorized to access a protected resource.

A common theme with the majority of these request headers is that the server is not obligated to honor them. An Accept-Encoding of gzip does not guarantee that the response will be compressed. An Accept-Language of ur-PK is likely to be ignored when hitting a U.S. site, unless they specifically support Urdu. And the server reserves the right to verify the Authorization header and return a 401 or 403 anyway, if it doesn't like what it sees.

None of these headers are intended to materially change anything about which resource the server provides in response. The Accept header is no different. If a client specifies application/xml and the server only supports application/json, then the server is going to send back JSON - not XML. More importantly, the Accept header can specify multiple types, in which case the server is free to return whichever it prefers (or none of them). As you might imagine, this could easily lead to undefined behavior for the user, but let's ignore that for the moment.

The intent of a hyperlink is to link to a page - page being a certain type of resource. Or, you might be justified in the looser definition of simply linking to a resource, even if that resource is something other than a page (perhaps an image, or a data set). What it is definitely not meant to do, however, is link to a specific representation of a resource. That is for the client and server to negotiate, and the server to ultimately decide.

Accept-Language is an obvious example of why it might be problematic to allow hyperlinks to control headers. It doesn't really make sense, if you think about it. Each user controls his or her own language preference; it's configured in the operating system and/or the browser. The browser should always send the same Accept-Language header, regardless of which page is being visited. If the server supports that language, great; if not, then it will respond with whatever language it thinks is closest.

If this could be changed by hyperlinks, then inbound links could essentially force you into the Chinese-language version of the site, even when your browser and operating system aren't configured to support that language. That makes no sense. If the site supports English, and your browser is English, then it should respond in English, no matter what the hyperlink says.

Likewise, if your browser knows how to display XML as structured data, and can look for XSLs to make it look pretty, but doesn't really know what to do with JSON other than dump it out as plain text, then forcing them to the JSON content by way of a link (if such a thing were possible) is an aggressively user-hostile behaviour. The browser should always be the one to say, "I know how to display X, but not Y, so I would really prefer if you gave me X".

I can understand why you might think it's logical to allow the user of a browser to override this decision. But the truth of the matter is that you're thinking of a few tiny edge cases like downloading a report; 99% of the time, when this choice exists, the user is not qualified or does not have sufficient information to make it.

To put it slightly differently, imagine your parents or grandparents going to download a file and being asked to choose text/csv or text/plain. Are they likely to know the difference? I don't know about yours, but mine often can't even spot the difference between a banner ad and an error message, so there's no way they'd be able to make this choice intelligently. On the other hand, there might be a glimmer of hope if they're given separate links to download an "Excel workbook" or "Text only" - which to them are actually separate resources, not just different representation of the same resource, and the URIs should reflect that.

The user can't be relied upon to understand that these two things are actually the same resource, but different representation. And without changing everything about the way the web works today, we can't assume anything about what they will do with that hyperlink. They might click, or they might right-click -> "save as", or they might copy-and-paste it into their address bar, or they might be using a download manager, or they might still be using IE6, or they might be using some off-brand tablet or mobile device with a proprietary browser... and in many of these cases, they're not going to get the content they want, because either they'll lose the part of the hyperlink that declares the content-type, or their browser won't support it.

Could the HTML spec have been designed 40 years ago to support a content-type attribute in hyperlinks? Maybe, although as I've described in the first several paragraphs, there were strong reasons against it, especially during a time when bandwidth and server resources were scarce and the idea of being able to download the same report in multiple formats (or, frankly, downloading any report at all) honestly hadn't occurred to anyone. But certainly in today's world it would be insane to try adding something like that to the spec; it would completely break backward compatibility and lead to the dreaded "undefined behaviour" in every existing browser.

  • If a client specifies application/xml and the server only supports application/json, then the server is going to send back JSON - not XML. Then, what is 406 HTTP error for ? To quote rfc2616 : If an Accept header field is present, and if the server cannot send a response which is acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response. Feb 2 '17 at 19:41
  • What it is definitely not meant to do, however, is link to a specific representation of a resource. That is for the client and server to negotiate, and the server to ultimately decide. → And what if the application designer wants to take part to the negotiation ? Is there any reference where it is asserted that the user agent i.e. client must be and only is the web browser ? I would be glad if you could help me understand this. Feb 2 '17 at 19:49

The primary answer is that a link in a web page is intended to be rendered as a web page. If the web server returns some type other than a renderable page (image, downloaded file, etc), then the content might be rendered by the browser or not (it might be saved as a file).

There is no way for a link in a web page that leads to a CSS file or a JavaScript file, etc, to be properly rendered in a browser.

To achieve whatever it is you are trying to achieve (you didn't say), you can create a link that invokes a JavaScript function that provides the extra functionality you need.


The Reason is really quite simple..


The Accepts header is saying to the server i accept and know how to display this type of file / file content....


Why you can change the header on sending a request it in javascript is you could well have created a way to accept this new content type say you encrypted something and sent it as file type encrypted/myencryption your javascript could well know how to decrypt it so it can accept that type of content so it should tell the server it can accept that content

Anchor links <a></a>

Are nothing more than telling the browser to obtain the file in the href and render it so if the browser can't understand it it was try to parse it and show a download prompt for the file. some servers get around this by just setting the type to text/plain and then the browser will just show the text of the file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.