What 415 means
The server refuses the request because it doesn't accept the format of the body: the media type in Content-Type, or the compression in Content-Encoding. 415 is defined in RFC 9110 §15.5.16. The server can say what it does take: Accept for media types, Accept-Encoding for content codings.
HTTP/1.1 415 Unsupported Media Type
Accept: application/json
Content-Type: application/problem+json
{"title": "Content-Type must be application/json"}
415 is about what you sent. If the server can't produce the format you asked for in Accept, that's 406 Not Acceptable.
Common causes
- No
Content-Typeon a JSON body.fetch()with a string body defaults totext/plain;charset=UTF-8, and many JSON APIs reject that. - curl's default.
curl -d '{"a":1}'sendsapplication/x-www-form-urlencoded, not JSON. - The wrong format for the endpoint: a form post to a JSON-only API, XML to an endpoint that only reads JSON, or an image type an upload endpoint doesn't take.
- Compressed bodies (
Content-Encoding: gzip) sent to a server that doesn't decompress requests. - A typo or extra parameter in the header, such as
application/jsn, that a strict parser won't match.
How to fix it as a client
Set the header to match the body you actually send.
curl --json '{"name":"Ana"}' https://api.example.com/users
curl -H 'Content-Type: application/json' -d '{"name":"Ana"}' https://api.example.com/users
--json (curl 7.82 and later) sets both Content-Type and Accept to JSON. In the browser:
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ana' }),
});
axios sets application/json itself when you pass an object. For file uploads, pass a FormData and don't set Content-Type by hand: the browser has to add the multipart boundary.
How to send it as a server
Frameworks differ. Spring answers 415 when no handler consumes the request's type, and ASP.NET Core does the same for [ApiController] actions. Express's express.json() silently skips bodies that aren't JSON and leaves req.body empty, so check the type yourself if you want a clear error:
app.post('/api/users', (req, res, next) => {
if (!req.is('application/json')) {
return res.set('Accept', 'application/json').status(415).json({ error: 'send JSON' });
}
next();
});
Answer 415 for the wrong format and 422 Unprocessable Content for the right format with invalid contents.
415 and SEO
No effect. Crawlers make GET requests without a body, so they never get 415. It shows up in APIs, webhooks and form handlers.
Related codes
- 400 Bad Request: the body is the right type but malformed, such as broken JSON.
- 422 Unprocessable Content: well-formed but failing validation.
- 413 Content Too Large: the body is too big.
- 405 Method Not Allowed: the method, not the body, is wrong.
To try different Content-Type headers against an endpoint, use the HTTP Request Builder.