Content-Type: media type, charset and boundary
Content-Type declares the media type of the body, plus parameters such as charset or the multipart boundary, so the recipient knows how to parse the bytes.
At a glance
- Direction
- Both. It describes whatever body the message carries.
- Defined in
- RFC 9110
- When absent
- The recipient has to guess, and a browser may sniff the body unless X-Content-Type-Options says otherwise.
- Structure
- type/subtype, then optional parameters separated by semicolons
- Text default
- Always state charset=utf-8 rather than relying on any implied default.
- Multipart
- boundary is mandatory, and its value must not appear anywhere in the body.
- Interacts with
- X-Content-Type-Options: nosniff, which makes the declared type binding
In detail
The value has a type, a subtype and optional parameters. text/html; charset=utf-8 is a type of text, a subtype of html and one parameter naming the character encoding. Parameter order does not matter, the parameter name is case insensitive, and unrecognised parameters are ignored, which is why an unknown one never breaks a response on its own.
The charset parameter is where mojibake comes from. A page whose bytes are UTF-8 but whose header says nothing forces the browser back to a fallback encoding or to a meta element inside the document, and the header wins over the markup wherever both are present. Declaring charset=utf-8 in the header removes the whole class of problem.
For uploads, multipart/form-data carries a boundary parameter that separates the parts. The client picks a random string, states it in the header, and repeats it between parts in the body. If a proxy or a hand written client rewrites the header without preserving that exact string, the server sees one unparseable blob rather than a set of fields.
Getting the type wrong has consequences beyond display. A JSON API answering with text/html makes some clients refuse to parse the body, a JavaScript file served as text/plain is blocked outright under nosniff, and a download served as text/html renders in the tab instead of saving.
Examples
Content-Type: text/html; charset=utf-8POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----FormBoundary7MA4YWxk
------FormBoundary7MA4YWxk
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdfContent-Type: application/jsonJSON is defined as UTF-8, so a charset parameter here is redundant, though harmless.
Things that catch people out
- The header beats a meta charset declaration inside the document, so a mismatch between the two is resolved in favour of the header and the page renders wrongly.
- Sending application/json while the body is actually an HTML error page is a common gateway behaviour, and it produces parse errors that point at the wrong layer.
- A multipart boundary must be unique within the body. Reusing a fixed string across requests works until a file happens to contain it.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →Content-Length: the size of the body in octets
What Content-Length counts, why it must never accompany Transfer-Encoding, what happens when it disagrees with the body, and when it may be omitted.
Content-Disposition: download prompts and file names
How to force a download instead of inline display, how filename and filename* differ, and how to send a non-ASCII file name that survives every browser.
Accept: asking for a media type, with preferences
How the Accept header expresses preferences with q values, how servers pick a representation, and what to return when nothing on the list can be produced.
X-Content-Type-Options: nosniff and MIME sniffing
What nosniff stops a browser doing, why it is the safest security header to add, and the two kinds of resource it starts rejecting once you turn it on.
Content-Encoding: what compression was applied
What Content-Encoding declares, how it differs from Transfer-Encoding, why it changes the ETag, and how double compression happens in a proxy chain.
Content-Language: the audience a document is for
What Content-Language actually states, how it differs from the lang attribute in markup, when to list several tags, and how it pairs with Accept-Language.
Tools for this
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL