Короткий ответ
Content-Type сообщает получателю формат и кодировку тела сообщения (например, application/json; charset=utf-8); без него клиент может неправильно распарсить тело или библиотека по умолчанию откажется автоматически декодировать JSON.
Как это работает подробнее
заголовок передаётся и в запросе, и в ответе; на основе него сервер решает, как парсить тело запроса (JSON, form-data, multipart), а клиент — как интерпретировать ответ. Многие HTTP-клиенты (например, requests) предоставляют метод .json(), который сам пытается распарсить тело независимо от заголовка, но это не гарантия — некоторые строгие клиенты и браузеры ориентируются именно на заголовок.
Пример кода
example.py
import requests
import json
# Намеренная ошибка: тело JSON, но заголовок не указан
resp = requests.post(
"https://api.example.com/items",
data=json.dumps({"name": "test"}) # без headers={"Content-Type": "application/json"}
)
print(resp.status_code) # многие строгие серверы вернут 415 или 400
# Исправленный вариант
resp_ok = requests.post(
"https://api.example.com/items",
json={"name": "test"} # requests сам выставит Content-Type: application/json
)Что использовать на практике
- Рекомендация. при отправке JSON нужно явно указывать
Content-Type: application/json; для форм —application/x-www-form-urlencoded; для файлов —multipart/form-dataс boundary. Фреймворки (FastAPI, Flask) обычно сами выставляют корректный Content-Type в ответе на основе возвращаемого объекта.
Подводные камни
- Риски. отправлять JSON-тело с
Content-Type: text/plain, из-за чего сервер пытается распарсить его как обычный текст и возвращает 400/422; забывать указыватьcharset, что может привести к проблемам с не-ASCII символами; вручную собирать multipart-запрос без корректного boundary.