HTTP 415 Unsupported Media Type
HTTP 415 Unsupported Media Type means the request body is in the right place but in the wrong format. The server examined the Content-Type header and cannot process that media type on this endpoint. The most common production scenario: a frontend sending application/x-www-form-urlencoded to a backend that expects application/json. The fix is almost always to set the correct Content-Type header and re-serialize the body to match.
Quick reference
| Code | 415 |
|---|---|
| Name | Unsupported Media Type |
| Category | 4xx Client Error |
| Specification | RFC 9110 §15.5.16 |
| IANA status | Assigned |
| Fix | Correct Content-Type header and re-encode body |
| Cacheable? | No |
Content-Type vs Accept: the 415 vs 406 distinction
There are two different content negotiation headers in HTTP, and confusing them is a frequent source of bugs:
Content-Type describes what the client is sending in the request body. Accept describes what formats the client is willing to receive in the response body. They are not interchangeable.
When the server cannot process the format the client sent (based on Content-Type), it returns 415. When the server cannot produce a response in a format the client accepts (based on Accept), it returns 406 Not Acceptable. These are separate problems in opposite directions.
A 415 response may include an Accept-Post header (for POST endpoints) or Accept-Patch header (for PATCH endpoints) listing the media types the server does support. Check these headers before retrying.
Common causes and fixes
Form encoding sent to JSON API: The most common case. A browser form submission or an HTTP client using default settings sends Content-Type: application/x-www-form-urlencoded with a body like amount=100¤cy=USD. The API endpoint expects Content-Type: application/json with a body like {"amount":100,"currency":"USD"}.
// Wrong (form encoding)
fetch('/api/payments', {
method: 'POST',
body: new URLSearchParams({amount: 100, currency: 'USD'})
});
// Correct (JSON)
fetch('/api/payments', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({amount: 100, currency: 'USD'})
});
Missing Content-Type header: A request body sent with no Content-Type header leaves the server guessing. Some servers reject this with 415; others fall back to a default type. Always set Content-Type explicitly when sending a body.
Wrong type for file uploads: File uploads require Content-Type: multipart/form-data with a boundary parameter. Sending a file with Content-Type: application/json or application/octet-stream to a multipart endpoint will trigger 415. Conversely, sending multipart to an endpoint expecting a raw binary stream also triggers 415.
Version mismatch after deployment: A 415 spike after a deployment often means client and server were updated separately. The server now expects a new media type (for example, a versioned JSON type like application/vnd.example.v2+json) but the client still sends the old type.
Full request-response example
POST /api/v1/payments HTTP/1.1
Host: api.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 24
amount=100¤cy=USD
HTTP/1.1 415 Unsupported Media Type
Accept-Post: application/json
Content-Type: application/json
{"error": "unsupported_media_type",
"message": "This endpoint requires application/json"}
// Fixed request:
POST /api/v1/payments HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 30
{"amount": 100, "currency": "USD"}
HTTP/1.1 201 Created
Server-side implementation
Express.js: Express returns 415 automatically when using body parsers with strict type checks. Explicitly declare accepted types:
app.post('/api/payments', (req, res, next) => {
if (!req.is('application/json')) {
return res.status(415).json({
error: 'unsupported_media_type',
supported: ['application/json']
});
}
// process...
});
Django REST Framework: DRF uses parser classes. Configure per view or globally:
from rest_framework.parsers import JSONParser, MultiPartParser
class PaymentView(APIView):
parser_classes = [JSONParser] # Only JSON; 415 for anything else
Spring Boot: Use consumes in the request mapping:
@PostMapping(value = "/payments",
consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> createPayment(@RequestBody PaymentRequest req) {
// Spring returns 415 automatically for wrong Content-Type
}
415 vs 406 vs 400 vs 422
| Code | Problem direction | Issue |
|---|---|---|
| 415 | Request body format | Client sent wrong Content-Type |
| 406 | Response body format | Server cannot respond in client’s Accept types |
| 400 | Request format/syntax | Malformed request (syntax error, invalid headers) |
| 422 | Request body semantics | Correct Content-Type, but body fails validation |
Frequently asked questions
What causes HTTP 415?
The server cannot process the media type specified in the request’s Content-Type header. The most common cause is sending form-encoded data to a JSON API endpoint, or sending a JSON body without setting the Content-Type: application/json header.
How do I find out what Content-Type the server accepts?
Check the 415 response for an Accept-Post or Accept-Patch header listing supported types. If absent, consult the API documentation or try a GET request to a related endpoint and check its Content-Type response header as a hint.
Can 415 be triggered by Accept-Encoding or Accept-Language?
No. 415 is only triggered by the Content-Type header of the request body. Accept-Encoding (compression) and Accept-Language affect the response, not the request body format.
What is the difference between 415 and 422?
415 means the server cannot process the format (the Content-Type is wrong). 422 means the server understood the format but the content failed semantic validation (correct JSON, but a required field is missing or a value is out of range). Fix 415 by changing the Content-Type; fix 422 by changing the content.
Related guides
HTTP 406 Not Acceptable · HTTP 400 Bad Request · HTTP 422 Unprocessable Content
Comparisons
Standards reference
Definitions from the IANA HTTP Status Code Registry and RFC 9110 §15.5.16. Human-readable guidance by ErrorLookup. · HTTP 415 quick reference →