Updated 10 hours ago
Every HTTP request can carry extra information beyond what the standard headers provide. Custom headers are how applications talk to themselves—passing context, tracking requests, controlling features. They're the margin notes of HTTP.
What Custom Headers Actually Do
Standard headers handle universal concerns: caching, content types, authentication. But applications have their own concerns:
- Which version of the API should handle this request?
- How do I trace this request through fifty microservices?
- Should this user see the new checkout flow?
Custom headers answer these questions:
These aren't part of any HTTP specification. They're agreements between your systems about what information to pass and how to interpret it.
The X- Prefix: A Brief History of Good Intentions
Custom headers traditionally start with "X-" to mark them as extensions:
This convention came from email headers (RFC 822) and seemed sensible—clearly distinguish custom from standard.
Then reality happened. Some "experimental" headers became so widely used they were effectively standard. X-Forwarded-For is everywhere. But it still has the X- prefix, because removing it would break everything that depends on the old name.
RFC 6648 (2012) officially deprecated the X- prefix for new headers. The recommendation now: just use descriptive names.
In practice, both conventions coexist. Legacy headers keep their X- prefix. New headers might or might not use it. The important thing is consistency within your own systems.
Request Tracing: The Killer Use Case
When a request fails at 3am in a system with fifty services, a request ID is the difference between finding the problem in minutes and searching blind through millions of log lines.
Every service logs this ID with every action:
Search for that ID and you see the entire story. The database timed out. The user service couldn't recover. The gateway returned an error. Without the ID, you'd be correlating timestamps and guessing.
The pattern is simple: generate an ID at the edge, pass it through every service, log it everywhere.
API Versioning
APIs evolve. Old clients break. Custom headers offer one solution:
The same endpoint serves different responses based on the version header. Compare this to URL versioning:
Both work. Header versioning keeps URLs cleaner. URL versioning is more visible and cacheable. Choose based on your needs, but be consistent.
Feature Flags
Headers can control which features a request sees:
This enables:
- A/B testing: Route different users to different experiences
- Gradual rollouts: Enable features for 1% of traffic, then 10%, then everyone
- Development: Test new features in production without exposing them
The server checks the flags and adjusts behavior accordingly.
Rate Limiting Information
APIs often tell clients how much capacity they have left:
Clients can throttle themselves rather than hitting limits and getting errors. GitHub's API does this extensively—the headers tell you exactly how many requests you have left and when your quota resets.
Proxy Headers: The De Facto Standards
Some custom headers are so universal they're effectively standard.
X-Forwarded-For tracks client IPs through proxy chains:
Each proxy appends the IP it received from. The leftmost is the original client.
X-Forwarded-Proto records the original protocol:
Critical when load balancers terminate TLS and forward plain HTTP to backends. Without this header, the backend thinks every request is insecure.
X-Real-IP is nginx's simpler alternative—just the original client IP:
Designing Good Custom Headers
Use clear, descriptive names:
One purpose per header:
Keep them small. Headers have practical limits (typically 8KB total). Move large data to the request body.
Handle missing headers gracefully:
CORS and Custom Headers
Browsers restrict custom headers in cross-origin requests. For your custom headers to work:
The server must explicitly allow them in preflight responses:
For clients to read custom response headers, expose them:
Without these CORS headers, browsers silently block custom header access.
Security
Headers are visible. They're logged by proxies, cached by CDNs, stored in browser history. Never put secrets in headers:
Validate everything. Custom headers are user input:
Implementation
Sending custom headers (client):
Reading custom headers (server):
Key Takeaways
- Custom headers carry application-specific metadata that standard headers don't address
- The X- prefix is deprecated for new headers but ubiquitous in existing systems
- Request IDs are essential for debugging distributed systems—generate at the edge, propagate everywhere
- X-Forwarded-* headers are effectively standard for preserving client information through proxies
- CORS requires explicit permission for custom headers in cross-origin requests
- Never put sensitive data in headers—they're logged everywhere
- Validate custom header values like any other user input
Frequently Asked Questions About Custom Headers
Was this page helpful?