Get Geolocation From an 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 a PHP application.

Get Geolocation from IP Address with GeoIP in PHP

GeoIP2 database is used to look up IP addresses and retrieve information such as latitude, longitude, city, country, region and time zone. In this post we will demonstrate, how to get location of an IP in PHP using the GeoIP2 database. Files we are going to create for this post:

  1. geo-functions.php: The file contains only one function to retrieve the client's IP address.
  2. index.php: The main index file to fetch and display geo-location data.
  3. 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 the country by an IP is fastest approach as compared to making requests 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 the IP Address of a User in PHP?

In PHP, a user's IP address can be retrieved from the global $_SERVER variable with certain IP key checks in order. We will create a PHP file with a function to get the IP address of the user from the $_SERVER global variable with a filter check to validate the IP address as well. The unction in the following script returns the IP address of the 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 an IP Address with GeoIP?

Now it's time to use the GeoIP library and get the user's geographical location from the IP address by using the function we created to get the IP address from the $_SERVER variable and then passing that IP address as a parameter to the GeoIP city reader class method. Steps to get the location from an IP address in PHP are as follows:

  • Load the composer autoload file in order to use GeoIP library functions.
  • Use the GeoIP Reader class.
  • Initialize a new reader by providing it with a database file. We are using the city database file in this post.
  • Retrieve the current user's IP address and store it in the $client_ip_address variable.
  • Create an HTML table and add an exception handler in the table's body.
  • Fetch the geographical information by using the city() of the $city_reader variable.
  • Display the IP Address, Latitude, Longitude, City name, Continent name, Country name, Country code and Timezone in a table.
  • Show an exception message if the record is not found in the 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 the 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 the country by IP in PHP using the GeoIP database. It is important to keep in mind that GeoIP2 databases are regularly updated and it is important to download the latest version of the database from time to time. MaxMind offers endpoints to download the updates using their API. These databases are free to use for non-commercial purposes. Getting geolocation data using GeoIP avoids the API requests involved in retrieving information from third-party resources. This is how the result will look like:

Geographical Information data table