๐ŸŽ‰ Premium Proxies ยท 3-Day Free TrialClaim Now โ†’
Proxy Basic

Proxy Headers: X-Forwarded-For & What They Reveal

Proxy headers like X-Forwarded-For, Via, and Forwarded (RFC 7239) reveal client IPs. See what each header exposes, spoofing risks, and how to strip them.

S SparkProxy 20 21 min read
Share
Proxy Headers: X-Forwarded-For & What They Reveal

Every time a request travels through a proxy, load balancer, or CDN, the origin server loses sight of who actually sent it. The TCP connection arrives from the proxy's IP address, not the client's. Proxy headers solve this: they carry the original client IP and other request context across intermediaries so your application can act on accurate data.

The most widely used is X-Forwarded-For. But it's one piece of a larger picture. The Forwarded header standardized by RFC 7239, the X-Real-IP shorthand common in Nginx setups, the Via hop-by-hop indicator, and the X-Forwarded-Proto / X-Forwarded-Host pair each carry different information and behave differently under attack conditions.

If you're building rate limiters, enforcing geo-based access controls, running a reverse proxy setup, or analyzing traffic through a proxy network, you need to know exactly what each header does, which one to trust, and where the security traps are.

Key Takeaways

  • X-Forwarded-For is a de facto standard (not an IETF spec) and any client can forge it before your proxy appends its hop, making the leftmost IP untrustworthy for access control (OWASP WSTG, 2023).
  • RFC 7239's Forwarded header (IETF, 2014) is the standardized replacement with structured syntax and IP obfuscation support.
  • Trust only the rightmost IP added by a proxy you control, never the leftmost value sent by the client.

What Are HTTP Proxy Headers?

HTTP proxy headers are request headers added or modified by intermediary nodes (proxies, load balancers, CDNs, gateways) as a request travels from a client to an origin server. According to Mozilla's MDN Web Documentation (MDN, 2024), X-Forwarded-For is now present in virtually every production web stack that sits behind a reverse proxy, making it one of the most commonly processed HTTP headers in existence. Without proxy headers, your application can't identify the real user from a proxied connection.

Without them, your application can't:

  • Enforce per-user rate limiting without blocking the proxy's shared IP
  • Apply accurate geo-restrictions or routing rules
  • Log real visitor IPs for analytics and security investigation
  • Feed IP reputation systems with accurate source data

There are two functional categories:

CategoryHeadersPurpose
Client IP forwarding`X-Forwarded-For`, `X-Real-IP`, `Forwarded`Pass original client address through intermediaries
Request metadata`Via`, `X-Forwarded-Proto`, `X-Forwarded-Host`, `X-Forwarded-Port`Preserve protocol, hostname, and port context

Which headers arrive at your origin depends entirely on how each proxy in your chain is configured. That variability is the source of both flexibility and risk.

According to MDN Web Docs, X-Forwarded-For became a de facto standard after widespread adoption by proxies like Squid starting in the early 2000s. It remains the most universally supported IP-forwarding mechanism, present in Nginx, Apache, HAProxy, Cloudflare, and AWS ALB deployments without a formal IETF specification until RFC 7239 addressed it in 2014 (MDN Web Docs, 2024).

See how an IP address identifies a client before and after it passes through these intermediary chains.

Proxy Header Reference Table: What Each Header Reveals

Use this table as a quick reference for the six headers that carry proxy and client context. Each one exposes different information, and how much of it actually leaks depends on the proxy's anonymity level.

HeaderStandardWhat it revealsAnonymity impact
`X-Forwarded-For`De facto (pre-RFC 7239)Original client IP plus every proxy hop, as a left-to-right comma listCarries your real IP on a transparent proxy; an elite proxy omits it
`X-Real-IP`Nginx conventionA single resolved client IP, no chainPresent on transparent and some anonymous setups; absent on elite proxies
`Via`Standard (RFC 9110)Proxy software name and HTTP version at each hop, but no IPSignals a proxy is in use even when the IP is hidden; elite proxies suppress it
`Forwarded` (RFC 7239)IETF standard`for`, `by`, `host`, and `proto` in one line, with optional IP obfuscationCan expose or obfuscate the client IP; elite proxies leave it off entirely
`X-Forwarded-Proto`De factoOriginal scheme (`http` or `https`) before TLS terminationMetadata only, not used to classify anonymity
`X-Forwarded-Host`De factoOriginal `Host` header before a proxy rewrote itMetadata only, not used to classify anonymity

How Anonymity Levels Change What Leaks

The same proxy software can expose or hide your address depending on how it handles these headers. Server-side classification falls into three levels:

  • Transparent (Level 3): forwards X-Forwarded-For with your real IP and usually adds Via. The origin server knows you are proxied and sees your actual address.
  • Anonymous (Level 2): adds proxy-identifying headers like Via, but replaces or drops your real IP. The server knows a proxy sits in front of it, yet cannot read your client address.
  • Elite (Level 1): sends none of the proxy-identifying headers. The request looks like a direct connection, with no X-Forwarded-For, Via, or Forwarded at all.

Here is what an origin server actually receives at each level for the same client. Assume the real client IP is 203.0.113.45 and the proxy IP is 198.51.100.10.

Transparent proxy:

GET /api/data HTTP/1.1
Host: sparkproxy.io
X-Forwarded-For: 203.0.113.45
X-Real-IP: 203.0.113.45
Via: 1.1 squid-proxy

Anonymous proxy:

GET /api/data HTTP/1.1
Host: sparkproxy.io
X-Forwarded-For: 198.51.100.10
Via: 1.1 squid-proxy

Elite proxy:

GET /api/data HTTP/1.1
Host: sparkproxy.io

Notice the pattern. The transparent dump leaks the real IP twice. The anonymous dump swaps in the proxy IP but still confesses an intermediary through Via. The elite dump carries nothing that identifies a proxy. For a full breakdown of how each tier is graded, read proxy anonymity levels explained.

Free trial

Scraping at scale? Skip the blocks.

Fast, unblockable datacentre proxies with unlimited bandwidth.

How Does X-Forwarded-For Work and Why Is It Risky?

X-Forwarded-For is supported by virtually every proxy and CDN vendor, making it the default mechanism for IP forwarding in production environments despite having no formal IETF specification until RFC 7239 indirectly addressed the problem in 2014 (IETF, 2014). Squid introduced the header in the early 2000s and its adoption spread quickly because it solved the real-origin-IP problem without requiring any changes to the underlying HTTP specification.

Header Format

The value is a comma-separated list of IP addresses, with each proxy appending the IP it received the request from:

X-Forwarded-For: client-ip, proxy1-ip, proxy2-ip

A real-world example with two proxy hops:

X-Forwarded-For: 203.0.113.45, 10.0.0.1

Here, 203.0.113.45 is the IP the first proxy saw from the client. 10.0.0.1 is the internal load balancer that forwarded to your origin. Each proxy in the chain appends one entry, building the list left-to-right.

Why It Exists

When your application sits behind one or more proxies, request.remote_addr or the TCP socket IP shows the proxy's address, not the user's. X-Forwarded-For gives you back the originating IP so you can:

  • Apply per-user rate limits without blocking the proxy's shared egress address
  • Log accurate visitor analytics
  • Run geo-based business logic (pricing, content delivery, compliance)
  • Feed IP reputation systems with accurate source data

The Core Problem with Leftmost IP Trust

There's no validation built into the header. A client can inject X-Forwarded-For: 192.168.1.1 before the request ever reaches your infrastructure. Your load balancer appends its own hop, and the header arrives looking like authentic chain data:

# Client sends (forged before reaching your proxy):
X-Forwarded-For: 192.168.1.1

# Your load balancer appends its own hop:
X-Forwarded-For: 192.168.1.1, 10.50.0.2

If your application reads the leftmost IP and trusts it, you've accepted forged data. The safe rule: trust only the IP your own trusted proxy added, which is the rightmost value.

IP Trust Reliability in X-Forwarded-For Chain IP Trust Reliability in X-Forwarded-For Chain Leftmost IP (client-supplied) Middle IPs (intermediate hops) Rightmost IP (your proxy) 0%: spoofable by any HTTP client ~40%: depends on chain depth 100%: controlled by you 0% 50% 100% Reliability Level
Trust level for each IP position in the X-Forwarded-For header. Only the rightmost value, added by your own proxy, is safe to trust for access control or rate limiting decisions.

Only the rightmost hop, the one your own proxy added, sits inside your trust boundary. Everything to the left of it arrived as raw client input.

What Is the Forwarded Header (RFC 7239)?

IETF published RFC 7239 in June 2014 to replace the fragmented X-Forwarded-* family with a single, formally specified header using structured key-value syntax (IETF RFC 7239, Petersson et al., 2014). It consolidates the client IP, proxy IP, original host, and protocol into one line, replacing four separate headers with one standard:

Forwarded: for=203.0.113.45;proto=https;host=example.com;by=10.0.0.1

The parameters map directly to their X-Forwarded-* equivalents:

ParameterReplacesExample
`for``X-Forwarded-For``for=203.0.113.45`
`by`Proxy IP identification`by=10.0.0.1`
`host``X-Forwarded-Host``host=example.com`
`proto``X-Forwarded-Proto``proto=https`

IPv6 addresses require quoting:

Forwarded: for="[2001:db8::1]";proto=https

RFC 7239 also supports IP obfuscation, a feature X-Forwarded-For doesn't have:

Forwarded: for=unknown;proto=https
Forwarded: for="_obfuscated-token-1";proto=https

This matters when forwarding requests through third-party systems where you need to signal that forwarding occurred without exposing the actual client IP. It's the right choice for GDPR-conscious architectures that need to log forwarding metadata without persisting real IPs.

From what we've seen across production deployments, RFC 7239 adoption has been slowest in self-hosted Nginx and Apache setups, where X-Forwarded-For defaults still dominate configuration templates. Cloud-native load balancers (Google Cloud Load Balancing, AWS ALB) support both formats, but generate X-Forwarded-For alongside Forwarded for backward compatibility rather than as a replacement. Expect transition periods to run long.

According to IETF RFC 7239 (Petersson et al., 2014), the Forwarded header was designed to consolidate and formalize the fragmented set of X-Forwarded-* headers into a single interoperable standard. The specification explicitly acknowledges that backward compatibility with X-Forwarded-For requires both headers to coexist during migration. As of 2025, most major CDNs support Forwarded but don't default to it, leaving X-Forwarded-For as the practical standard for existing deployments (IETF RFC 7239, 2014).

See how these headers map to each proxy anonymity level and what information each level exposes.

What Other HTTP Proxy Headers Should You Know?

HTTP proxy infrastructure has accumulated several headers beyond the X-Forwarded-* family. Each carries specific information the IP forwarding headers don't provide, and knowing when to use each one avoids common configuration mistakes.

X-Real-IP

X-Real-IP is an Nginx convention rather than a standard. It carries a single IP address, not a list:

X-Real-IP: 203.0.113.45

Nginx's ngx_http_realip_module populates this header after resolving the real client IP from the forwarding chain, accounting for your configured trusted proxy ranges. In single-proxy architectures, it's a convenient shorthand that avoids parsing comma-separated lists in application code.

# nginx.conf
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;

After this directive, $remote_addr becomes the resolved client IP and Nginx sets X-Real-IP for upstream applications. It doesn't work reliably across multi-proxy chains unless each layer is explicitly configured to pass it correctly.

Via

Via is a standard HTTP header defined in RFC 9110 (the consolidated HTTP semantics specification, IETF, 2022). It identifies the proxy software and HTTP version at each hop:

Via: 1.1 proxy.example.com
Via: 1.1 proxy.example.com, 1.1 cdn-node-42.cdn.example.net

Via doesn't carry IP addresses. It identifies the proxy product and version, giving you routing topology without disclosing network internals. CDN logs use it to detect caching behavior; search engine crawlers read it to understand how content was fetched. It's not useful for IP attribution, but it helps debug multi-hop routing issues and detect unexpected intermediaries in the request chain.

X-Forwarded-Proto and X-Forwarded-Host

When a load balancer terminates TLS, the origin receives HTTP internally. Without additional headers, your application sees http:// in request URLs and generates broken redirect URLs or incorrect canonical tags.

X-Forwarded-Proto passes the original scheme:

X-Forwarded-Proto: https

X-Forwarded-Host passes the original Host header when a proxy rewrites it:

X-Forwarded-Host: www.example.com

Both are required when your origin can't see the connection's TLS state directly. In Nginx, you set them explicitly:

proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host  $host;

Without X-Forwarded-Proto, Django's request.is_secure() returns False behind a TLS terminator, and Rails generates http:// canonical URLs. These configuration gaps can take hours to trace back to a missing header. The scheme a proxy forwards also depends on which proxy protocol handles the connection, since HTTP, HTTPS, and SOCKS5 terminate TLS at different points.

From the field: In multi-tenant proxy setups we've analyzed, missing X-Forwarded-Host is the most common source of confusing production bugs. The application works in direct HTTPS testing but breaks in production because the origin generates URLs based on the wrong host value. Always verify your proxy configuration includes both X-Forwarded-Proto and X-Forwarded-Host.

Proxy Header Support Matrix Across Major Platforms Proxy Header Support Matrix X-Forwarded-For Forwarded X-Real-IP X-Fwd-Proto CDN-Native IP Nginx Default Optional Module Default N/A Cloudflare Default Optional N/A Default CF-IP AWS ALB Default Optional N/A Default N/A HAProxy option Supported N/A Manual N/A Default / easily enabled Requires explicit config Not natively supported
Proxy header support across major platforms. Cloudflare's CDN-native CF-Connecting-IP header (set server-side) is more tamper-resistant than X-Forwarded-For across all platforms.

How CDNs and Load Balancers Handle These Headers

Production stacks layer headers from multiple intermediaries, and each layer follows its own defaults. Here's what actually happens at each platform.

Nginx appends to X-Forwarded-For when you include proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;. The $proxy_add_x_forwarded_for variable appends $remote_addr to any existing value, building the chain correctly. Without this directive, Nginx passes whatever the upstream sent without modification, which can result in headers being stripped or duplicated.

Cloudflare sets CF-Connecting-IP to the real visitor IP at the network edge (Cloudflare Developer Docs, 2024). This header is set by Cloudflare's infrastructure, not the client, so it can't be forged by users the way X-Forwarded-For can. Enterprise plans also receive True-Client-IP with the same value. These CDN-native headers are the right choice for IP-based decisions when you're already behind Cloudflare.

AWS Application Load Balancer always appends to X-Forwarded-For, always sets X-Forwarded-Proto to http or https, and adds X-Forwarded-Port automatically (AWS Documentation, 2024). There's no option to disable this behavior.

HAProxy requires the explicit option forwardfor directive to add X-Forwarded-For. It can also strip existing values from untrusted sources before adding its own:

option forwardfor except 0.0.0.0/0

This tells HAProxy to strip any incoming X-Forwarded-For from all sources before appending its own hop, which prevents client injection entirely.

When your stack has three or more layers (client โ†’ CDN โ†’ ALB โ†’ Nginx โ†’ app), the final header can contain three to four IP addresses. Your application needs to know exactly how many trusted proxy hops sit in front of it to extract the right IP from the chain. The number of hops also affects how proxy ports route requests across network boundaries.

According to Cloudflare's developer documentation (Cloudflare, 2024), CF-Connecting-IP is populated at the Cloudflare network edge and cannot be overridden by visitor-controlled request headers. This makes it a reliable source for the original visitor IP in all Cloudflare-protected deployments, unlike X-Forwarded-For which remains vulnerable to client-side injection unless the proxy explicitly strips pre-existing values before appending.

How Can Proxy Headers Enable IP Spoofing Attacks?

OWASP's Web Security Testing Guide (OWASP WSTG v4.2, 2023) identifies IP-based access controls that trust client-supplied proxy headers as a documented high-risk vector. The vulnerability is consistent: any HTTP client can set X-Forwarded-For before the request reaches your infrastructure, and unless your proxy strips it, the forged value becomes part of a chain that looks authentic.

The attack is two lines:

curl https://example.com/admin-panel \
  -H "X-Forwarded-For: 10.0.0.1"

If your application grants admin access to 10.0.0.1 (an internal IP), the attacker bypasses the control with zero sophistication. This class of attack is also used to impersonate trusted IPs for IP blacklist bypass and rate limit evasion.

Vulnerable pattern (do not use):

# Flask: UNSAFE
def get_real_ip():
    return request.headers.get("X-Forwarded-For", "").split(",")[0].strip()

Safe pattern with known proxy count:

# Flask: SAFE
def get_real_ip(request, trusted_proxy_count=1):
    xff = request.headers.get("X-Forwarded-For", "")
    ips = [ip.strip() for ip in xff.split(",") if ip.strip()]
    if len(ips) > trusted_proxy_count:
        return ips[-(trusted_proxy_count + 1)]
    return request.remote_addr  # fall back to direct TCP connection IP

The same principle applies in Node.js (Express trust proxy setting), PHP (Laravel TrustedProxies middleware), and Go (net/http reverse proxy handling).

Additional hardening steps:

  • Strip at the edge. Configure your outermost proxy to delete any incoming X-Forwarded-For before adding its own. In HAProxy: http-request del-header X-Forwarded-For placed before option forwardfor.
  • Use CDN-native headers. Behind Cloudflare, trust CF-Connecting-IP instead of X-Forwarded-For.
  • Validate IP format before use. A malformed string in X-Forwarded-For can cause unexpected parsing behavior in downstream code. Validate that extracted values match IPv4 or IPv6 format before acting on them.
  • Log the full chain for forensics. Don't log only the resolved IP. Keep the full X-Forwarded-For value for security investigations.

Spoofed headers also corrupt IP reputation scoring by letting bad-faith traffic impersonate known-clean IP addresses, which is why stripping at the edge matters beyond just your own application.

A common mistake in Express.js is setting app.set('trust proxy', true) rather than specifying a CIDR. The boolean true trusts all proxies in the chain, which restores the spoofing vulnerability the setting is supposed to prevent. Always use app.set('trust proxy', '10.0.0.0/8') with explicit trusted ranges.

How Do You Read Proxy Headers Safely in Your Application?

Once you understand the trust model, reading the right IP is a matter of framework configuration. Most frameworks let you declare trusted proxies so they resolve the correct IP automatically without requiring custom header-parsing logic.

Node.js (Express):

// Declare your trusted proxy CIDR. Don't use true, which trusts everything.
app.set('trust proxy', '10.0.0.0/8');

// Express resolves req.ip to the correct client IP automatically
const clientIp = req.ip;

Python (Django):

# settings.py: required for HTTPS detection behind TLS terminator
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST    = True

# views.py: REMOTE_ADDR is rewritten by Django's security middleware
def view(request):
    client_ip = request.META.get('REMOTE_ADDR')

PHP (Laravel):

// app/Http/Middleware/TrustProxies.php
protected $proxies = ['10.0.0.0/8'];
protected $headers = Request::HEADER_X_FORWARDED_FOR
                   | Request::HEADER_X_FORWARDED_HOST
                   | Request::HEADER_X_FORWARDED_PORT
                   | Request::HEADER_X_FORWARDED_PROTO;

// Controller: resolves correctly once TrustProxies is active
$clientIp = $request->ip();

The pattern across all frameworks: declare which IP ranges are trusted proxies, then let the framework subtract trusted hops from the end of the chain. Don't write your own leftmost-IP extraction logic.

Want to understand how a transparent proxy modifies requests differently from anonymous proxies? The header behavior changes significantly depending on proxy type.

Our finding: When analyzing production multi-proxy stacks, we've consistently found that most IP extraction bugs trace back to one of two misconfiguration patterns: (1) reading the leftmost X-Forwarded-For IP without stripping edge-injected values, or (2) trusting app.set('trust proxy', true) in Express, which accepts all forwarded IPs rather than a specific trusted range. Both fixes take under 10 minutes to implement.

How Do You Inspect and Strip Proxy Headers?

Before you trust or block anything, confirm what your stack actually adds. Two tasks cover most of it: inspecting the headers that reach an origin, and stripping the ones you don't want forwarded.

Inspecting the headers a proxy sends

Route a request through your proxy to a header-echo endpoint and read what comes back:

# Send through your proxy, then echo the request headers the endpoint saw
curl -x http://user:pass@proxy.sparkproxy.io:8080 \
     https://httpbin.org/headers

The JSON response lists every header the endpoint received, including any X-Forwarded-For, Via, or Forwarded your proxy injected. Run the same request without the -x flag and compare the two. Anything present only in the proxied response is something your proxy added. An elite proxy shows no proxy-identifying headers at all; a transparent one hands over your real IP in X-Forwarded-For.

On the server side, log the raw chain so you can audit what production really receives:

# nginx.conf: log the full forwarding chain for auditing
log_format proxy_debug '$remote_addr xff="$http_x_forwarded_for" '
                       'via="$http_via" real="$http_x_real_ip"';
access_log /var/log/nginx/proxy_debug.log proxy_debug;

Stripping proxy headers

Whether you strip headers to harden access control or to raise proxy anonymity, it is one directive per platform:

PlatformStrip incoming `X-Forwarded-For`
Nginx`proxy_set_header X-Forwarded-For "";`
Apache`RequestHeader unset X-Forwarded-For`
HAProxy`http-request del-header X-Forwarded-For`
CloudflareTransform Rule, remove header `X-Forwarded-For`

Strip at your outermost edge to defeat client injection, then let your trusted proxy append a clean value. To hide that a proxy is involved at all, drop Via, X-Forwarded-For, and Forwarded together. That combination is exactly what an elite proxy does by default, which is why the request reads as a direct connection.


Conclusion

Proxy headers are the connective tissue between a client, its intermediaries, and your origin server. X-Forwarded-For handles the job in most deployments, but its informal origins mean it carries real security risks when misconfigured. RFC 7239's Forwarded header is the direction the standard points, though the transition will take years.

The practical rules to keep in mind:

  • Read the rightmost IP your trusted proxy added, not the leftmost client-supplied value
  • Strip incoming X-Forwarded-For at your outermost edge before appending your own
  • Use CDN-native headers (CF-Connecting-IP) when you're already behind a CDN
  • Adopt Forwarded (RFC 7239) for new infrastructure that needs IP obfuscation
  • Always validate extracted IPs before using them in access decisions or rate limiting

Understanding what's in these headers, and what isn't, keeps your rate limiting, geo-logic, and security controls accurate regardless of how many proxy hops sit in front of your application.

Frequently asked questions

X-Forwarded-For is a de facto standard introduced by Squid with a comma-separated IP list and no formal IETF specification until 2014. Forwarded is the IETF standard (RFC 7239) with structured key-value syntax that consolidates client IP, proxy IP, host, and protocol in one header, plus adds IP obfuscation support. Most infrastructure still defaults to X-Forwarded-For due to its 20-year adoption head start.

Not without verifying which IP came from a proxy you control. Any client can inject a value at the leftmost position before your proxy appends its hop. The safe approach: read the rightmost IP your trusted proxy added, or use a CDN-native header like Cloudflare's CF-Connecting-IP that clients cannot set. Working code examples are in the IP spoofing section above.

Via identifies the proxy software and HTTP version at each hop (e.g., 1.1 nginx), not IP addresses. It shows routing topology and proxy product identity without disclosing network internals. It's defined in RFC 9110 as a standard hop-by-hop header, unlike the non-standard X-Forwarded-For. Use Via for debugging routing paths; use X-Forwarded-For for IP attribution.

Yes. The header carries real client IP addresses in plain text across the entire intermediary chain. If you forward requests through third-party services, RFC 7239's Forwarded header lets you obfuscate IPs using for=unknown or a pseudonymous token, a capability X-Forwarded-For doesn't have. For GDPR-sensitive architectures, Forwarded with obfuscation is the appropriate choice.

Configure your proxy to strip the header before forwarding. In Nginx: proxy_set_header X-Forwarded-For "";. In HAProxy: http-request del-header X-Forwarded-For. Removing the header makes requests appear to originate from the proxy itself, which is the mechanism behind anonymous proxy classification.

It can. On a transparent proxy, the leftmost X-Forwarded-For value is your real client IP in plain text, so the origin server sees exactly where the request came from. An anonymous proxy replaces that value with the proxy's own IP, and an elite proxy omits the header entirely, so no X-Forwarded-For reaches the server. Whether your IP leaks comes down to the proxy's anonymity level, not the header itself. The same rule applies to X-Real-IP, which also carries a raw client address on transparent setups.

Strip the proxy-identifying headers before the request leaves your outermost proxy. Remove X-Forwarded-For, Via, and Forwarded together so nothing signals an intermediary. In Nginx, use proxy_set_header X-Forwarded-For ""; and proxy_set_header Via "";. In HAProxy, use http-request del-header for each one. The simplest option is to route through an elite (Level 1) proxy, which suppresses all of these headers by default and makes the request look like a direct connection.

Via is the clearest tell, because it names the proxy software and HTTP version even when your IP is hidden. X-Forwarded-For, X-Real-IP, and Forwarded also expose the presence of an intermediary, and on a transparent proxy they leak your real IP as well. X-Forwarded-Proto and X-Forwarded-Host carry request metadata rather than identity. An elite proxy sends none of these, which is why it reads as a direct connection.


SparkProxy helps teams scrape the web with confidence and anonymity. Explore our residential, datacenter, and ISP proxy infrastructure built for scale.

Limited-time ยท 50% off

Get 50% off your first purchase

Premium datacentre proxies with unlimited bandwidth. Use the code at checkout.

Offer ends soon โ€” claim it before it's gone

Claim Discount
S

Written by

SparkProxy

Proxy infrastructure and web-data experts at SparkProxy.

Keep reading

Related articles

What Is a P2P Proxy Network?

What Is a P2P Proxy Network?

A P2P proxy network routes traffic through real consumer devices that opt in to share bandwidth. See how it differs from datacenter and ISP proxies, and vet it.

SparkProxyยทProxy Basic
What Is an Upstream Proxy? Parent Proxy Explained

What Is an Upstream Proxy? Parent Proxy Explained

An upstream proxy is a proxy that forwards traffic to another proxy. Learn how upstream and parent proxies work, Squid and mitmproxy config, and real use cases.

SparkProxyยทProxy Basic
What Are WebRTC Leaks and How to Prevent Them

What Are WebRTC Leaks and How to Prevent Them

A WebRTC leak reveals your real IP through STUN and ICE candidates even behind a proxy or VPN. Learn how it happens, how to test for a leak, and how to stop it.

SparkProxyยทProxy Basic