JSON Content-Type: The Correct application/json Header (and When to Use Others)
The correct Content-Type for JSON is application/json. This guide explains why, covers common mistakes like text/json and text/plain, and shows how to set the header in every major language and framework.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →If you've ever seen an API fail silently because a server sent JSON with Content-Type: text/html, or watched a client reject a valid response because it expected application/json but got text/plain, this guide is for you.
The correct MIME type for JSON is application/json. Everything else — text/json, text/x-json, application/x-json, text/javascript — is either legacy, wrong, or specific to a niche use case. Here's the full picture.
The Correct Content-Type for JSON
Content-Type: application/json
This is the MIME type registered with IANA (Internet Assigned Numbers Authority) in RFC 4627 (2006) and updated in RFC 8259 (2017), which is the current JSON specification. It tells the receiver two things:
- The body is JSON-encoded data
- The character encoding defaults to UTF-8 (per RFC 8259, §8.1)
You do not need to add ; charset=utf-8 — it is implied. Adding it is not wrong, but it is redundant for application/json.
What Happens If You Use the Wrong Content-Type
text/json or text/x-json
These were used before application/json was officially registered. They appear in old codebases, early REST framework documentation, and some legacy APIs. They are not wrong in the sense that a browser or HTTP client will usually still parse the body, but:
- Strict clients may reject them. Some API gateways and HTTP libraries check the Content-Type header before attempting to parse the body as JSON.
- They bypass some security protections. Content-Type sniffing behavior in browsers differs for
text/*vsapplication/*types. - They are not the IANA-registered type. Any new code should use
application/json.
text/plain
A server that returns JSON with Content-Type: text/plain is telling the client "this is plain text." Most REST clients will receive the response body but will not automatically parse it as JSON. You'll get a string, not an object.
Common cause: a backend framework's default response type when you return a string instead of calling a JSON serializer.
application/x-www-form-urlencoded or multipart/form-data
These are form submission types. If a client sends JSON to an API endpoint that expects form data, the server won't be able to parse the body. This is the most common source of 400 errors when integrating with third-party APIs that have inconsistent documentation.
Setting the Content-Type in Every Major Language
Fetch API (JavaScript/Browser)
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ key: 'value' }),
});
const data = await response.json();
Note: response.json() does not check the Content-Type header — it always attempts to parse the body as JSON. For production code, check response.headers.get('content-type') before calling .json() if you can't trust the server.
Node.js (fetch)
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
Express.js (sending JSON responses)
app.get('/api/data', (req, res) => {
res.json({ key: 'value' }); // Sets Content-Type: application/json automatically
});
res.json() sets the Content-Type header for you. Do not use res.send(JSON.stringify(obj)) — that sets Content-Type: text/html by default.
Python (requests library)
import requests
# Sending JSON — requests sets Content-Type: application/json automatically
response = requests.post(
'https://api.example.com/data',
json={'key': 'value'} # use 'json=' not 'data='
)
data = response.json()
Critical: Use json= not data= when sending JSON with requests. Using data=JSON.dumps(obj) sends the body but does not set the Content-Type header to application/json. You would need to add the header manually.
# This is wrong — sends JSON body but wrong Content-Type
response = requests.post(url, data=json.dumps(payload))
# This is correct — requests sets Content-Type for you
response = requests.post(url, json=payload)
Python (aiohttp)
import aiohttp
import json
async with aiohttp.ClientSession() as session:
async with session.post(
'https://api.example.com/data',
json={'key': 'value'} # sets Content-Type: application/json
) as response:
data = await response.json()
Python (FastAPI — receiving JSON)
FastAPI validates the Content-Type header and parses the body automatically:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Payload(BaseModel):
key: str
@app.post('/data')
async def receive_data(payload: Payload):
return {'received': payload.key} # Returns application/json automatically
Go (net/http)
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func sendJSON() error {
payload := map[string]string{"key": "value"}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.example.com/data", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
_, err := client.Do(req)
return err
}
curl
curl -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
HTTPie
http POST https://api.example.com/data key=value
HTTPie sets Content-Type: application/json automatically when you pass key=value arguments. Alternatively:
echo '{"key": "value"}' | http POST https://api.example.com/data Content-Type:application/json
Reading the Content-Type Header in Responses
JavaScript / fetch
const response = await fetch('https://api.example.com/data');
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
const data = await response.json();
} else {
const text = await response.text();
console.error('Expected JSON, got:', contentType, text);
}
Python / requests
response = requests.get('https://api.example.com/data')
if 'application/json' in response.headers.get('Content-Type', ''):
data = response.json()
else:
raise ValueError(f"Unexpected Content-Type: {response.headers.get('Content-Type')}")
Special Cases
JSONP — application/javascript
JSONP (JSON with Padding) is a legacy technique for cross-origin requests that wraps a JSON payload in a JavaScript function call. Its correct Content-Type is application/javascript — not application/json. JSONP is largely obsolete since CORS became universal, but you may encounter it in older API integrations.
JSON Lines / NDJSON — application/x-ndjson
JSON Lines (.jsonl) files contain one JSON object per line. The MIME type application/x-ndjson is common, though application/jsonlines and application/x-jsonlines appear in some APIs. No single type is formally registered for this format — check what your target API documents.
JSON Patch — application/json-patch+json
RFC 6902 defines JSON Patch (a format for describing changes to JSON documents) with its own registered media type: application/json-patch+json. A PATCH request using JSON Patch should use this header, not plain application/json.
PATCH /api/resource/123 HTTP/1.1
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/name", "value": "New Name" },
{ "op": "remove", "path": "/deprecated_field" }
]
JSON Merge Patch — application/merge-patch+json
RFC 7396 defines a simpler patch format (just send the fields you want to change). Its media type is application/merge-patch+json.
HAL JSON — application/hal+json
Hypermedia Application Language uses application/hal+json for REST responses that include _links and _embedded sections. Treat it as application/json for parsing purposes — any standard JSON parser handles it.
Debugging Content-Type Errors
The most common Content-Type-related failures in APIs:
1. Server sends wrong type, client rejectsCheck the response headers in the browser DevTools Network tab or with curl -v. If the Content-Type doesn't say application/json, find where the response is being constructed and add/fix the header.
You're sending a POST/PUT/PATCH body without Content-Type: application/json. Add the header explicitly. If you're using a library, check whether it has a json= parameter that sets the header for you.
Two common causes: (a) the body isn't valid JSON despite the correct Content-Type, or (b) the server expects a different schema than what was sent. For case (a), use AI JSON Medic's repair tool to validate and fix the body before sending.
4. CORS preflight fails with Content-Typeapplication/json is not a "simple" content type for CORS (unlike text/plain). Sending Content-Type: application/json triggers a CORS preflight OPTIONS request. If your server doesn't handle OPTIONS or doesn't return the right Access-Control-Allow-Headers, the preflight will fail. Add Content-Type to your CORS Access-Control-Allow-Headers response header.
Summary
| Use Case | Correct Content-Type |
|---|---|
| Standard JSON data | application/json |
| JSON Patch (RFC 6902) | application/json-patch+json |
| JSON Merge Patch (RFC 7396) | application/merge-patch+json |
| JSONP (legacy) | application/javascript |
| JSON Lines / NDJSON | application/x-ndjson |
| HAL JSON | application/hal+json |
The rule is simple: if you're sending or receiving JSON, the header is application/json. Everything else is a specialized format with its own registered type.
Internal Links
If you're hitting JSON parsing errors after your API receives the body, check our guides on:
- Fix Invalid JSON — repair malformed JSON before sending or after receiving
- Validate JSON — confirm your payload is valid JSON Schema-compliant
- JSON Parse Error — What It Means and How to Fix It — when
JSON.parse()orjson.loads()throws
Frequently Asked Questions
What is the correct Content-Type for JSON?
The correct MIME type for JSON is application/json. This is the IANA-registered type defined in RFC 8259. Use this in both request headers (when sending JSON) and response headers (when returning JSON from an API).
Should I add charset=utf-8 to the Content-Type header for JSON?
No — it is optional and redundant. RFC 8259 mandates UTF-8 as the default encoding for JSON. Content-Type: application/json already implies UTF-8. Adding ; charset=utf-8 is not wrong, but modern APIs omit it.
What is the difference between text/json and application/json?
text/json is a legacy MIME type used before application/json was officially registered. Both describe JSON data, but application/json is the current IANA-registered standard. New APIs should always use application/json. text/json may cause issues with strict clients or security tools that rely on Content-Type for sniffing.
Why does my API return 415 Unsupported Media Type?
A 415 error means the server cannot process the request body because the Content-Type header is missing, wrong, or not supported. Add Content-Type: application/json to your POST/PUT/PATCH request headers. If you're using the Python requests library, use json=payload instead of data=json.dumps(payload) — the json= parameter sets the header automatically.
Does JSON require UTF-8 encoding?
Yes. RFC 8259 (§8.1) requires that JSON exchanged between systems must be encoded in UTF-8. UTF-16 and UTF-32 are permitted only in closed systems where all components agree on the encoding. For any public API, UTF-8 is required.
What Content-Type should I use for JSON Lines (NDJSON)?
The most common Content-Type for JSON Lines (one JSON object per line, .jsonl files) is application/x-ndjson. Some APIs use application/jsonlines or application/x-jsonlines. There is no single formally registered type — check the documentation of the specific API you're integrating with.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles