Content-Type

Correct parsing and rendering of an HTTP message body depends on knowing the media type. The HTTP Content-Type request and response header declares that type.

Usage

The Content-Type header tells the client (or server, for request bodies) the media type of the enclosed content. The media type determines how the recipient parses and renders the body. Without this header, clients resort to MIME sniffing, which introduces security risks and inconsistent behavior.

Note

Accept declares what the client wants to receive. Content-Type declares what is being sent. Accept appears in requests. Content-Type appears in both requests (when a body is present) and responses. GET requests typically have no body and need no Content-Type. POST and PUT requests with a body require the header.

A media type consists of a top-level type and a subtype separated by a slash, optionally followed by parameters. The Accept request header works alongside Content-Type during content negotiation, letting the client express preferred media types before the server selects one.

Servers and intermediaries sometimes apply Content-Encoding (such as gzip or br) before transmission. The Content-Type header always describes the original media type before encoding, not the encoded format.

The MIME-Version header traces back to the email origins of MIME types and appears in some HTTP messages, though HTTP does not require the header for media type processing.

Parameters

media-type

The media type value follows the type/subtype format registered with IANA. Common types include text/html, application/json, image/png, and application/octet-stream. A complete registry is maintained by IANA.

charset

The charset parameter specifies the character encoding of text-based media types. UTF-8 is the dominant encoding on the web.

Content-Type: text/html; charset=UTF-8

boundary

The boundary parameter is required for multipart/* media types. The boundary string separates each part of the multipart body. The boundary value must not appear within any of the body parts.

Content-Type: multipart/form-data; boundary=----FormBoundary

Example

A server returns an HTML page with UTF-8 encoding. The browser uses the media type to render the content as a web page and the charset to decode the text correctly.

Content-Type: text/html; charset=UTF-8

An API returns a JSON response. The application/json media type instructs the client to parse the body as JSON.

Content-Type: application/json

An API error response uses the application/problem+json media type to signal a structured problem details payload.

Content-Type: application/problem+json

A CDN converts an HTML page to Markdown on the fly when the client sends Accept: text/markdown. The response carries text/markdown as the content type, signaling the body is Markdown rather than HTML.

Content-Type: text/markdown; charset=utf-8

AI agents and Content-Type

CDN providers like Cloudflare return Content-Type: text/markdown alongside an x-markdown-tokens header estimating the token count of the converted document. Agents use the content type to select the correct parser and the token estimate to manage context window budgets.

A file upload uses multipart/form-data with a boundary string separating the form fields and file data within the request body.

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

A server delivers a binary file download. The application/octet-stream type signals raw binary data, often paired with a Content-Disposition header set to attachment.

Content-Type: application/octet-stream

A multipart/byteranges response delivers multiple byte ranges from a single resource. Each part has its own Content-Type and Content-Range header.

Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

Troubleshooting

Rendering failures and parsing errors often trace back to a missing or incorrect Content-Type header.

  1. Missing charset parameter causes garbled text. Browsers fall back to a default encoding (often ISO-8859-1) when no charset is declared. Non-ASCII characters appear as mojibake. Add the charset parameter explicitly: Content-Type: text/html; charset=UTF-8. In nginx:

    charset utf-8;
    

    In Apache:

    AddDefaultCharset UTF-8
    
  2. Browser applies MIME sniffing despite a correct Content-Type. Browsers sometimes ignore the declared type and sniff the body content to determine the type. This behavior creates XSS attack vectors when user-uploaded content is served as HTML. Add the X-Content-Type-Options header set to nosniff to block MIME sniffing:

    X-Content-Type-Options: nosniff
    
  3. API returns text/html instead of application/json. Clients parsing JSON from an API receive HTML error pages or framework default responses. This happens when an error handler or reverse proxy intercepts the response and replaces the body without updating the Content-Type. Check the full response chain: origin server, application framework, reverse proxy, and CDN. In Express.js, calling res.json() sets the correct header automatically. In Django, return JsonResponse instead of HttpResponse.

  4. Multipart boundary mismatch breaks file uploads. The boundary string declared in the Content-Type header must match the delimiter used in the request body. A mismatch causes the server to fail parsing the multipart body. Inspect the raw request in DevTools Network tab under the Headers and Payload sections. Avoid setting the boundary manually when using fetch() or XMLHttpRequest with FormData objects. The browser generates the correct boundary automatically when the Content-Type header is omitted from the request.

  5. Framework default Content-Type overrides an explicit setting. Some frameworks set Content-Type after the application code runs. Middleware in Express.js, Django, or Spring Boot may reset the header. Check middleware execution order. In Express.js, ensure res.type() or res.set('Content-Type', ...) is called after all middleware that modifies headers.

  6. Diagnosing Content-Type issues with DevTools. Open the browser DevTools Network tab, select the request, and inspect the Response Headers section for the Content-Type value. Compare the declared type with the actual body content shown in the Response or Preview tab. Use curl -I https://example.re/api/data to check headers from the command line without browser interference.

See also

Last updated: April 4, 2026