How to check content-type of API response
Print the media type on its own with curl -s -o /dev/null -w '%{content_type}\n' https://httpbin.org/json, which returns application/json. To see the charset parameter and the exact spelling, read the raw header from a GET with -D -. Check the error path as well as the 200.
Why check this
The content type decides whether a client parses the body, renders it, or downloads it. A JSON route that answers text/html on its 404 makes every error handler fail, and a JSON route that answers text/plain stops a browser client that filters on media type. Run this on staging sign-off and after any change to a proxy, a CDN or a framework error page.
Prerequisites
- curl. Any build works, no HTTP/2 support is needed. See the curl manual.
- The MDN reference on Content-Type for the syntax of the parameter list.
- One URL per route you care about, including a URL that is known to fail.
Steps
- Step 1.
Print the media type of a GET, with no other header noise.
curl -s -o /dev/null -w '%{content_type}\n' https://httpbin.org/jsonapplication/json%{content_type}prints the header value in full, parameters included, so an empty line here means the server sent no content type at all. - Step 2.
Read the raw header line from a different API to see a charset parameter in place.
curl -s -D - -o /dev/null https://api.github.com/repos/curl/curl | grep -i '^content-type'content-type: application/json; charset=utf-8 - Step 3.
Ask the same service for a route that fails, and read what the error path sends.
curl -s -o /dev/null -w '%{http_code} %{content_type}\n' https://httpbin.org/status/404404 text/html; charset=utf-8The success path of this host is JSON and its 404 is HTML. A client that parses every body without reading the header breaks on this route.
- Step 4.
Confirm that the type is fixed and not negotiated, by asking for something else.
curl -s -H 'Accept: application/xml' -o /dev/null -w '%{http_code} %{content_type}\n' https://httpbin.org/json200 application/jsonA service that honours
Acceptanswers with a different type here, or with406. This one ignores the header, which is worth writing down before a client team assumes otherwise. - Step 5.
Compare what a HEAD request reports with the GET from step 1.
curl -sI https://httpbin.org/json | grep -i '^content-type'content-type: application/jsonThe two agree here. A HEAD and a GET that disagree mean two code paths answer the route, and the one your client uses is the GET.
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| application/json | The type a JSON client expects | Nothing. Confirm the error routes send the same. |
| application/json; charset=utf-8 | Correct type, redundant parameter | Harmless. RFC 8259 defines no charset for this media type. |
| text/html; charset=utf-8 on an API route | HTML came back, most likely an error page | Read the status code, then parse the body to see who wrote it. |
| text/plain on a JSON route | The type was never set, so a default applied | Set it in the handler. Browser clients that filter on type drop this response. |
| An empty value | No content-type header at all | Browsers sniff the body, and X-Content-Type-Options: nosniff then blocks it. |
Thresholds
Common mistakes
What to check next
- How to check if API returns valid JSON: the header is a claim, the parse is the proof.
- How to check HTTP response headers with curl: read the whole header block in one pass instead of one line at a time.
- How to check X-Content-Type-Options: what happens to a wrong or missing type once nosniff is in play.
- How to validate JSON against schema: the contract that applies after the type and the parse both hold.
FAQ
How to check the content type of a response in the browser?
Open DevTools, Network tab, click the request, then the Headers panel and read Response Headers. The Type column in the request list shows a normalised label, not the header, so it hides text/plain served for JSON.
Should application/json carry charset=utf-8?
It is not required. RFC 8259 registers no charset parameter for the media type and mandates UTF-8 for interchange. Sending it is harmless, and removing it from an existing API is not worth a release on its own.
Why does my API return text/html only sometimes?
Because a different layer answered. Reverse proxies, WAFs and framework error pages write their own bodies with their own defaults. Compare the status code from step 3 with the one your handler intends to send.
Does content-type change what the server parses on a request?
It changes what the server parses on the way in, which is the request content type, a separate header of the same name. This procedure reads the response side only. Send Content-Type: application/json on POST bodies and check that route separately.
Verified
Verified by Maks Vernycurl 8.21.0
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
basic3 minpublished updated Maks Verny