Skip to content

Código de status HTTP · Erros do cliente (4xx)

Erro 415 Unsupported Media Type

O erro 415 Unsupported Media Type significa que o servidor não processa o corpo do pedido no formato enviado. Na grande maioria das vezes o corpo é JSON, mas o cabeçalho Content-Type está ausente ou diz text/plain ou formulário.

Dados sobre este código de status
Classe4xx, Erros do cliente
Definido emRFC 9110 §15.5.16
Pode ir para o cache por padrãoSó com Cache-Control ou Expires explícitos
Pode repetir o pedidoSim, depois de corrigir o Content-Type ou o formato do corpo
Cabeçalhos relevantes
  • Content-Type: cabeçalho do pedido que o servidor conferiu; ausente ou errado é a causa comum
  • Accept: cabeçalho da resposta com os tipos de mídia que o endpoint aceita
  • Accept-Encoding: cabeçalho da resposta quando o problema é o Content-Encoding (gzip, br)
  • Accept-Patch: em PATCH, lista os formatos de patch aceitos (RFC 5789)

O que significa o 415

A RFC 9110, seção 15.5.16, diz que o problema pode vir do Content-Type declarado, do Content-Encoding ou da própria inspeção dos dados pelo servidor. Ela também explica como ajudar o cliente: listar na resposta 415 as codificações aceitas em Accept-Encoding, ou os tipos de mídia aceitos em Accept.

Os frameworks se comportam de jeitos bem diferentes. Controllers do Spring MVC e do ASP.NET Core com [FromBody] respondem 415 sozinhos quando o Content-Type não tem leitor registrado. O Express não: o express.json() só ignora pedidos que não são application/json, e o req.body fica undefined. O FastAPI costuma responder 422, porque a validação falha por falta do corpo.

Um detalhe do navegador causa muitos desses erros: fetch() com corpo em string e sem cabeçalhos envia Content-Type: text/plain;charset=UTF-8. Na aba de rede parece JSON, mas o servidor recebe texto puro.

Causas comuns

Se você administra o servidor

  • fetch() chamado com body: JSON.stringify(dados) mas sem cabeçalho Content-Type, e o navegador rotula como text/plain.
  • O curl -d envia application/x-www-form-urlencoded por padrão; uma API JSON recusa, a menos que você adicione -H "Content-Type: application/json".
  • Um upload enviado como multipart/form-data para um endpoint que espera binário ou JSON, ou o contrário.
  • O corpo do pedido com Content-Encoding gzip ou br que o servidor não descompacta; o body-parser com inflate: false responde 415 nesse caso.
  • Um charset que o endpoint recusa, como application/json; charset=latin1 numa API rígida.

Como resolver

Se você administra o servidor

  • Defina o cabeçalho que corresponde ao corpo: headers: { "Content-Type": "application/json" } no fetch, ou deixe o axios definir passando um objeto em vez de string.
  • No curl, use --json '{"a":1}' (curl 7.82+), que define Content-Type e Accept como JSON.
  • Em uploads de arquivo, passe um objeto FormData e não defina Content-Type na mão; o navegador inclui o boundary do multipart.
  • No servidor, devolva um cabeçalho Accept junto com o 415 e uma mensagem com o tipo esperado, para quem integra não precisar adivinhar.

Como enviar um 415

Express (Node.js)
app.post('/orders', express.json(), (req, res) => {
  if (!req.is('application/json')) {
    res.set('Accept', 'application/json');
    return res.status(415).json({ error: 'Send the body as application/json' });
  }
  // ...
});
Next.js App Router (route handler)
// app/orders/route.ts
export async function POST(request: Request) {
  const type = request.headers.get('content-type') ?? '';
  if (!type.startsWith('application/json')) {
    return Response.json(
      { error: 'Send the body as application/json' },
      { status: 415, headers: { Accept: 'application/json' } }
    );
  }
  const order = await request.json();
  // ...
}
Go net/http
mux.HandleFunc("POST /orders", func(w http.ResponseWriter, r *http.Request) {
	mediatype, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
	if err != nil || mediatype != "application/json" {
		w.Header().Set("Accept", "application/json")
		http.Error(w, "send the body as application/json", http.StatusUnsupportedMediaType) // 415
		return
	}
	// ...
})
Python FastAPI
from fastapi import FastAPI, HTTPException, Request

app = FastAPI()

@app.post("/orders")
async def create_order(request: Request):
    if not request.headers.get("content-type", "").startswith("application/json"):
        raise HTTPException(status_code=415, detail="Send the body as application/json",
                            headers={"Accept": "application/json"})
    order = await request.json()
    ...
Terminal
# Form-encoded by default: a JSON API may answer 415
curl -X POST -d '{"sku":"A1"}' https://api.example.com/orders

# Correct: declare the type (or use --json on curl 7.82+)
curl -X POST -H 'Content-Type: application/json' -d '{"sku":"A1"}' https://api.example.com/orders

Costuma ser confundido com

415 vs 422
O 422 indica que o formato foi entendido mas o conteúdo é inválido (falta um campo obrigatório); o 415 indica que o próprio formato não é aceito.
415 vs 406
O 406 trata do formato de resposta pedido no Accept; o 415 trata do formato do pedido que o cliente enviou.
415 vs 400
O 400 serve para um corpo com o Content-Type certo que não pode ser lido, como um JSON quebrado.

Perguntas frequentes

Por que recebo 415 ao mandar JSON com fetch?
Porque o fetch() com corpo em string usa Content-Type: text/plain;charset=UTF-8 por padrão. Inclua headers: { "Content-Type": "application/json" } na requisição.
Como resolver o erro 415 no Spring Boot?
O parâmetro @RequestBody não tem conversor para o Content-Type recebido. Envie Content-Type: application/json, ou, se o cliente manda um formulário, use @ModelAttribute ou @RequestParam no lugar de @RequestBody.
Devo definir Content-Type em upload multipart?
Não manualmente. Quando você passa um FormData para o fetch ou o axios, o navegador define multipart/form-data com o boundary certo. Definir na mão tira o boundary e o servidor não consegue separar as partes.
Content-Type errado é 415 ou 400?
É 415. A RFC 9110 o define exatamente para conteúdo num formato que o recurso não aceita, seja pelo Content-Type, pelo Content-Encoding ou pela inspeção dos dados.

Revisado em por Arielton Oberek.