PHP
Client IP Address
Web Development
Coding Tutorial
Server-Side Scripting

How to get the client IP address in PHP

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In PHP, the easiest way to get the connecting address is $_SERVER['REMOTE_ADDR']. The tricky part is deciding whether you really want the direct peer address or the original client address behind a trusted reverse proxy or load balancer, because those are not always the same thing.

Start with REMOTE_ADDR

The most direct server-side answer is:

php
<?php
$ip = $_SERVER['REMOTE_ADDR'] ?? null;
echo $ip;

REMOTE_ADDR is the address of the machine that connected to your web server. If the request came straight from the client, this is the client IP. If the request came through a proxy, CDN, or load balancer, it is usually the address of that intermediary instead.

That is why REMOTE_ADDR is reliable as a transport fact, but not always as the original end-user identity.

Reverse proxies change the picture

In production deployments, traffic often passes through:

  • Nginx or Apache reverse proxies
  • cloud load balancers
  • CDNs
  • API gateways

Those intermediaries may place the original client address into headers such as:

  • 'X-Forwarded-For'
  • 'X-Real-IP'

A simple parser might look like:

php
1<?php
2function getForwardedIp(): ?string
3{
4    if (empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
5        return null;
6    }
7
8    $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
9
10    foreach ($parts as $part) {
11        $candidate = trim($part);
12        if (filter_var($candidate, FILTER_VALIDATE_IP)) {
13            return $candidate;
14        }
15    }
16
17    return null;
18}

But this is only safe if you trust the proxy that set the header.

Do not trust forwarded headers blindly

This is the most important security point. Headers like X-Forwarded-For can be spoofed by a client unless your infrastructure strips and rewrites them consistently.

So:

  • 'REMOTE_ADDR is trustworthy as the direct peer'
  • forwarded headers are trustworthy only behind known, controlled proxies

If your PHP app is behind a trusted reverse proxy, the usual safe design is:

  1. trust the proxy's REMOTE_ADDR
  2. only then inspect forwarded headers
  3. validate the result as an IP address

A more careful helper might look like:

php
1<?php
2function getClientIp(array $trustedProxies): ?string
3{
4    $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? null;
5    if ($remoteAddr === null) {
6        return null;
7    }
8
9    if (!in_array($remoteAddr, $trustedProxies, true)) {
10        return filter_var($remoteAddr, FILTER_VALIDATE_IP) ? $remoteAddr : null;
11    }
12
13    $forwarded = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
14    foreach (explode(',', $forwarded) as $candidate) {
15        $candidate = trim($candidate);
16        if (filter_var($candidate, FILTER_VALIDATE_IP)) {
17            return $candidate;
18        }
19    }
20
21    return $remoteAddr;
22}

This is much safer than treating X-Forwarded-For as authoritative in every environment.

IPv4 and IPv6 both matter

Do not assume every address will be IPv4. filter_var(..., FILTER_VALIDATE_IP) handles both IPv4 and IPv6, which is usually what you want unless your application has a very specific restriction.

For logging and auditing, storing the normalized validated string is generally enough. For security decisions, the surrounding trust model matters more than the header name.

Common Pitfalls

The biggest mistake is using HTTP_X_FORWARDED_FOR directly as if it were always the real client IP. It is only meaningful if the request passed through trusted infrastructure that sets it correctly.

Another mistake is ignoring that REMOTE_ADDR may be a load balancer or proxy address in production. That is not wrong; it just answers a different networking question.

Developers also forget to validate the extracted value. Even if a header exists, it should still be checked with filter_var.

Finally, do not build security policy on IP headers alone unless you control the full proxy chain and understand exactly which hop is authoritative.

Summary

  • Use $_SERVER['REMOTE_ADDR'] for the direct connected peer address.
  • Use forwarded headers only when the request comes from trusted proxies.
  • Validate any extracted address with FILTER_VALIDATE_IP.
  • Understand the difference between the transport address and the original client address.
  • Treat IP extraction as an infrastructure-aware problem, not just a one-line PHP snippet.

Course illustration
Course illustration

All Rights Reserved.