jsonerrorsapihttpdebugging

415 Unsupported Media Type — Fix JSON API Errors

·8 min read·Error Fixes

What Is HTTP 415 Unsupported Media Type?

A 415 Unsupported Media Type response means the server refuses your request because it does not support the Content-Type you declared for the request body. It is not a problem with your JSON being malformed — it is that the server does not know what format it is receiving.

This almost always happens when sending a JSON body without the Content-Type: application/json header.

Why 415 Happens: All the Causes

Cause 1 (Most common): Missing Content-Type header

javascript
// WRONG — browser defaults to text/plain;charset=UTF-8
fetch("/api/users", {
  method: "POST",
  body: JSON.stringify({ name: "Ravi" }),
});

Without a Content-Type header, the browser sends text/plain;charset=UTF-8 (for string bodies) or application/x-www-form-urlencoded (for form data). The server's JSON parser middleware never runs.

Cause 2: Wrong Content-Type value

javascript
// WRONG — application/x-www-form-urlencoded cannot carry JSON
fetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: JSON.stringify({ name: "Ravi" }),
});

Cause 3: charset suffix causing mismatch

Some servers only accept application/json exactly and reject application/json;charset=utf-8. This is technically wrong server behavior but you may encounter it with strict SOAP or enterprise APIs.

Cause 4: Sending a pre-stringified body to axios

javascript
// WRONG — axios cannot detect Content-Type from a string body
await axios.post("/api/users", JSON.stringify({ name: "Ravi" }));
// sends Content-Type: text/plain — triggers 415

Cause 5: Server-side JSON middleware not configured

The server does not have a JSON body parser registered — Express without express.json(), Spring without @RequestBody, etc.

Fix: JavaScript fetch (The Complete Version)

javascript
const response = await fetch("/api/orders", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Authorization": `Bearer ${token}`,
  },
  body: JSON.stringify(payload),
});

if (response.status === 415) {
  throw new Error("Server rejected our Content-Type. Check that the API accepts JSON.");
}

if (!response.ok) {
  const err = await response.json().catch(() => ({}));
  throw new Error(err.message || `HTTP ${response.status}`);
}

const data = await response.json();

Fix: axios

Pass the plain object — never stringify manually before passing to axios:

javascript
// CORRECT — axios auto-sets Content-Type: application/json
await axios.post("/api/orders", payload);

// Also correct — explicit headers
await axios.post("/api/orders", payload, {
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${token}`,
  },
});

// WRONG — triggers 415 because axios sees a string, not an object
await axios.post("/api/orders", JSON.stringify(payload));

Fix: Python requests Library

python
import requests

# WRONG — sends application/x-www-form-urlencoded
requests.post("/api/orders", data={"name": "Ravi"})

# CORRECT — json= param serializes and sets Content-Type automatically
requests.post("/api/orders", json={"name": "Ravi"})

# Also correct — fully manual approach
import json
requests.post(
    "/api/orders",
    data=json.dumps({"name": "Ravi"}),
    headers={"Content-Type": "application/json"},
)

Fix: curl

bash
# WRONG — no Content-Type
curl -X POST https://api.example.com/users \
  -d '{"name":"Ravi"}'

# CORRECT
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"name":"Ravi"}'

# With a file
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d @payload.json

Server-Side Fixes: Configure JSON Parsing

Express (Node.js):

javascript
const express = require("express");
const app = express();

app.use(express.json());            // parses application/json
app.use(express.urlencoded({ extended: true })); // parses form-encoded (optional)

Without express.json(), req.body is undefined for all JSON requests.

FastAPI (Python):

python
from pydantic import BaseModel
from fastapi import FastAPI

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    email: str

@app.post("/users")
async def create_user(user: UserCreate):
    # FastAPI automatically expects application/json for Pydantic body params
    return {"created": user.name}

Spring Boot (Java):

java
@RestController
@RequestMapping("/api")
public class UserController {
    @PostMapping(value = "/users",
                 consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<User> createUser(@RequestBody UserRequest req) {
        // Spring automatically parses application/json bodies via Jackson
        return ResponseEntity.ok(userService.create(req));
    }
}

Go (net/http):

go
func createUser(w http.ResponseWriter, r *http.Request) {
    ct := r.Header.Get("Content-Type")
    if !strings.HasPrefix(ct, "application/json") {
        http.Error(w, "Content-Type must be application/json", 415)
        return
    }

    var req UserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, err.Error(), 400)
        return
    }
    // process...
}

Django REST Framework (Python):

python
# settings.py — ensure JSONParser is in the list
REST_FRAMEWORK = {
    "DEFAULT_PARSER_CLASSES": [
        "rest_framework.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        "rest_framework.parsers.MultiPartParser",
    ]
}

Debugging Checklist

CheckWhere to lookWhat you expect
Request Content-TypeBrowser Network tab → Headersapplication/json
Request body formatBrowser Network tab → PayloadJSON string {"key":"value"}
Server middlewareServer codeexpress.json() or equivalent
Axios payload typeYour codePlain object, not JSON.stringify'd string
Python requests callYour codejson= param, not data=

Use JSONKit's JSON Validator to confirm your JSON payload is syntactically correct before sending it, and use the curl examples above to test the endpoint directly.

Try JSON Validator

Confirm your request body is valid JSON before setting Content-Type.