portfolio image

Languages :  Laravel


How to Get User Location From IP in Laravel

Learn three ways to resolve a visitor’s city, country, coordinates, and timezone from their IP address in Laravel:

  • a package-first method
  • a DIY HTTP client method with hosted APIs

Why IP Geolocation?

  • Personalize content and currency.
  • Geo-based analytics and rate limiting.
  • Compliance prompts (consent banners per region).

Approach 1: Package-First with stevebauman/location

Install

composer require stevebauman/location
php artisan vendor:publish --provider="Stevebauman\Location\LocationServiceProvider"

Make controller called LocationController

php artisan make:controller LocationController

Open Controller file and paste this code

// app/Http/Controllers/LocationController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Stevebauman\Location\Facades\Location;

class LocationController extends Controller
{
    public function approach1(Request $request){
        $ip = $request->ip();
        // or
        // $ip = $_SERVER['REMOTE_ADDR'];

        // NOTE: Location::get($ip) works in server not in localhost
        $location = Location::get($ip);

        return view('location', [
            'geo' => $location ? [
                'ip'          => $ip,
                'country'     => $location->countryName,
                'countryCode' => $location->countryCode,
                'region'      => $location->regionName,
                'city'        => $location->cityName,
                'postal'      => $location->postalCode,
                'lat'         => $location->latitude,
                'lon'         => $location->longitude,
                'timezone'    => $location->timezone,
            ] : null,
            'error'=>$location? null : 'We could not determine your location'
        ]);
    }
}

Route file

// routes/web.php
use App\Http\Controllers\LocationController;

Route::get('/approach1', [LocationController::class, 'approach1'])->name('approach1');

Blade Code

<div class="max-w-xl mx-auto mt-8 p-6 bg-white dark:bg-gray-800 shadow rounded-xl">
    <h2 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">
        🌍 IP Location
    </h2>

    {{-- Error Section --}}
    @if($error)
        <div class="p-3 mb-4 text-sm text-red-800 rounded bg-red-100 dark:bg-red-200 dark:text-red-900">
            {{ $error }}
        </div>
    @endif

    {{-- Geo Section --}}
    @if($geo)
        <ul class="space-y-2 text-gray-700 dark:text-gray-200">
            <li><strong>IP:</strong> {{ $geo['ip'] }}</li>
            <li><strong>Country:</strong> {{ $geo['country'] }} ({{ $geo['countryCode'] }})</li>
            <li><strong>Region:</strong> {{ $geo['region'] }}</li>
            <li><strong>City:</strong> {{ $geo['city'] }}</li>
            <li><strong>Postal:</strong> {{ $geo['postal'] }}</li>
            <li><strong>Timezone:</strong> {{ $geo['timezone'] }}</li>
            <li><strong>Lat/Lon:</strong> {{ $geo['lat'] }}, {{ $geo['lon'] }}</li>
        </ul>
    @endif
</div>

Approach 2: DIY HTTP Client + Hosted APIs (ipapi, IPinfo, ip-api)

Make controller called LocationController

php artisan make:controller LocationController

Open Controller file and paste this code

// app/Http/Controllers/LocationController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;

class LocationController extends Controller
{
    public function approach2(Request $request){
        $ip = $request->ip();
        // or
        // $ip = $_SERVER['REMOTE_ADDR'];

        // NOTE: Location::get($ip) works in server not in localhost
        try {
            $res = Http::get("http://ip-api.com/json/{$ip}");

            if (!$res->ok() || $res->json('status') == 'fail') {
                return view('location', [
                    'geo'   => null,
                    'error' => 'We could not determine your location',
                ]);
            }

            return view('location', [
                'geo' => [
                    'ip'          => $ip,
                    'country'     => $res->json('country'),
                    'countryCode' => $res->json('countryCode'),
                    'region'      => $res->json('region'),
                    'city'        => $res->json('city'),
                    'postal'      => $res->json('zip'),
                    'lat'         => $res->json('lat'),
                    'lon'         => $res->json('lon'),
                    'timezone'    => $res->json('timezone'),
                    'org'         => $res->json('org'),
                ],
                'error'=>null
            ]);
        } catch (ConnectionException $exception) {
            return view('location', [
                'geo'   => null,
                'error' => 'Unexpected error: ' . $exception->getMessage(),
            ]);
        }
    }
}

Route file

// routes/web.php
use App\Http\Controllers\LocationController;

Route::get('/approach2', [LocationController::class, 'approach2'])->name('approach2');

Blade Code

<div class="max-w-xl mx-auto mt-8 p-6 bg-white dark:bg-gray-800 shadow rounded-xl">
    <h2 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">
        🌍 IP Location
    </h2>

    {{-- Error Section --}}
    @if($error)
        <div class="p-3 mb-4 text-sm text-red-800 rounded bg-red-100 dark:bg-red-200 dark:text-red-900">
            {{ $error }}
        </div>
    @endif

    {{-- Geo Section --}}
    @if($geo)
        <ul class="space-y-2 text-gray-700 dark:text-gray-200">
            <li><strong>IP:</strong> {{ $geo['ip'] }}</li>
            <li><strong>Country:</strong> {{ $geo['country'] }} ({{ $geo['countryCode'] }})</li>
            <li><strong>Region:</strong> {{ $geo['region'] }}</li>
            <li><strong>City:</strong> {{ $geo['city'] }}</li>
            <li><strong>Postal:</strong> {{ $geo['postal'] }}</li>
            <li><strong>Timezone:</strong> {{ $geo['timezone'] }}</li>
            <li><strong>Lat/Lon:</strong> {{ $geo['lat'] }}, {{ $geo['lon'] }}</li>
            @if(isset($geo['org']))
                <li><strong>Organization:</strong> {{ $geo['org'] }}</li>
            @endif
        </ul>
    @endif
</div>

Comparison Table

CriterionPackage (stevebauman/location)DIY HTTP + API
Setup speedVery fastFast
AccuracyProvider-dependentHigh (paid tiers)
Rate limitsProvider-dependentVendor-defined
PrivacyProvider-dependentProvider-dependent
CostFree (provider may bill)Free → Paid
MaintenanceLowLow–Medium

Happy coding 🚀