The short answer: application/json, and almost nothing else
· 11 min read
Which Content-Type do you send for JSON? What application/json and text/json actually are, why the +json suffix exists, and how Accept negotiation works.

The highest-voted question on Stack Overflow's json tag is "Which JSON content type do I use?": 11,652 score, 4,045,766 views. Its accepted answer, at 11,616 votes, still cites RFC 4627: a 2006 Informational document, obsolete since 2017.
Those counts are a decade of accumulated community interest, not search volume. No keyword data was available for this post, and none is implied. The shape is the point: the field's most-cited answer to its most-asked question points at a dead spec.
The answer fits in one header line: send application/json. Everything worth knowing is in the exceptions.
What RFC 8259 actually registers
RFC 8259 is Standards Track, December 2017, and it obsoletes RFC 7159. Its §11 registration is the entire authority here:
The media type for JSON text is application/json.
Type name: application
Subtype name: json
Required parameters: n/a
Optional parameters: n/a
Encoding considerations: binary
Neither parameter row carries a value: no charset, no version, no profile. Anything you append outside that block is inert, or something you invented.
RFC 4627 defined the type in 2006. Informational, obsolete since 2017. Cite 8259.
The charset=utf-8 argument, settled
Both camps are wrong. RFC 8259 §11, immediately after that registration block, says:
Note: No "charset" parameter is defined for this registration. Adding one really has no effect on compliant recipients.
So Content-Type: application/json; charset=utf-8 is neither required nor forbidden. The type works without it. It is inert, and a compliant recipient ignores it. "You must send charset=utf-8" and "you must never send charset=utf-8" both fail, in opposite directions.
The encoding question underneath is real but narrower than either side claims. RFC 8259 §8.1: "JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8." Scoped, not absolute. The next paragraph concedes why: "the vast majority of JSON-based software implementations have chosen to use the UTF-8 encoding, to the extent that it is the only encoding that achieves interoperability." UTF-8 in practice; the header buys nothing.
What text/json actually is (and is not)
application/json and text/json are not two spellings of the same thing. One is a registered media type backed by an RFC that defines what the bytes mean. The other is a legacy label nobody ever registered.
The usual framing is wrong in a specific way. A lot of writing claims RFC 8259 obsoleted text/json. It did not. A full-text search of RFC 8259, RFC 7159 and RFC 4627 returns zero occurrences of text/json in all three, and text/json has no row in IANA's media type registry: the text/* subtree parses to 103 entries, none of them json. There is no formal obsolescence to point at, because there was never a registration to obsolete. text/json is legacy and unregistered. Anyone telling you an RFC deprecated it is reciting a plausible story.
Why does it persist? Registrations are sticky. RFC 6838 §5.5: "Media type registrations may not be deleted; media types that are no longer believed appropriate for use can be declared OBSOLETE by a change to their 'intended use' field." Once a bad type reaches a codebase or a decade of tutorial copy, it does not disappear because a registry got tidied. Practically, sending text/json gets you an unregistered type: some old clients honour it, some reject it as unrecognised, some negotiate it into a plain-text response. A compatibility hazard rather than a semantic one, because nothing defines what it is supposed to mean.
This is the thinnest-covered question in the area: the two Stack Overflow questions targeting the myth directly score 73 and 70, on 46,694 and 63,748 views, while the four-million-view question is "which do I use". Readers ask the decision question; almost nobody asks the taxonomy one.
The +json structured syntax suffix
What the suffix buys you
RFC 6839 §3.1 is the whole legal basis, four lines long. Check the category first: Informational, January 2013, updating RFC 3023. Not Standards Track, not a standard. RFC 6838, next section, is the Best Current Practice one.
[RFC4627] defines the "application/json" media type. The suffix "+json" MAY be used with any media type whose representation follows that established for "application/json".
MAY. Same grammar, your own semantics, opt-in.
What it buys is the ability to name a processing contract rather than a grammar. application/json tells a receiver the bytes parse as JSON and nothing more. application/merge-patch+json tells it how to apply them.
RFC 7396 (Standards Track, October 2014, obsoletes RFC 7386) makes it concrete. Its §3 example is a PATCH /target with Content-Type: application/merge-patch+json and the body:
{"a":"z","c":{"f":null}}
Under merge-patch semantics a becomes "z", f is deleted, everything else untouched. Send that identical body as application/json and a server with no merge-patch handling stores the object as written. f survives, a stays. No linter flags it.
RFC 6902 (Standards Track, April 2013, not obsoleted) registers application/json-patch+json for a different model entirely: an operation list, where null is a value inside an operation object rather than a deletion instruction. Two patch formats, same grammar, two media types: the argument against treating all JSON as one type.
What it obliges you to
The suffix inherits three things from application/json by reference, in the registration itself:
- Encoding — "Per [RFC4627], JSON is allowed to be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible ([RFC2045])."
- Fragment identifier — "The syntax and semantics of fragment identifiers specified for +json SHOULD be as specified for 'application/json'."
- Security — "See [RFC4627]", which now resolves to RFC 8259 §12.
+json is not decoration bolted onto a type invented in a whiteboard session, and a +json type behaving differently in UTF-16 than application/json does is not conformant. The first quote is also a historical citation pointing at an obsolete RFC. Read it as "whatever JSON allows", which RFC 8259 §8.1 now defines.
For scale: IANA's registry currently holds 174 distinct +json subtypes under application/, roughly 40 of them vnd.*. That cuts both ways: derived JSON types are a heavily populated, legitimate practice, and inventing a name is something you register, not something you type.
The +json types you will actually meet
| Type | Defined by (status) | What it is for | Widely implemented? |
|---|---|---|---|
application/json |
RFC 8259 §11 (current) | JSON text. The default for any payload. | Yes — universal |
application/problem+json |
RFC 9457 (current; obsoletes 7807) | Machine-readable HTTP errors: type, title, status, detail. XML twin application/problem+xml. |
Yes — de-facto for API errors |
application/merge-patch+json |
RFC 7396 (current) | Merge Patch body for PATCH. null deletes. |
Yes — server frameworks |
application/json-patch+json |
RFC 6902 (current) | JSON Patch operation list. Not the same as merge patch. | Yes |
application/geo+json |
RFC 7946 §12 (current) | GeoJSON objects. §12 asks that vnd.geo+json be marked OBSOLETED. |
Yes — mapping stacks |
application/ld+json |
W3C JSON-LD 1.1 API (Rec) | Linked Data context expansion. | Moderate — SEO tooling |
application/yaml, +yaml |
RFC 9512 (Informational, current) | YAML documents. The contrast case. | Growing — YAML is a JSON superset |
application/vnd.api+json |
JSON:API (non-IETF spec) | JSON:API documents. Has ext and profile. |
Narrow — JSON:API clients |
application/graphql-response+json |
IETF WG working draft | GraphQL response envelope. Requests use plain application/json. |
Narrow — evolving |
application/json-seq |
RFC 7464 (Standards Track, current) | Concatenated JSON texts, streaming. | Rare |
application/jose+json |
RFC 7515 (Standards Track, current) | JOSE objects: JWK sets, flattened JWS. | Yes — JWT tooling |
application/jwk+json, jwk-set+json |
RFC 7517 (Standards Track, current) | JSON Web Key(s). | Yes |
application/scim+json |
RFC 7644 (Standards Track, current) | SCIM provisioning payloads. | Yes — enterprise IdP |
application/rdap+json |
RFC 9083 (Standards Track, current) | Registration Data Access Protocol. | Narrow |
application/problem+json, and the 7807 trap
RFC 9457 is Standards Track, July 2023, and it obsoletes RFC 7807. If you find code or documentation citing 7807 as current, that reference is three years stale.
What did the obsoletion change? Appendix D lists three items: a registry of common problem type URIs (§4.2), clarification of how multiple problems should be treated (§3), and guidance for type URIs that cannot be dereferenced (§3.1.1). Registries and guidance. No wire format changed. If your client parses problem documents today, RFC 9457 did not break you, and implying otherwise invents a breaking change that does not exist.
geo+json, ld+json, and yaml
RFC 7946 (Standards Track, August 2016, not obsoleted) registers application/geo+json in §12, and the same section asks that the application/vnd.geo+json entry be marked OBSOLETED with a pointer to the new type. I did not confirm the live registry row reads OBSOLETED, so treat that migration as "per RFC 7946 §12" rather than verified in place.
application/ld+json is a W3C registration rather than an IETF one, per the JSON-LD 1.1 API, a Recommendation. It carries a normative preference order worth imitating: a request "MUST prefer Content-Type application/ld+json followed by application/json". An Accept list in miniature.
application/yaml comes from RFC 9512, which is Informational, February 2024. Again not a standard, an easy assumption to make. It also registers a +yaml suffix, so the mechanism matches JSON's. JSON's ecosystem has simply generated far more derived types, with HTTP error formats the largest driver. YAML being a superset of JSON means one type does most of the work there.
application/vnd.api+json, and what a vendor type obliges you to do
JSON:API "requires use of the JSON:API media type (application/vnd.api+json) for exchanging data." A community specification, not an RFC and not a W3C Recommendation. Its IANA contact is an individual contributor.
That is also the shape worth copying. A vendor type carries parameters for its dialect: JSON:API defines ext and profile. The suffix tells you the grammar; the parameters tell you which variant.
RFC 6838 closes off the free-form version. §4.2.5: "This does not mean, however, that any application program name may simply be used freely as a subtype of 'application'; the subtype needs to be registered." §4.2.8: "media types MUST NOT be given names incorporating suffixes for structured syntaxes they do not actually employ", and "'+suffix' constructs for as-yet unregistered structured syntaxes SHOULD NOT be used."
So you can design a payload format freely. You cannot call it +json without registering it.
Content-Type and Accept are not the same thing
Request side vs response side
Content-Type describes the body you are sending. Accept describes what you can receive. RFC 9110, Standards Track, STD 97, June 2022, §8.3.1: "HTTP uses media types in the Content-Type and Accept header fields in order to provide open and extensible data typing and type negotiation."
One is a claim about what you did; the other a request about what you may be sent. MDN documents that split in its Content-Type reference. RFC 9110 obsoletes RFC 7231, so learning Accept semantics from 7231 means reading the superseded document.
What Accept: application/json actually matches
Accept = #( media-range [ weight ] )
media-range = ( "*/*"
/ ( type "/" "*" )
/ ( type "/" subtype )
) parameters
application/json is the type "/" subtype form. It matches application/json and nothing else: not application/problem+json, not application/merge-patch+json, not application/geo+json. To accept every application subtype, including all 174 registered +json ones, the media-range has to be application/*.
RFC 9110 illustrates the semantics with an example that maps straight onto this:
Accept: audio/*; q=0.2, audio/basic
is interpreted as "I prefer audio/basic, but send me any audio type if it is the best available after an 80% markdown in quality".
Read Accept: application/json through that grammar and the problem shows: you asked for one exact type, no wildcard, no fallback, and a server that can only produce application/problem+json has nothing it may give you. RFC 9110 also removed the accept-ext grammar, tells senders using weights to send q last, and notes the registry disallows a media type parameter named q.
q-values and the wire example from RFC 9457
RFC 9457's worked example is the single best asset in this area, because one exchange shows both halves:
POST /purchase HTTP/1.1
Host: store.example.com
Content-Type: application/json
Accept: application/json, application/problem+json
{
"item": 123456,
"quantity": 2
}
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
Read the request twice. Content-Type: application/json is plain, no suffix, because a purchase body is just JSON with no special processing rule. The same request's Accept lists two types in preference order, and the response comes back as the second.
That is why a client accepting only application/json will not get a document it can parse, and why Content-Type here does format selection rather than decoration: application/problem+json has an XML twin at application/problem+xml, and the same error could have arrived either way.
How to choose: a decision table
| Situation | Send |
|---|---|
| Any JSON body with no special processing rule | application/json |
| HTTP error details you want machine-readable | application/problem+json |
PATCH, RFC 7396 merge semantics |
application/merge-patch+json |
PATCH, RFC 6902 operation list |
application/json-patch+json |
| GeoJSON, Linked Data, or JSON:API | application/geo+json, application/ld+json, application/vnd.api+json |
| Never | text/json, or any unregistered type |
If that last row describes something in your codebase today, it is a finding, not a style preference.
What this post does not cover
The JSON grammar (objects, arrays, escaping, numbers) is separate, and our guide to the JSON format itself covers it. That page is syntax-level; this one is transport-level. Schema is a different question again: What JSON Schema is describes the shape a value must have, while the media type describes the envelope carrying it. A valid document in an unregistered envelope is still an interoperability bug, and schema tooling will not flag it.
Four claims I could not close, listed rather than smoothed over. OpenAPI 3.1.1 defines no media type of its own, verified for 3.1.1 only since I did not check the 3.2 draft. I did not confirm the IETF draft number behind the GraphQL-over-HTTP document, or whether it has since been published as an RFC. JSON:API's version is not cited because the format page does not state one. And repeated searches of RFC 6839 returned no content-negotiation section, so I have not claimed one exists.
Related Tools & Further Reading
- JSON Formatter & Validator — inspect a response body whose
Content-Typeyou are unsure about. - JSON to YAML Converter — the practical side of the
application/yamlcontrast. - YAML vs JSON — the format differences behind it.
Written by
Abhay Khant
Abhay Khant is the founder of ToolSura, a privacy-first developer tools platform. Writes about client-side architecture, AI tooling, and the open web.