To get the client IP address in Laravel 13, call $request->ip() or the request()->ip() helper. Behind a load balancer, CDN or reverse proxy you must also configure trusted proxies, otherwise Laravel returns the proxy's address instead of the visitor's.
This tutorial targets Laravel 13 (PHP 8.3 to 8.5). The code was written for this article and not executed in a live project. Proxy settings follow the "Configuring Trusted Proxies" section of the Laravel request docs.
How do you read the IP address in a controller?
use Illuminate\Http\Request;
Route::get('/my-ip', function (Request $request) {
return [
'ip' => $request->ip(),
'ips' => $request->ips(),
];
});ip() returns the client address as a string. ips() returns the whole chain from the X-Forwarded-For header (only trusted entries are included), with the original client first. You can also use request()->ip() anywhere, such as in a service class or Blade view.
Why does Laravel show 127.0.0.1 or the wrong IP?
On a local server you will see 127.0.0.1 (or ::1 for IPv6), because the browser and the server run on the same machine. In production behind Nginx proxy, Cloudflare, an AWS load balancer or Docker, the TCP connection comes from the proxy. The real client address is only in headers such as X-Forwarded-For. Laravel ignores those headers unless the sender is a trusted proxy, because anyone can forge them.
How do you configure trusted proxies in Laravel 13?
Configure them in bootstrap/app.php using the middleware callback:
use Illuminate\Foundation\Configuration\Middleware;
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: [
'192.168.1.10',
'10.0.0.0/8',
]);
})List the exact IP addresses or CIDR ranges of your load balancers. If proxy addresses change often, as with some cloud load balancers, you can trust all of them:
$middleware->trustProxies(at: '*');Only use '*' when your app is reachable exclusively through your proxy. If the server is also directly exposed, anyone can send a fake X-Forwarded-For header and spoof their IP.
You can limit which headers are trusted with the headers argument, for example headers: Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PROTO. The Laravel docs list the available header constants.
How do you get the real IP behind Cloudflare?
Cloudflare sets CF-Connecting-IP with the visitor address. The safe approach is to trust only Cloudflare's published IP ranges as proxies, then read $request->ip() through X-Forwarded-For. Reading CF-Connecting-IP directly is only safe if your origin accepts traffic from Cloudflare alone, because otherwise anyone can set that header.
How do you use the IP address in practice?
Log it with each request:
use Illuminate\Support\Facades\Log;
Log::info('Login attempt', [
'email' => $request->email,
'ip' => $request->ip(),
]);Throttle by IP using a rate limiter in AppServiceProvider::boot():
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});Block certain addresses with a small middleware:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class BlockIps
{
public function handle(Request $request, Closure $next)
{
$blocked = config('security.blocked_ips', []);
if (in_array($request->ip(), $blocked, true)) {
abort(403, 'Your IP address is not allowed.');
}
return $next($request);
}
}Create the config/security.php file returning a blocked_ips array, and apply the middleware to the routes you want to protect.
Is the IP address personal data?
In many jurisdictions an IP address counts as personal data. Store it only when you have a reason, mention it in your privacy policy, and consider truncating or deleting it after a retention period.
Common mistakes
- Reading
$_SERVER['REMOTE_ADDR']directly. It ignores your proxy configuration. Use the request object. - Trusting
X-Forwarded-Foryourself. Parsing the raw header lets clients spoof their IP. - Using
trustProxies(at: '*')on an exposed server. Restrict access to the proxy first. - Using IP as identity. Many users share one address (offices, mobile carriers), and one user may change addresses.
- Testing only locally. You always get
127.0.0.1, so the proxy problem is not visible until deployment.
How do you verify it works?
- Deploy the
/my-iproute to staging. - Open it from your phone on mobile data and compare the result with a "what is my IP" site.
- If it shows a private address like
10.x.x.x, trusted proxies are not configured. - In a feature test, simulate it with
$this->withServerVariables(['REMOTE_ADDR' => '203.0.113.5'])->get('/my-ip')and assert the JSON.
FAQ
How do I get the IPv4 address only?
Use filter_var($request->ip(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4). It returns false for IPv6 addresses.
Can a user fake their IP?
Not the TCP address, but they can fake forwarded headers if you trust them. That is why you trust only known proxies.
Can I look up the location from an IP?
Yes, with a GeoIP database or service, but results are approximate and should not be used for security decisions.



