Kamero

IP Geolocation in PHP: Get Visitor Location with a Free API

PHP powers a huge portion of the web — WordPress alone runs over 40% of all websites. If you need to detect visitor location in PHP, here's how to do it with a free API that requires no key and no registration.

Quick Start: file_get_contents

The simplest approach — one function call:

<?php
$response = file_get_contents("https://geo.kamero.ai/api/geo");
$location = json_decode($response, true);

echo "IP: " . $location["ip"] . "\n";
echo "City: " . $location["city"] . "\n";
echo "Country: " . $location["country"] . "\n";
echo "Timezone: " . $location["timezone"] . "\n";
echo "Coordinates: " . $location["latitude"] . ", " . $location["longitude"];
?>

Using cURL (More Control)

For production use, cURL gives you timeout control and error handling:

<?php
function getGeolocation(): ?array {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => "https://geo.kamero.ai/api/geo",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_CONNECTTIMEOUT => 3,
        CURLOPT_HTTPHEADER => ["Accept: application/json"],
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200 || !$response) {
        return null;
    }

    return json_decode($response, true);
}

$geo = getGeolocation();
if ($geo) {
    echo "Welcome from {$geo['city']}, {$geo['country']}!";
} else {
    echo "Welcome!";
}
?>

Laravel Integration

Create a service class and use it across your Laravel app:

<?php
// app/Services/GeoLocationService.php
namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;

class GeoLocationService
{
    public function detect(): ?array
    {
        return Cache::remember("geo:" . request()->ip(), 3600, function () {
            try {
                $response = Http::timeout(5)
                    ->get("https://geo.kamero.ai/api/geo");

                return $response->successful() ? $response->json() : null;
            } catch (\Exception $e) {
                return null;
            }
        });
    }

    public function getCountry(): string
    {
        return $this->detect()["country"] ?? "US";
    }

    public function getTimezone(): string
    {
        return $this->detect()["timezone"] ?? "UTC";
    }
}

// Usage in a controller:
class HomeController extends Controller
{
    public function index(GeoLocationService $geo)
    {
        $location = $geo->detect();

        return view("home", [
            "city" => $location["city"] ?? "there",
            "country" => $location["country"] ?? null,
        ]);
    }
}
?>

Laravel Middleware

Automatically attach location data to every request:

<?php
// app/Http/Middleware/DetectLocation.php
namespace App\Http\Middleware;

use App\Services\GeoLocationService;
use Closure;

class DetectLocation
{
    public function __construct(private GeoLocationService $geo) {}

    public function handle($request, Closure $next)
    {
        $location = $this->geo->detect();
        $request->merge(["geo" => $location]);

        return $next($request);
    }
}

// Then in any controller:
$city = $request->input("geo.city");
$country = $request->input("geo.country");
?>

WordPress: Detect Visitor Location

Add geolocation to your WordPress theme or plugin:

<?php
// In your theme's functions.php or a custom plugin

function kamero_get_visitor_location() {
    // Check transient cache first
    $ip = $_SERVER["REMOTE_ADDR"] ?? "";
    $cache_key = "geo_" . md5($ip);
    $cached = get_transient($cache_key);

    if ($cached !== false) {
        return $cached;
    }

    $response = wp_remote_get("https://geo.kamero.ai/api/geo", [
        "timeout" => 5,
    ]);

    if (is_wp_error($response)) {
        return null;
    }

    $body = wp_remote_retrieve_body($response);
    $data = json_decode($body, true);

    // Cache for 1 hour
    set_transient($cache_key, $data, HOUR_IN_SECONDS);

    return $data;
}

// Usage in a template
$location = kamero_get_visitor_location();
if ($location) {
    echo "<p>Shipping to " . esc_html($location["city"]) . "? ";
    echo "We deliver to " . esc_html($location["country"]) . "!</p>";
}
?>

Caching Strategies

For high-traffic PHP sites, always cache geolocation results. The visitor's location doesn't change during a session:

<?php
// Session-based caching
session_start();

function getGeoWithCache(): array {
    if (isset($_SESSION["geo_data"])) {
        return $_SESSION["geo_data"];
    }

    $response = file_get_contents("https://geo.kamero.ai/api/geo");
    $data = json_decode($response, true) ?: [];

    $_SESSION["geo_data"] = $data;
    return $data;
}

// Redis caching (for multi-server setups)
function getGeoRedis(string $ip): array {
    $redis = new Redis();
    $redis->connect("127.0.0.1");

    $cached = $redis->get("geo:{$ip}");
    if ($cached) {
        return json_decode($cached, true);
    }

    $response = file_get_contents("https://geo.kamero.ai/api/geo");
    $data = json_decode($response, true) ?: [];

    $redis->setex("geo:{$ip}", 3600, json_encode($data));
    return $data;
}
?>

Try the API from PHP

No API key, no composer package needed. Just HTTP.

PHP Examples →