PHP: How to detect / get the real client IP address of website visitors?

It may seem simple at first because most of us should be relying on the server side environmental variable REMOTE_ADDR solely for client IP addresses:

echo $_SERVER['REMOTE_ADDR'];

Yet it’s barely enough to get the real IP for a variety of circumstances such as when the user is visiting your website from a proxy server. To everyone’s surprise, there are a lot more environmental variables regarding client IP address than just the most straightforward one, REMOTE_ADDR. Consider this snippet in the attempt to detect the real source IP address of the request:

function get_ip_address() {
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
                    return $ip;
                }
            }
        }
    }
}

It first searches through a series of possible environmental variables that may contain the client IP address and uses whichever that is set and then extract the potential IP value to be validated. After successful validation by the PHP5 filter_var() function, the value is returned. You better not change the order these variable names are placed in the literal array.

This approach is much more sophisticated than just looking at REMOTE_ADDR but it’s far from mess-proof because it relies on the HTTP header information which can be easily manipulated anywhere along the way the request is routed to your server / website.

19 thoughts on “PHP: How to detect / get the real client IP address of website visitors?”

  1. Pingback: PHP Security Checklist for Websites and Web Applications – Bottom Line for Every Good PHP Developer

  2. I got you stuff, really looks nice and tactical. But I tried to call the function this way:
    echo get_ip_address(); but generated this error: Fatal error: Call to undefined function filter_var() in C:\wamp\www\php-bank\create-directory\index.php on line 10, That is the error that it generated, please help! I would love to get the reply in my mail box please! Thanks.

  3. $client_addr = filter_var((!empty($_SERVER[‘HTTP_CLIENT_IP’]))? $_SERVER[‘HTTP_CLIENT_IP’]:
    (!empty($_SERVER[‘HTTP_X_FORWARDED_FOR’]))? $_SERVER[‘HTTP_X_FORWARDED_FOR’]:
    (!empty($_SERVER[‘REMOTE_ADDR’]))? $_SERVER[‘REMOTE_ADDR’]:’UNKNOWN’, FILTER_SANITIZE_STRING);

    1. This is not preferable because it jeopardizes the readability of the code.

      Human efficiency comes way higher priority than that of machines or storage.

  4. Hello, nice job here! I totally agree with Yang Yang on readability being the most important thing. Actually, for the sake of it, 2 extra things I’d do on your function are:
    – use a regex and avoid one extra level of indentation (on the filter_var line)
    – declare the array before the foreach (might have some speed benefits also, if an array is otherwise build at every cycle iteration – not sure on this; main point is nevertheless to be able to break long constant line in multiple ones, though, so o improve readability);
    But hey, again, cool solution of yours 😉

  5. [ $client_addr = filter_var((!empty($_SERVER[‘HTTP_CLIENT_IP’]))? $_SERVER[‘HTTP_CLIENT_IP’]:
    (!empty($_SERVER[‘HTTP_X_FORWARDED_FOR’]))? $_SERVER[‘HTTP_X_FORWARDED_FOR’]:
    (!empty($_SERVER[‘REMOTE_ADDR’]))? $_SERVER[‘REMOTE_ADDR’]:’UNKNOWN’, FILTER_SANITIZE_STRING) ]

  6. Pingback: Hỏi về $_SERVER['REMOTE_ADDR'] - Trang 4

Comments are closed.

Scroll to Top