Flask
Python
HTTP Headers
Web Development
Tutorial

How to get http headers in flask?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In Flask, incoming HTTP headers are available through the request object. Accessing them is simple, but using them correctly matters because headers are central to authentication, tracing, content negotiation, and proxy-aware request handling.

The practical rule is to read headers through request.headers, validate anything important, and avoid trusting client-supplied values blindly. That gives you code that works both in local testing and behind real reverse proxies.

Read Headers With request.headers

Flask exposes request headers as a case-insensitive mapping:

python
1from flask import Flask, request, jsonify
2
3app = Flask(__name__)
4
5
6@app.get("/headers")
7def headers():
8    user_agent = request.headers.get("User-Agent")
9    content_type = request.headers.get("Content-Type")
10
11    return jsonify({
12        "user_agent": user_agent,
13        "content_type": content_type,
14    })

Using .get() is preferable to direct indexing because missing headers are common and should not usually raise an exception.

If you need to inspect everything during debugging, convert the header mapping to a normal dictionary:

python
@app.get("/headers/all")
def all_headers():
    return jsonify(dict(request.headers))

That is useful when debugging client libraries, proxies, or webhook calls.

Handle Common Header Use Cases

Header access becomes more useful when tied to real behaviors.

Authorization:

python
1@app.get("/secure")
2def secure():
3    auth = request.headers.get("Authorization")
4    if not auth:
5        return jsonify({"error": "missing authorization header"}), 401
6
7    return jsonify({"message": "header received"})

Language preference:

python
1@app.get("/hello")
2def hello():
3    lang = request.headers.get("Accept-Language", "en")
4    greeting = "Bonjour" if lang.startswith("fr") else "Hello"
5    return jsonify({"greeting": greeting})

Request tracing:

python
1@app.get("/trace")
2def trace():
3    request_id = request.headers.get("X-Request-ID", "generated-fallback-id")
4    return jsonify({"request_id": request_id})

These examples show the normal pattern: read the header, validate it if necessary, and convert it into application logic.

Validate Important Headers

Headers come from the client, so treat them as untrusted input unless they are inserted by a trusted gateway. A small validation helper keeps the rules clear:

python
1from flask import jsonify, request
2
3
4def require_api_key():
5    key = request.headers.get("X-API-Key")
6    if not key:
7        return None, (jsonify({"error": "X-API-Key required"}), 400)
8
9    if len(key) < 20:
10        return None, (jsonify({"error": "invalid key format"}), 401)
11
12    return key, None

This is especially important for custom headers that affect authorization or routing decisions.

Think About Reverse Proxies

In production, Flask often sits behind Nginx, Apache, a cloud load balancer, or an API gateway. That means some headers may be rewritten, added, or forwarded by infrastructure.

For example, values such as X-Forwarded-For or X-Forwarded-Proto should only be trusted when the proxy setup is known and controlled. If you need Flask to understand those forwarded values, configure proxy middleware explicitly:

python
from werkzeug.middleware.proxy_fix import ProxyFix

app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)

Do this only when your deployment topology is well defined. Otherwise you risk trusting spoofed headers from untrusted clients.

Set Response Headers Too

Many applications need not only to read request headers but also to write response headers:

python
1from flask import make_response
2
3
4@app.get("/health")
5def health():
6    response = make_response({"status": "ok"}, 200)
7    response.headers["Cache-Control"] = "no-store"
8    response.headers["X-Service-Version"] = "2026.03.11"
9    return response

This is how you add caching directives, trace metadata, or security policies to the response.

Common Pitfalls

The biggest mistake is assuming a header is always present and indexing it directly. Missing headers are normal, so .get() with validation is usually the better pattern.

Another common issue is trusting forwarded or custom identity headers from arbitrary clients. If a proxy is responsible for injecting those headers, the trust boundary needs to be explicit.

People also log sensitive headers such as authorization tokens during debugging. That can create credential leaks in logs very quickly.

Finally, do not confuse request headers with response headers. Reading from request.headers and writing to response.headers are different parts of the API.

Summary

  • Read incoming headers in Flask through request.headers.
  • Use .get() so missing headers are handled safely.
  • Validate headers that affect authentication, routing, or business logic.
  • Treat proxy-forwarded headers carefully and only trust them in controlled deployments.
  • Set response headers explicitly when you need caching, tracing, or security metadata.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.