What is Content-Type header?
The server needs to know how to read data from the request. Without Content-Type, the server won't know how to deserialize the bytes.
Junior Level
Content-Type is an HTTP header that tells the server in what format the data is being sent.
Examples:
Content-Type: application/json — data in JSON format
Content-Type: application/xml — data in XML format
Content-Type: text/plain — plain text
Content-Type: multipart/form-data — form with files
Why is this needed?
The server needs to know how to read data from the request. Without Content-Type, the server won’t know how to deserialize the bytes.
Request example:
POST /users
Content-Type: application/json
{"name": "Ivan", "age": 30}
Common media types:
| Type | Description |
| ———————————– | —————– |
| application/json | JSON data |
| application/xml | XML data |
| text/html | HTML page |
| multipart/form-data | Form with files |
| application/x-www-form-urlencoded | Form data |
Middle Level
Content-Type in Spring MVC
HttpMessageConverter is responsible for handling Content-Type:
- Request arrives with
Content-Type: application/json - Spring iterates through converters (Jackson, Gson, etc.)
- The
canRead(clazz, mediaType)method returnstrue - Reading and mapping to a Java object begins
Security and MIME Sniffing
X-Content-Type-Options: nosniff
Browsers sometimes try to “guess” the content type, ignoring the header. MIME Sniffing — a browser mechanism: it tries to determine content type by content, ignoring Content-Type. Useful for backward compatibility, but creates XSS vulnerabilities.
Risk: A user uploaded an image that is actually JavaScript. The browser may execute it.
Solution: Always return X-Content-Type-Options: nosniff.
Boundary in Multipart
With multipart/form-data, the header contains a unique delimiter:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
This delimiter is used to parse the request body into separate parts.
Edge Cases
- Missing Content-Type: If the client didn’t send the header — return 415 Unsupported Media Type. Don’t try to guess the type
- Custom MIME Types: For versioning, use your own types:
application/vnd.mycompany.v1+json
Performance
- Charset: For
application/json, UTF-8 is the default per RFC 8259, socharset=utf-8is optional. Fortext/*types, specifying charset is mandatory, as the default isiso-8859-1. - Binary Formats: In Highload systems,
application/x-protobuforapplication/octet-streamis used — Protobuf is typically 3-10x faster than JSON for parsing (depends on payload size and language). Binary format doesn’t require lexical parsing, no string-key parsing — numeric field tags.
Senior Level
When Content-Type can be omitted
GET requests without a body, DELETE without a body. For requests with a body (POST, PUT, PATCH) — it’s mandatory.
Converter selection process
In Spring MVC, HttpMessageConverter is selected based on:
- The
Content-Typeheader from the request - Registered converters in the application
- The
canRead(clazz, mediaType)method
Multipart/Related vs Multipart/Form-Data
- Multipart/Form-Data: For uploading files via forms
- Multipart/Related: When you need to send an object (JSON) and a related binary file (image) in a single request. More efficient than two separate requests
Performance and Highload
- Charset Overhead: Specifying encoding prevents proxies from attempting to re-encode text
- Binary Formats: Protobuf is typically 3-10x faster than JSON for parsing (depends on payload size and language). Binary format doesn’t require lexical parsing, no string-key parsing — numeric field tags.
- Multipart/Related: More efficient for sending JSON + binary file in a single request
Diagnostics
- Curl Debugging:
curl -v -H "Content-Type: application/json" -d '{"key":"val"}' ...— the basics for API diagnostics - Postman/Insomnia Pitfalls: These tools often add
Content-Typeautomatically. When testing a “raw” API, disable auto-fill - 415 Unsupported Media Type: If the server doesn’t support the sent type — return 415, don’t try to guess
Interview Cheat Sheet
Must know:
- Content-Type tells the server the format of data in the request body:
application/json,application/xml,multipart/form-data - Content-Type is mandatory for requests with a body (POST, PUT, PATCH); not needed for GET/DELETE without body
- In Spring MVC, HttpMessageConverter handles processing (Jackson, Gson, etc.)
- X-Content-Type-Options: nosniff prevents MIME Sniffing and XSS attacks
- multipart/form-data uses a boundary delimiter to parse the body into parts
- Missing Content-Type → return 415 Unsupported Media Type, don’t guess
- Binary Formats (Protobuf) are 3-10x faster than JSON for parsing
Common follow-up questions:
- Why is X-Content-Type-Options: nosniff needed? — Prevents MIME Sniffing, where the browser “guesses” the type and executes JS
- How does Spring choose a converter? — By request Content-Type → checks canRead(clazz, mediaType) → first match
- When can Content-Type be omitted? — For GET and DELETE without body; for POST/PUT/PATCH — mandatory
- What is Multipart/Related? — Sending JSON + related binary file in one request, more efficient than two requests
Red flags (DO NOT say):
- “Content-Type and Accept are the same” — Content-Type = what I’m sending, Accept = what I want to receive
- “Content-Type is needed for GET requests” — GET without body doesn’t require Content-Type
- “The server can guess the content type” — should return 415, not guess
- “charset=utf-8 is mandatory for JSON” — UTF-8 is the default per RFC 8259, optional
Related topics:
- [[What is Accept header]]
- [[How to organize REST API versioning]]
- [[What is REST]]
- [[What HTTP status codes do you know]]
- [[What is RESTful API design]]