811

In a blog post I use the following PHP to set the content-type of a response:

header('content-type: application/json; charset=utf-8');

I just got a comment on that post saying that content-type needs to be capitalized, Content-type. Is this correct? It seems to work for me with all lower-case, and I assumed the HTTP headers were case-insensitive. Or does it just work because browsers are nice?

Svish
  • 138,188
  • 158
  • 423
  • 589
  • 33
    It's case insensitive, but if you're going to fix the case, it should be 'Content-Type'. – mc0e Jan 09 '15 at 21:31
  • 10
    FWIW, sending "charset" with application/json is pointless. There is no such parameter. – Julian Reschke Dec 02 '15 at 09:35
  • 6
    @JulianReschke - That is false, charset is a valid parameter within Content-Type header. See https://www.w3.org/International/articles/http-charset/index and https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type – cchamberlain Aug 22 '16 at 23:25
  • 6
    @cchamberlain - it's meaningless in "applocation/json". There is no such parameter for that media type. – Julian Reschke Aug 23 '16 at 19:28
  • 2
    @JulianReschke There are no downsides to adding the parameter. Also, there are even some applications/libraries that will flat out not work unless it includes a charset parameter. Applications that don't expect a charset parameter on the other hand will continue to work fine if you add it. – NullUserException Nov 07 '16 at 23:05
  • 8
    @NullUserException - the downside (aside from wasted bytes) is to continue to confuse people about the charset param. Just get those components fixed instead. – Julian Reschke Nov 08 '16 at 12:38
  • 11
    @JulianReschke is correct. The [IANA application/json assignment](https://www.iana.org/assignments/media-types/application/json) says charset is meaningless for this media type. it doesn't do anything. Please don't add it, because it's noise that leads to unnecessary confusion. – Reinstate Monica 2331977 Mar 03 '17 at 06:37
  • Could charset inclusion be future-proofing? Let's assume you've got internationalised templates in your json ... charset=utf-16 / 32 ? – Tyeth Aug 06 '17 at 11:57
  • 3
    I’d guess probably not, Tyeth. JSON is specified as being encoded in UTF-8, UTF-16 or UTF-32 only; anything else, and it’s not JSON. Those are encodings, not character sets (though "charset" is fuzzy about this distinction) — they are all encodings for the same character set, that of Unicode. The spec also mandates the algorithm for determining the correct encoding from the content alone, so the only reason one might include this is to work around bugs in software that both reads JSON _and_ content type headers incorrectly. – Semicolon Oct 01 '17 at 08:04

9 Answers9

1045

Header names are not case sensitive.

From RFC 2616 - "Hypertext Transfer Protocol -- HTTP/1.1", Section 4.2, "Message Headers":

Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive.

The updating RFC 7230 does not list any changes from RFC 2616 at this part.

Qwerty
  • 19,992
  • 16
  • 88
  • 107
Ignacio Vazquez-Abrams
  • 699,552
  • 132
  • 1,235
  • 1,283
  • 103
    Answer is still true, RFC 7230 states: "Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace." – Martin Müller Dec 11 '14 at 15:34
  • 7
    Header fields are case sensitive when using PHP to get the value of a header field using the method 'apache_request_headers()'. – Harm Oct 21 '15 at 10:13
  • 8
    Can anyone provide examples of popular browsers that do not comply with the spec in this regard? – David W Nov 13 '15 at 17:28
  • 8
    @Harm That's only because string comparison in PHP is case-sensitive. – MrWhite Feb 22 '16 at 00:00
  • 7
    For anyone looking, here is where RFC 7230 explicitly states that field headers should be treated as case insensitive: https://tools.ietf.org/html/rfc7230#section-3.2 – J Z Aug 09 '17 at 19:12
  • Random fact: some systems (AWS CloudFront being one) may leverage this part of the standard when they rewrite your headers. I've had the case of header keys change on me unexpectedly - good to know for next time – killthrush Nov 19 '17 at 18:03
  • 2
    what about header field values? – JoeCodeFrog Jan 31 '18 at 17:06
  • 2
    @JoeCodeFrog: Header field values are application-defined; you will need to consult the documentation of the specific application in use. – Ignacio Vazquez-Abrams Jan 31 '18 at 17:08
  • Am I the only one who think that "case-insensitive" does *not* mean that case can nor should manipulated? – MatteoSp Feb 06 '21 at 23:39
259

HTTP header names are case-insensitive, according to RFC 2616:

4.2:

Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive.

(Field values may or may not be case-sensitive.)

If you trust the major browsers to abide by this, you're all set.


BTW, unlike most of HTTP, methods (verbs) are case sensitive:

5.1.1 Method

The Method token indicates the method to be performed on the
resource identified by the Request-URI. The method is case-sensitive.

   Method         = "OPTIONS"                ; Section 9.2
                  | "GET"                    ; Section 9.3
                  | "HEAD"                   ; Section 9.4
                  | "POST"                   ; Section 9.5
                  | "PUT"                    ; Section 9.6
                  | "DELETE"                 ; Section 9.7
                  | "TRACE"                  ; Section 9.8
                  | "CONNECT"                ; Section 9.9
                  | extension-method
   extension-method = token
Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
  • Another comment said this answer is obsoleted. Is that true? If so, maybe you can update it so people don't get confused. – speedplane Mar 07 '16 at 20:31
  • using `curl -X put` lower cased verb will return 400 bad request cryptic error from server. It took some time before realizing that verb was invalid. curl also did not throw any warnings. `curl -X PUT` went thru. – Sushil May 26 '21 at 08:42
42

tldr; both HTTP/1.1 and HTTP/2 headers are case-insensitive.

According to RFC 7230 (HTTP/1.1):

Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace.

https://tools.ietf.org/html/rfc7230#section-3.2

Also, RFC 7540 (HTTP/2):

Just as in HTTP/1.x, header field names are strings of ASCII
characters that are compared in a case-insensitive fashion.

https://tools.ietf.org/html/rfc7540#section-8.1.2

Afshin Mehrabani
  • 28,405
  • 26
  • 117
  • 186
  • 20
    just clarifying: field *names* are case insensitive; field *values* can be case-sensitive, depending on the field name. – Julian Reschke Dec 15 '16 at 19:07
  • 11
    Continued citation from HTTP/2 RFC: "However, header field names MUST be converted to lowercase prior to their encoding in HTTP/2. A request or response containing uppercase header field names MUST be treated as malformed (Section 8.1.2.6)" – Borek Bernard Sep 18 '17 at 08:34
  • 3
    I just noticed the "MUST be converted to lowercase..." part as well. Why is that? CamelCase appears to be preferred casing in practice (developer tools, popular code libraries), so why would HTTP/2 attempt to go against that trend? – jimp Oct 27 '17 at 16:03
  • 7
    @jimp - because standards are about consistency - using camel-case can be ambiguous - especially with abbreviations, initialisations and acronyms. For example - would it be "Front-End-Https" or "Front-End-HTTPS" - "WWW-Authenticate" or "Www-Authenticate" - specifying all lowercase removes ambiguity by standardising the field. This in turn simplifies handling the headers all round. – Fraser Apr 10 '18 at 18:31
  • @jimp It could be related to HPACK, the header compression algorithm used with HTTP2. It's certainly easier if it's all lowercase. Also it has a small static dictionnary : https://tools.ietf.org/html/rfc7541#appendix-A – YoungFrog Aug 21 '20 at 09:46
17

header('Content-type: image/png') did not work with PHP 5.5 serving IE11, as in the image stream was shown as text

header('Content-Type: image/png') worked, as in the image appeared as an image

Only difference is the capital 'T'.

Rudiger W.
  • 686
  • 5
  • 12
  • 23
    Then there is obviously a problem with the implementation because all header fields are supposed to read as case-insensitive. Apache Bench is also messed up. It doesn't like lowercase field names. – bond Mar 03 '16 at 04:32
10

They are not case sensitive. In fact NodeJS web server explicitly converts them to lower-case, before making them available in the request object.

It's important to note here that all headers are represented in lower-case only, regardless of how the client actually sent them. This simplifies the task of parsing headers for whatever purpose.

jayarjo
  • 14,000
  • 20
  • 83
  • 123
  • That's because node/javascript is case-sensitive, so to simplify things they normalize everything to lower-case, meaning the HTTP headers in effect are case insensitive. – Svish Jul 07 '19 at 14:25
5

The RFC for HTTP (as cited above) dictates that the headers are case-insensitive, however you will find that with certain browsers (I'm looking at you, IE) that capitalizing each of the words tends to be best:

Location: http://stackoverflow.com

Content-Type: text/plain

vs

location: http://stackoverflow.com

content-type: text/plain

This isn't "HTTP" standard, but just another one of the browser quirks, we as developers, have to think about.

Robert Lerner
  • 146
  • 1
  • 4
2

officially, headers are case insensitive, however, it is common practice to capitalize the first letter of every word.
but, because it is common practice, certain programs like IE assume the headers are capitalized.
so while the docs say the are case insensitive, bad programmers have basically changed the docs.

GideonMax
  • 356
  • 2
  • 10
0

I have used code as below:

reqObj['headers'] = new Headers({
    CSRF: ABCD-DEFG..,
});

I could see it getting converted to lowercase ('csrf'). Will revisit, and update with further findings. However, as it is being done by the constructor, I assume it should be working. Hence also, Headers seem to be case-insensitive.

-14

the Headers word are not case sensitive, but on the right like the Content-Type, is good practice to write it this way, because its case sensitve. like my example below

headers = headers.set('Content-Type'
PPK
  • 11
  • 7