Get Geolocation from IP Address with GeoIP in PHP
GeoIP2 is an open-source database offered and maintained by MaxMind. This database is used for IP lookup and retrieving geolocation data from an IP address. Learn how to get geolocation from an IP address with GeoIP in PHP.

GeoIP2 database is used to lookup IP addresses and retrieve information like latitude, longitude, city, country, region and timezone. In this post we will demonstrate how to get IP location in PHP using GeoIP2 database. Files we are going to create for this post:
- geo-functions.php: The file contains only one function to get client IP address.
- index.php: The main index file to fetch and display geo-location data.
- style.css: The stylesheet for our index page.
Before we start with this post we first need to download MaxMind's GeoIP database. Using a database to get country by IP is fastest approach as compared to making request to third-party Geolocation API services. However the downside is database might not have some data and always needs to be updated. The database can be downloaded after creating a free account on MaxMind's website. Then we need to download the GeoIP library which is available in composer packages:
composer require geoip2/geoip2:~2.0
How to Get IP Address of User in PHP?
In PHP user's IP address can retrieved from global $_SERVER variable with certain IP keys checks in order. We will create a PHP file with function to get IP address of user from $_SERVER global variable with filter check to validate the IP address as well. Function in following script returns the IP address of user:
geo-functions.php
<?php
/**
* @return string|null
*/
function get_client_ip_address(): ?string
{
$client_ip_address = null;
$ip_address = $_SERVER['HTTP_CLIENT_IP'] ??
$_SERVER['HTTP_X_FORWARDED_FOR'] ??
$_SERVER['HTTP_X_FORWARDED'] ??
$_SERVER['HTTP_FORWARDED_FOR'] ??
$_SERVER['HTTP_FORWARDED'] ??
$_SERVER['REMOTE_ADDR'];
foreach (explode(',', $ip_address) as $ip) {
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
$client_ip_address = $ip;
break;
}
}
return $client_ip_address;
}
How to Get Geo-location Data from IP Address with GeoIP?
Now its time to use GeoIP library and get user's geographical location from IP address by using the function we created to get IP address from $_SERVER variable and then passing that IP address as parameter to GeoIP city reader class method. Steps to get location from IP address in PHP are as follow:
- Load the composer autoload file in order to use GeoIP library functions.
- Use the GeoIP Reader class.
- Initialize new reader by providing it a database file. We are using city database file in this post.
- Retrieve the current user's IP address and store it in
$client_ip_addressvariable. - Create HTML table and add an exception handle in table's body.
- Fetch the geographical information by using the
city()of$city_readervariable. - Display the IP Address, Latitude, Longitude, City name, Continent name, Country name, Country code and Timezone in table.
- Show an exception message if record is not found in database.
index.php
<?php
include_once __DIR__ . '/vendor/autoload.php';
include_once __DIR__ . '/geo-functions.php';
use GeoIp2\Database\Reader;
$city_reader = new Reader('GeoLite2-City.mmdb');
$client_ip_address = get_client_ip_address();
?>
<!DOCTYPE html>
<html>
<head>
<title>Get Geolocation from IP Address with GeoIP in PHP - Demo</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<section class="section py-4">
<div class="container">
<table class="table">
<thead>
<tr>
<th colspan="2">Geolocation Data</th>
</tr>
</thead>
<tbody>
<?php
try {
$record = $city_reader->city($client_ip_address); ?>
<tr>
<th class="text-left" style="width: 200px;">IP Address</th>
<td><?= $record->traits->ipAddress ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Latitude</th>
<td><?= $record->location->latitude ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Longitude</th>
<td><?= $record->location->longitude ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">City</th>
<td><?= $record->city->name ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Region</th>
<td><?= $record->continent->name ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Country</th>
<td><?= $record->country->name ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Country Code</th>
<td><?= $record->country->isoCode ?? 'N/A' ?></td>
</tr>
<tr>
<th class="text-left">Timezone</th>
<td><?= $record->location->timeZone ?? 'N/A' ?></td>
</tr>
<?php } catch (Exception $e) { ?>
<tr>
<td colspan="2"><?= $e->getMessage() ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</section>
</body>
</html>
Add CSS Styles for GeoIP Interface
Add the necessary CSS styles for our entire index page and GeoIP details table.
style.css
* {
box-sizing: border-box;
}
html,body {
margin: 0;
padding: 0;
}
body {
background-color: #f6f6f6;
font-family: "Segoe UI", "Roboto", "Helvetica", sans-serif;
font-size: 15px;
font-weight: normal;
font-style: normal;
}
img {
max-width: 100%;
height: auto;
}
.container {
max-width: 1024px;
margin: 0 auto;
padding-left: 15px;
padding-right: 15px;
}
.py-4, .pt-4 {
padding-top: 1rem;
}
.py-4, .pb-4 {
padding-bottom: 1rem;
}
.text-left {
text-align: left;
}
.table {
display: table;
width: 100%;
border-collapse: collapse;
background-color: #ffffff;
}
.table th, .table td {
border-top: 1px solid #d1d5db;
}
.table th {
font-weight: 600;
padding: .75rem;
}
.table td {
padding: 0.345rem .75rem;
}Following these simple steps we can get country by IP in PHP using GeoIP database. It is to keep in mind that GeoIP2 databases are regularly updated and it is important to download latest version of database from time to time. MaxMind offers endpoints to download the updates using their API. These database are free to use for non-commercial use. Getting geolocation data using GeoIP avoids the API requests involved to retrieve information from third party resources. This is how the result will look like:
