How to get client IP address in Laravel 5+

317,211

Solution 1

Looking at the Laravel API:

Request::ip();

Internally, it uses the getClientIps method from the Symfony Request Object:

public function getClientIps()
{
    $clientIps = array();
    $ip = $this->server->get('REMOTE_ADDR');
    if (!$this->isFromTrustedProxy()) {
        return array($ip);
    }
    if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
        $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
        preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
        $clientIps = $matches[3];
    } elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
    }
    $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
    $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
    foreach ($clientIps as $key => $clientIp) {
        // Remove port (unfortunately, it does happen)
        if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
            $clientIps[$key] = $clientIp = $match[1];
        }
        if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
            unset($clientIps[$key]);
        }
    }
    // Now the IP chain contains only untrusted proxies and the client IP
    return $clientIps ? array_reverse($clientIps) : array($ip);
} 

Solution 2

If you are under a load balancer, Laravel's \Request::ip() always returns the balancer's IP:

            echo $request->ip();
            // server ip

            echo \Request::ip();
            // server ip

            echo \request()->ip();
            // server ip

            echo $this->getIp(); //see the method below
            // clent ip

This custom method returns the real client ip:

public function getIp(){
    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){
                $ip = trim($ip); // just to be safe
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
    return request()->ip(); // it will return server ip when no client ip found
}

In addition to this I suggest you to be very careful using Laravel's throttle middleware: It uses Laravel's Request::ip() as well, so all your visitors will be identified as the same user and you will hit the throttle limit very quickly. I experienced this live and this caused big issues.

To fix this:

Illuminate\Http\Request.php

    public function ip()
    {
        //return $this->getClientIp(); //original method
        return $this->getIp(); // the above method
    }

You can now also use Request::ip(), which should return the real IP in production.

Solution 3

Use request()->ip().

From what I understand, since Laravel 5 it's advised/good practice to use the global functions like:

response()->json($v);
view('path.to.blade');
redirect();
route();
cookie();

And, if anything, when using the functions instead of the static notation my IDE doesn't light up like a Christmas tree.

Solution 4

Add namespace

use Request;

Then call the function

Request::ip();

Solution 5

For Laravel 5 you can use the Request object. Just call its ip() method, something like:

$request->ip();
Share:
317,211

Related videos on Youtube

Amrinder Singh
Author by

Amrinder Singh

Updated on February 23, 2022

Comments

  • Amrinder Singh
    Amrinder Singh about 2 years

    I am trying to get the client's IP address in Laravel.

    It is easy to get a client's IP in PHP by using $_SERVER["REMOTE_ADDR"]. It is working fine in core PHP, but when I use the same thing in Laravel, it returns the server IP instead of the visitor's IP.

  • Chris
    Chris over 8 years
    You are right that request is a "global" function - it's one of the global helper functions provided by laravel. However, the Request facade, isn't static (nor is the method ip) - request()->foo, and Reqest::foo and $request->foo are all identical. Have a look at this gist for an example: gist.github.com/cjke/026e3036c6a10c672dc5
  • Stan Smulders
    Stan Smulders over 8 years
    Yeah I know :) But it's written in the static syntax ::. My IDE tends to light up light a christmas tree with those. The global functions just 'look' cleaner ;-) But to each his own!
  • Chris
    Chris over 8 years
    Fair enough - both are equally correct. I just thought the bit where you said "it's not Request::ip might be misleading
  • Stan Smulders
    Stan Smulders over 8 years
    You're absolutely right! Re-reading it I notice the second sentence should have read: And since Laravel 5 it's (from what I understand) [recommended] to use the global functions like My bad! That should have put things into perspective.
  • shalini
    shalini over 8 years
    If you have use namespace :--> use Illuminate\Http\Request; bold Rename namespace for request since both will clash
  • jfadich
    jfadich about 8 years
    The original answer is correct. You need to import use Request because you're trying to use the Facade. The namespace you provided is for the underlying class. If you import that you will get an error because ip() can't be called statically, that's what the facade is for.
  • hackel
    hackel about 8 years
    The problem is that these global functions aren't easily testable—they can't be mocked. Façades can be. I try to avoid global functions, since it means digging through to global function source to mock its calls, which is extra work, annoying, and shouldn't be my responsibility.
  • hackel
    hackel about 8 years
    If you're going to bother importing the class, you should use the actual façade, not the alias: use Illuminate\Support\Facades\Request. If not, just use \Request::.
  • Chris
    Chris over 7 years
    Although request()->ip() is correct, the surrounding text is really misleading - especially to say "it's not Request::ip.
  • Stan Smulders
    Stan Smulders over 7 years
    @Chris Thanks, you're absolutely right. Edited for clarity!
  • Stan Smulders
    Stan Smulders over 7 years
    @hackel Good point! Thanks for explaining that. I hardly ever mock so don't run into that problem but that definitely seems like something to be aware of!
  • Chris
    Chris over 7 years
    @StanSmulders Cheers!
  • secondman
    secondman over 7 years
    Using the Request object doesn't work for me, it returns the address of my Homestead server. 192.168.10.10 which is obviously not my IP address.
  • Mistre83
    Mistre83 over 7 years
    is correct the if(filter_var...) inside second foreach ? this code will be never executed.
  • Sebastien Horin
    Sebastien Horin over 7 years
    @Mistre83 Yes you are right, I think it's a test oversight. I update it!
  • Crystal
    Crystal about 7 years
    this actually works with laravel 5.4 Please consider making PR on github. I think this should be default behavior
  • w5m
    w5m almost 7 years
    This worked a treat in Laravel 5.3 when the Laravel request object's ip() method kept returning 127.0.0.1
  • Sebastien Horin
    Sebastien Horin over 6 years
    @VinceKronlein for your case check this answer stackoverflow.com/a/41769505/3437790
  • mizan3008
    mizan3008 about 6 years
    $request->ip() L5.1
  • ied3vil
    ied3vil about 6 years
    @VinceKronlein in your case it was very correct. Because you were accessing Homestead, in your LOCAL network, you had tje 192. IP. if you were accessing someone else's homestead server, through the internet, your IP would go out through your ISP and your public one would be used.
  • user2722667
    user2722667 almost 6 years
    Cant you fix this with trusted proxys? - laravel.com/docs/master/requests#configuring-trusted-proxies
  • Yevgeniy Afanasyev
    Yevgeniy Afanasyev over 5 years
    Thank you, your answer helped me more than I thought I needed. But there is a better way to solve this problem, see my answer.
  • Sebastien Horin
    Sebastien Horin over 5 years
    @YevgeniyAfanasyev not sure about the protected $proxies = '*'; in terms of security, when reading the headers is harmless
  • Philipp Mochine
    Philipp Mochine over 5 years
    Not working anymore, now "trustedHeaderSet" is neeed
  • Deepak Sharma
    Deepak Sharma about 5 years
    I think one pipe "|" sign is missing after FILTER_FLAG_NO_PRIV_RANGE FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE other than this it work fine for me Thanks @SebastienHorin
  • Sandra
    Sandra over 4 years
    for "recent" laravel versions, see the docs laravel.com/docs/5.5/requests#configuring-trusted-proxies
  • PJP
    PJP over 4 years
    It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code. As is, the system is flagging it as low-quality so try to improve it.
  • rashedcs
    rashedcs over 4 years
    Thank you for your suggestion.
  • Syamsoul Azrien
    Syamsoul Azrien about 4 years
    if the client use VPN, is this code will retrieve the fake IP address or the real IP address?
  • Philipp Mochine
    Philipp Mochine over 3 years
    @Huzaifa99 weird it worked for me for a while, not it's not working! How weird (did you find another solution?)
  • NosiaD
    NosiaD over 3 years
    To answer @SyamsoulAzrien, might not be a possible due to the user's IP's present before the request has been done, thus it's the vpn's ip was the present
  • Misbah Ahmad
    Misbah Ahmad about 3 years
    For the second part of the answer, is it wise to edit the core framework file (Illuminate\Http\Request.php)? Because every time you do composer install on another machine, this will not apply.
  • Hassan Joseph
    Hassan Joseph almost 3 years
    To get current user ip in php, laravel \Request::ip(); OR $request->ip();
  • Suresh Kumar Kumawat
    Suresh Kumar Kumawat over 2 years
    Request::ip(); return me Server Ip. I want network Ip address . It is possible ???