Skip to main content

HTTP Requests, Headers, Cookies, Sessions, and Tokens

Introduction #

REST APIs are built on top of HTTP, so understanding HTTP makes APIs much easier to reason about.

HTTP is a client-server protocol. The client starts the conversation by sending a request, and the server answers with a response. A browser, mobile app, command-line tool, IoT device, or another backend service can all act as HTTP clients.

At a high level, the flow looks like this:

  1. The client sends an HTTP request.
  2. The server reads the request.
  3. The server performs the required action.
  4. The server sends back an HTTP response.
  5. The client interprets the response.

That response might become a web page, JSON data, an image, a file download, or some other kind of content.

HTTP Is Stateless #

HTTP is stateless by default. This means each request is treated as a separate event.

If you log in to a website and then refresh the page, HTTP does not automatically remember that you already logged in. Without some extra mechanism, the server would need your username and password again on every request.

That would be a terrible experience, so web applications use tools like cookies, sessions, and tokens to remember who you are between requests.

Anatomy of an HTTP Request #

An HTTP request is a text-based message sent from the client to the server. It usually contains:

  • A request line
  • Request headers
  • An optional request body

The request line is the first line of the request. It contains the HTTP method, the resource being requested, and the HTTP version.

For example:

1
GET /account HTTP/1.1

This means:

  • GET is the HTTP method.
  • /account is the resource path.
  • HTTP/1.1 is the HTTP version.

Another example:

1
POST /login HTTP/1.1

This means the client wants to send data to the /login endpoint.

Common HTTP Methods #

HTTP methods describe the kind of action the client wants to perform.

Some common methods are:

  • GET retrieves data.
  • POST sends new data.
  • PUT replaces existing data.
  • PATCH partially updates existing data.
  • DELETE removes data.

In a REST API, these methods help describe actions on resources. For example, GET /users/10 might retrieve a user, while DELETE /users/10 might delete that user.

HTTP Headers #

Headers are metadata about an HTTP request or response. They give extra information without being the main content itself.

Headers are written as name-value pairs:

1
2
3
Accept: application/json
User-Agent: Mozilla/5.0
Authorization: Bearer eyJhbGciOi...

Request headers are sent by the client. They can tell the server things like:

  • What content type the client accepts
  • What browser or client is making the request
  • What language the client prefers
  • Whether the client has authentication information
  • Whether the client has cookies for this website

For example:

1
2
3
4
GET /profile HTTP/1.1
Host: example.com
Accept: application/json
Cookie: sessionId=abc123

Here, the client is asking for /profile, saying it accepts JSON, and sending a cookie named sessionId.

HTTP Responses #

After the server receives and processes a request, it sends an HTTP response.

A response usually contains:

  • A status line
  • Response headers
  • An optional response body

Example:

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: sessionId=abc123; HttpOnly; Secure

{
  "name": "John",
  "loggedIn": true
}

The status code tells the client what happened.

Common status codes include:

  • 200 OK: The request succeeded.
  • 201 Created: A new resource was created.
  • 400 Bad Request: The request was invalid.
  • 401 Unauthorized: Authentication is required or failed.
  • 403 Forbidden: The client is authenticated but not allowed.
  • 404 Not Found: The resource does not exist.
  • 500 Internal Server Error: Something went wrong on the server.

Cookies #

A cookie is a small piece of data stored by the browser for a specific website.

Cookies are useful because browsers automatically send them back to the same website on future requests. This makes them convenient for remembering state, especially login state.

Cookies are exchanged using HTTP headers:

  • The server sends cookies using the Set-Cookie response header.
  • The browser sends cookies back using the Cookie request header.

For example, after a successful login, the server might respond with:

1
Set-Cookie: sessionId=abc123; Expires=Wed, 29 Apr 2026 12:00:00 GMT; HttpOnly; Secure

The browser stores that cookie. On the next request to the same website, the browser automatically sends:

1
Cookie: sessionId=abc123

This is how the server can recognize that the request belongs to a previously logged-in user.

Cookies can be temporary or long-lived.

If a cookie has an expiration time, the browser keeps it until that time is reached. After it expires, the browser removes it and stops sending it with requests.

For authentication, expiration is important. A banking site may use a short session lifetime for security, while a social media site may keep users signed in for much longer.

Cookie lifetime is controlled with attributes such as:

  • Expires
  • Max-Age

For example:

1
Set-Cookie: sessionId=abc123; Max-Age=1200

This tells the browser to keep the cookie for 1200 seconds.

Sessions #

A session is server-side state that represents an active interaction between a client and a server.

In a typical session-based login flow:

  1. The user submits a username and password.
  2. The server validates those credentials.
  3. The server creates a session record in a database or session store.
  4. The server sends the browser a cookie containing a session ID.
  5. The browser sends that session ID cookie on future requests.
  6. The server looks up the session ID and decides whether the user is still logged in.

The important detail is that the browser usually does not store the full session data. It only stores the session ID.

The actual session information stays on the server. That might include:

  • The user ID
  • Login time
  • Last activity time
  • Session expiration time
  • Permission or role information

This is safer than trusting the client with important data. The client can modify cookies, so the server should always validate cookie values before trusting them.

Logout and Session Expiry #

When a user logs out, two things usually happen:

  1. The server invalidates the session in the session store.
  2. The server tells the browser to remove the session cookie.

Even if the browser still has an old cookie, it becomes useless once the server-side session has expired or been deleted.

This is why the session ID itself should be random, hard to guess, and meaningless on its own. It is only useful if the server has a valid matching session.

Tokens #

Tokens are another way to handle authentication and authorization.

A token is often used when multiple systems are involved, such as when a mobile app or third-party application needs access to an API. Instead of giving the third-party app your password, you authenticate with the trusted service and the app receives a token with limited access.

Tokens are commonly sent with the Authorization header:

1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

A token can represent:

  • Who the user is
  • What the client is allowed to access
  • When the token was issued
  • When the token expires
  • What scopes or permissions were granted

OAuth, OpenID Connect, and JSON Web Tokens are common terms you will see around token-based authentication.

JSON Web Tokens #

A JSON Web Token, or JWT, is a common token format.

A JWT can contain claims such as:

  • User ID
  • Issuer
  • Audience
  • Expiration time
  • Granted scopes

JWTs are signed, which means the receiver can verify that the token was issued by a trusted party and has not been modified.

Signing does not automatically mean the token is encrypted. In many cases, the contents of a JWT can be decoded by anyone who has the token. The signature protects integrity, not secrecy.

Because of that, sensitive information such as passwords should not be placed inside a normal JWT.

Cookies vs Sessions vs Tokens #

Cookies, sessions, and tokens are related, but they are not the same thing.

A cookie is a browser storage and transport mechanism. It stores small values and automatically sends them with requests to the matching website.

A session is server-side state. The server stores the real session information and gives the browser a session ID, often inside a cookie.

A token is a credential-like value that can be sent to an API. Tokens often work well for mobile apps, third-party integrations, and API-to-API communication.

Here is a simple comparison:

Concept Where It Lives How It Is Sent Common Use
Cookie Browser Cookie header Store small website-specific values
Session Server Session ID often sent in a cookie Keep a user logged in to a website
Token Client Often Authorization header API access and delegated permissions

Example Login Flow With Cookies and Sessions #

Imagine logging in to a banking website.

First, the browser sends credentials:

1
2
3
4
5
6
7
8
POST /login HTTP/1.1
Host: bank.example
Content-Type: application/json

{
  "username": "john",
  "password": "correct-password"
}

The server checks the credentials. If they are valid, it creates a session and sends back a session cookie:

1
2
3
4
5
6
HTTP/1.1 200 OK
Set-Cookie: sessionId=7f9a2c...; HttpOnly; Secure; SameSite=Lax

{
  "message": "Login successful"
}

On the next page request, the browser sends the cookie automatically:

1
2
3
GET /account HTTP/1.1
Host: bank.example
Cookie: sessionId=7f9a2c...

The server reads the session ID, checks whether the session is valid, and then returns the account page or API response.

Example API Flow With Tokens #

Now imagine a budgeting mobile app that needs permission to read bank transactions.

Instead of giving the app your banking password, the flow might look like this:

  1. The app redirects you to the bank’s login page.
  2. You log in directly with the bank.
  3. The bank asks whether you want to allow the app to read transactions.
  4. You approve limited access.
  5. The app receives an access token.
  6. The app sends that token to the bank API when requesting transaction data.

The API request might look like this:

1
2
3
GET /transactions HTTP/1.1
Host: api.bank.example
Authorization: Bearer eyJhbGciOi...

The token can be limited so the app can read transactions but cannot transfer money or change account settings.

Security Notes #

Authentication data needs careful handling.

Use these principles as a starting point:

  • Use HTTPS so cookies, tokens, and credentials are encrypted in transit.
  • Use HttpOnly cookies when JavaScript does not need to read the cookie.
  • Use Secure cookies so they are only sent over HTTPS.
  • Use SameSite cookies to reduce some cross-site request risks.
  • Keep session IDs random and hard to guess.
  • Do not store passwords or sensitive personal data in cookies.
  • Do not trust cookie values just because the browser sent them.
  • Give tokens the smallest permissions they need.
  • Set expiration times for both sessions and tokens.
  • Provide a way to revoke sessions and tokens.

Summary #

HTTP works through a request and response flow. The client asks for something, and the server replies.

Headers carry metadata about those messages. Request headers tell the server more about the client and the request. Response headers tell the client more about the server’s answer.

Cookies allow browsers to store small values and automatically send them back to the same website. Sessions use cookies to carry a session ID while keeping the real login state on the server. Tokens are commonly used for APIs, mobile apps, and third-party access where limited and revocable permissions are important.

Once these pieces make sense, REST APIs and web authentication become much easier to understand.