Skip to main content

Command Palette

Search for a command to run...

HTTP Status Codes & Headers – Understanding API Communication

Updated
6 min readView as Markdown

Over the past few days, I've learned how JavaScript communicates with APIs using the Fetch API.

Today, I went deeper into what actually comes back from an HTTP request.

I explored HTTP status codes, request headers, response headers, and response properties.

These concepts are important because an API response isn't just about the data—it also tells us whether the request succeeded, failed, was redirected, or needs further action.

Let's dive in.


What is an HTTP Status Code?

An HTTP status code is a number returned by a server that tells us what happened with a request.

For example:

200

usually means the request was successful.

Status codes are divided into categories.

Range Meaning
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error

2xx – Success

These status codes generally indicate that the request was successfully processed.

200 – OK

The request was successful.

200 OK

Commonly returned for successful GET requests.


201 – Created

The server successfully created a new resource.

This is commonly associated with successful POST requests.

201 Created

204 – No Content

The request succeeded, but the server doesn't return a response body.

204 No Content

This is commonly seen with operations where there's nothing to return.


3xx – Redirection

These status codes indicate that further action may be needed to complete the request.

Examples include:

301
302
304

For example:

301 – Moved Permanently

The requested resource has permanently moved to another URL.

304 – Not Modified

The cached version can be used because the resource hasn't changed.


4xx – Client Errors

These generally indicate that something is wrong with the request or the client's access.


400 – Bad Request

The server couldn't understand or process the request.

400 Bad Request

For example, the request might contain invalid data.


401 – Unauthorized

Authentication is required or the provided authentication credentials are not valid.

401 Unauthorized

403 – Forbidden

The server understood the request but refuses to allow it.

403 Forbidden

404 – Not Found

The requested resource couldn't be found.

404 Not Found

This is one of the most common errors you'll encounter while working with APIs.


5xx – Server Errors

These indicate that something went wrong on the server side.

500 – Internal Server Error

The server encountered an unexpected problem.

500 Internal Server Error

Other examples include:

502 Bad Gateway
503 Service Unavailable

Checking Status With Fetch

When using fetch(), we can access the status code through:

const response = await fetch(
    "https://jsonplaceholder.typicode.com/users"
);

console.log(response.status);

We can also check:

console.log(response.ok);

response.ok is true for successful HTTP responses in the 200–299 range.


Why response.ok Matters

One important thing I learned is that fetch() does not automatically reject its Promise just because the server returns a 4xx or 5xx response.

For example:

const response = await fetch(
    "https://example.com/not-found"
);

console.log(response.status);

We should explicitly check the response:

if (!response.ok) {
    throw new Error(
        `Request failed: ${response.status}`
    );
}

This makes error handling much more reliable.


What are HTTP Headers?

Headers contain additional information about an HTTP request or response.

Think of them as metadata describing the communication.

There are two major types:

  • Request headers

  • Response headers


Request Headers

Request headers are sent from the client to the server.

For example:

const response = await fetch(
    "https://example.com",
    {
        headers: {
            "Content-Type": "application/json"
        }
    }
);

The server can use this information to understand how the request should be interpreted.


Content-Type

One of the most common headers is:

Content-Type

For JSON requests:

headers: {
    "Content-Type": "application/json"
}

This tells the server that the request body contains JSON.


Authorization Header

APIs often require authentication.

A request might contain an authorization header such as:

headers: {
    "Authorization": "Bearer YOUR_TOKEN"
}

The exact authentication mechanism depends on the API.

Private API keys and tokens should not be exposed in frontend code when the API design requires them to remain secret.


Response Headers

Servers also send headers back to the client.

We can access them through:

const response = await fetch(
    "https://jsonplaceholder.typicode.com/users"
);

console.log(response.headers);

Getting a Specific Response Header

We can use .get():

console.log(
    response.headers.get("content-type")
);

This allows us to inspect specific response metadata.


Response Properties

A Fetch API response contains several useful properties.

For example:

console.log(response.status);
console.log(response.ok);
console.log(response.url);
console.log(response.headers);

These give us information about the response.


Reading Response Data

After checking the response, we can read its body.

For JSON:

const data = await response.json();

console.log(data);

For plain text:

const text = await response.text();

console.log(text);

The appropriate method depends on the response format.


Building Better Error Handling

Now we can combine everything we've learned.

async function getUsers() {

    try {

        const response = await fetch(
            "https://jsonplaceholder.typicode.com/users"
        );

        if (!response.ok) {
            throw new Error(
                `HTTP Error: ${response.status}`
            );
        }

        const data = await response.json();

        console.log(data);

    } catch (error) {

        console.error(
            "Request failed:",
            error.message
        );

    }
}

getUsers();

Now our application can distinguish between a successful response and an unsuccessful HTTP response.


HTTP Communication Flow

The complete communication process now looks like:

Frontend
   │
   │ Request
   │ Headers + Body
   ↓
Server / API
   │
   │ Response
   │ Status + Headers + Body
   ↓
Frontend

The response isn't just data.

It contains:

Status + Headers + Body

Understanding this makes API communication much easier to reason about.


Best Practices

✔ Always check response.ok when handling API requests.

✔ Use appropriate HTTP status codes when building APIs.

✔ Use headers to communicate metadata between client and server.

✔ Don't expose private credentials or secrets in frontend JavaScript.

✔ Handle both network errors and unsuccessful HTTP responses.

✔ Don't assume every successful response contains JSON.


My Biggest Takeaway

Today, I learned that an API response contains much more than just the data I'm trying to retrieve.

The server communicates important information through:

Status Codes + Headers + Response Body

Understanding status codes also makes debugging much easier.

If I see a 404, I know I'm dealing with a missing resource. If I see a 401, I know authentication is involved. If I see a 500, the problem is generally on the server side.

1 views

100 Days of Code: My Journey to Becoming a Full Stack Developer

Part 47 of 50

Welcome to my 100 Days of Code journey! In this series, I'll document my daily progress as I learn Full Stack Web Development from the ground up. Every post will cover what I learned, challenges I faced, mistakes I made, and the projects I built. My goal is not just to complete 100 days but to become a better developer through consistency, discipline, and learning in public. Topics I'll cover include: • Git & GitHub • HTML, CSS & JavaScript • React.js • Node.js & Express • MongoDB • APIs • Real-world Projects • AI tools for Developers Whether you're just starting out or revising your fundamentals, I hope this journey helps you learn alongside me. Let's build, learn, and grow together! 🚀

Up next

Promises in JavaScript – Handling Asynchronous Operations

Over the past few days, I've been learning how JavaScript communicates with APIs using the Fetch API. Today, I went deeper into one of the concepts that makes this possible—Promises. Promises provide

More from this blog

T

TheSaurceCode

73 posts

Documenting my journey to becoming a Full Stack Developer through daily blogs, coding challenges, projects, tutorials, and lessons learned. Learn, build, and grow with me