What is the difference between Content-Type...charset=X and Content-Encoding=X?

According to RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content, the Content-Encoding header contains a list of content coding values. Quoting the RFC:

Content coding values indicate an encoding transformation that has been or can be applied to a representation. Content codings are primarily used to allow a representation to be compressed or otherwise usefully transformed without losing the identity of its underlying media type and without loss of information. Frequently, the representation is stored in coded form, transmitted directly, and only decoded by the final recipient.

content-coding = token

All content-coding values are case-insensitive and ought to be registered within the "HTTP Content Coding Registry", as defined in Section 8.4. They are used in the Accept-Encoding (Section 5.3.4) and Content-Encoding (Section 3.1.2.2) header fields.

Section 8.4 says:

The "HTTP Content Coding Registry" defines the namespace for content coding names (Section 4.2 of [RFC7230]). The content coding registry is maintained at http://www.iana.org/assignments/http-parameters.

The registry currently lists:

br           Brotli Compressed Data Format                [RFC7932]     
compress     UNIX "compress" data format                  [RFC7230] Section 4.2.1
deflate      "deflate" compressed data ([RFC1951])        [RFC7230] Section 4.2.2
             inside the "zlib" data format ([RFC1950])
exi          W3C Efficient XML Interchange
gzip         GZIP file format [RFC1952]                   [RFC7230] Section 4.2.3
identity     Reserved (synonym for "no encoding" in       [RFC7231] Section 5.3.4
             Accept-Encoding)
pack200-gzip Network Transfer Format for Java Archives
x-compress   Deprecated (alias for compress)              [RFC7230] Section 4.2.1
x-gzip       Deprecated (alias for gzip)                  [RFC7230] Section 4.2.3

UTF-8 is a character encoding scheme that can't be used to transform arbitrary binary data losslessly (at least not in a way that would make any sense). It's simply wrong to set Content-Encoding to UTF-8. User agents might simply ignore the unknown value or discard the message and report an error. The correct place to set the character encoding scheme is the Content-Type header.


Optional parameter charset makes sense only for text-based content (Content-Types like text/plain, text/html, and such). Not all messages are text.

Content-Encoding means that the whole body has been encoded in some way (usually compressed). Typical values for this header are gzip and deflate. The recipient of this message should decode (e.g. ungzip) the body to get the original message.

I'm not even sure if UTF-8 makes any sense as a value for the Content-Encoding.