---
title: "JSON Sent as text/plain"
description: "Learn how to properly parse different API response formats by checking Content-Type headers first. Avoid common parsing mistakes."
slug: "json-sent-as-textplain"
url: "https://furkanbaytekin.dev/blogs/json-sent-as-textplain"
author: "Furkan Baytekin"
category: "Software"
tags: []
published: 2025-05-05T07:23:25Z
updated: 2025-05-05T07:23:25Z
readTime: 4
cover: "https://myblogcms.furkanbaytekin.dev/uploads/cover/json-sent-as-textplain+1746296381188"
---

Once, I was working on a project at my company. There was a requirement to extract a single key from a JSON response coming from a backend API and use it in a redirect URL. Android and iOS developers used the same endpoint and completed their part without issues. But the web app I was building didn’t work.

I checked the response model. I was expecting a JSON object—but what I got wasn’t JSON at all. Or so I thought.

I dug into it and opened the Swagger docs. Turns out, the response *was* valid JSON—but the `Content-Type` was set to `"text/plain"` instead of `"application/json"`. I asked the mobile devs how they handled it. They said they always parse the response manually, regardless of the `Content-Type`.

But in the frontend world, we don’t just `JSON.parse()` everything. We rely on the response headers to determine the format. If the header says it's plain text, we treat it as plain text.

I begged the backend dev to change the `Content-Type` to `"application/json"`—and they did.

---

## When & How to Parse API Responses

APIs can return responses in many formats: JSON, XML, HTML, plain text, SGML, etc. You **must not** assume the format based on the content. Always check the **`Content-Type`** header first.

Here’s a simple guide:

| Content-Type     | Description  |
| ---------------- | ------------ |
| application/json | JSON data    |
| application/xml  | XML data     |
| text/plain       | Plain text   |
| text/html        | HTML content |
| text/sgml        | SGML content |

All the following examples are meant to be used **inside async functions**, since most fetch methods return Promises.

---

## ✅ JSON

If `Content-Type` is not `application/json`, do not treat the response as JSON.

```json
{
  "name": "John",
  "age": 30
}
```

```javascript
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();
  console.log(data.name); // John
}
```

---

## ✅ XML

Client-side:

```xml
<note>
  <to>Furkan</to>
  <from>ChatGPT</from>
  <message>Hello!</message>
</note>
```

```javascript
const response = await fetch('https://api.example.com/data');
const text = await response.text();

const parser = new DOMParser();
const xmlDoc = parser.parseFromString(text, "application/xml");

const to = xmlDoc.getElementsByTagName("to")[0].textContent;
console.log(to); // Furkan
```

Server-side (Node.js):

```javascript
const xml2js = require('xml2js');

const response = await fetch('https://api.example.com/data');
const text = await response.text();

xml2js.parseString(text, (err, result) => {
  if (err) throw err;
  console.log(result.note.to[0]); // Furkan
});
```

---

## ✅ HTML

```html
<p>Hello!</p>

<figure>
  <img src="https://example.com/image.jpg" alt="Example Image">
  <figcaption>Example Image</figcaption>
</figure>

<p>This is an example article.</p>
```

We assume there’s an `<article>` element in the DOM and insert the content there:

```javascript
const response = await fetch('https://api.example.com/html');
const htmlDoc = await response.text();

const article = document.querySelector('article');
article.innerHTML = htmlDoc;
```

---

## ✅ Plain Text

```text
You've got mail!
```

```javascript
const response = await fetch('https://api.example.com/message');
const text = await response.text();

const box = document.getElementById('message-box');
box.textContent = text;
```

---

## ✅ SGML

SGML is rare on the web today. But if the server sends `Content-Type: text/sgml`, it should be parsed accordingly.

Example content:

```sgml
<!DOCTYPE note SYSTEM "note.dtd">
<note>
  <to>Furkan</to>
  <from>ChatGPT</from>
  <message>Hello!</message>
</note>
```

There’s no native browser support for parsing SGML, so you'd need a third-party parser on the server side. This example is illustrative only:

```javascript
const sgml2js = require('sgml2js');

const response = await fetch('https://api.example.com/sgml');
const sgmlText = await response.text();

const sgmlDoc = sgml2js.parse(sgmlText);

console.log(sgmlDoc.note.to[0]); // Furkan
```

---

## 🔚 Conclusion

Never parse a response without checking its `Content-Type` first. That header tells you how to treat the body.

If you want to parse the response as a certain format, make sure the backend sends the correct content type. Otherwise, you're just guessing—and your app might break silently.

---

**Album of the day:**

<iframe style="border-radius:12px" src="https://open.spotify.com/embed/album/2EJIGjaVFq9PKinjyA9yOn?utm_source=generator" width="100%" height="152" frameBorder="0" allowfullscreen="" allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy"></iframe>
