Skip to content

How to get a visitor’s IP address without trusting headers

5 min read API guides

get visitor IP address

This guide shows how to get visitor IP address data without trusting a forged header.

The safe way to get visitor IP address data starts with one rule: trust the proxy list, not the header. Every request carries a source address. Reading it sounds trivial until a proxy sits in front of the application. Then the source address belongs to the proxy, and the original client is in a header that anyone can forge.

The Public IP address endpoint returns the caller address as the server sees it. It is a quick way to check what your own stack sends upstream.

curl "https://api2.globus.studio/v2/ip?format=json"

Direct connection

When the client connects directly, REMOTE_ADDR is the client address. In PHP that is $_SERVER['REMOTE_ADDR']. In Node it is req.socket.remoteAddress. Use it for logging and rate limits when there is no proxy.

Behind a proxy

To get visitor IP address data behind a proxy, read the forwarded header only when the connection comes from that proxy. A reverse proxy usually adds X-Forwarded-For, X-Real-IP or CF-Connecting-IP. The first value in X-Forwarded-For is the original client only if every proxy on the path appended to the header. A client can send its own header, so the value is untrusted unless the request comes from a proxy you control.

The safe pattern is a list of trusted proxy addresses. If REMOTE_ADDR is in that list, read the forwarded header. Otherwise use REMOTE_ADDR and ignore the header. The API uses the same rule through security.trusted_proxies.

// PHP, simplified
$remote = $_SERVER['REMOTE_ADDR'];
$trusted = ['10.0.0.10', '10.0.0.11'];
if (in_array($remote, $trusted, true) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $candidate = trim($parts[0]);
    if (filter_var($candidate, FILTER_VALIDATE_IP)) {
        return $candidate;
    }
}
return $remote;

IPv4 and IPv6

An address can be IPv4 or IPv6. Some headers carry both, and a client may connect over IPv6 while the proxy forwards an IPv4 address. The endpoint accepts v=4 or v=6 and returns a dash when the family does not match.

However you get visitor IP address data, store addresses in a column that handles both families. A 15-character string is too small for IPv6. Use inet6 in PostgreSQL, VARBINARY(16) in MySQL, or a text field with validation.

Privacy

When you get visitor IP address data, remember that an address can identify a person. Keep it only as long as the task needs it. Hash or truncate addresses in analytics. Tell users what you collect. The API does not store the caller address after the response.

Check your own stack

Run the endpoint from the same network as your application and compare the result with your logs. If the API returns a proxy address, your egress proxy is the caller. If it returns a client address and your logs show the proxy, the proxy configuration is the next thing to inspect.

Read the endpoint documentation for parameters and response examples.

Cloudflare and load balancers

To get visitor IP address data from a CDN, read the header the CDN documents. Cloudflare sends CF-Connecting-IP. A load balancer may send X-Real-IP or append to X-Forwarded-For. Each layer adds its own header and its own trust rule. Write the rule once, in front of the application, and pass a single trusted client address to the code that needs it.

If the application runs behind two proxies, the trusted list needs both addresses. A request from the first proxy can carry a header from the second. Check the chain from the outside in, and stop at the first address that is not trusted.

Testing the rule

To test whether you can get visitor IP address data safely, send a request with a forged X-Forwarded-For from a network that is not a trusted proxy. The application should ignore it and log the real source. Then send the same header through the proxy and confirm that the client address appears. A test for both cases prevents a later refactor from reopening the hole.

IPv4-mapped IPv6

A proxy may report an IPv4 client as ::ffff:203.0.113.5. Normalize the address before you compare it with a block list or store it. A string comparison between the mapped form and the plain form will miss a match.

Get visitor IP address safely

The safe pattern is to trust the proxy list, not the header. If the request does not come from a proxy you control, ignore the forwarded value and use the direct source address.

Further reading: RFC 7239, Forwarded HTTP Extension.

Custom work

Need an API that does not exist yet?

Describe the task and the response format. We will estimate the endpoint, the integration and the maintenance.

Start a conversation