Geolocate with GeoLite2 and PHP

April 22, 2021 Posted by Editorial Staff

With GeoLite2 and PHP, you can easily and for free retrieve geolocation data and create a custom experience for the user.

In this article, you will find all the essential information required to download GeoLite2 and create your first geolocation script with PHP.

Download the GeoLite2 database from the MaxMind website

GeoLite2 is a free IP geolocation database provided by MaxMind. It’s the free version of GeoIP2, an accurate geolocation database accessible with a paid subscription.

You can download these two databases or use them as a web service. It’s also important to note the multiple versions, for different purposes, of the database are available. For example GeoLite2 ASN, GeoLite2 City, GeoLite2 Country, etc.

This tutorial will cover the steps required to download and use the GeoLite2 Country database in .mmdb format, a binary format created by MaxMind for low latency operations.

Follow this procedure to download the GeoLite2 database manually:

  1. Create an account on the MaxMind website
  2. Set a password to complete the account creation process
  3. Click on your avatar and visit the My Account page
  4. Visit the Download Files tab
  5. Download the GeoLite2 Country database and save it on your pc

Move the GeoLite2 database in your web server

Since you can’t distribute the GeoLite2 database, you should store it so that it won’t be accessible on the web. For this reason, I recommend you to use one of these two techniques.

Host the GeoLite2 database outside the public folder

If your website is hosted in a private server or VPS, you can move the Geolite2 database outside the public folder. In this way, the file will be accessible by PHP but not accessible through an URL.

Make the file non-discoverable

Another technique consists of making the file non-discoverable by the users. You can achieve this first by storing the file in a dedicated folder protected by a .htaccess file with this content:

deny from all

And then by renaming the database file from GeoLite2-Country.mmdb to a randomly generated file name like for example 30064661e9421729e9c216ce4f7168b1.mmdb

Get the IP address of the user with PHP

There are multiple methods to retrieve the IP address of a user. The simplest one is to use the REMOTE_ADDR index of the $_SERVER variable.

$ip_address = $_SERVER['REMOTE_ADDR']; 

More complex and precise techniques to retrieve the IP address of a user are outside the scope of this tutorial. But you can find more details in articles like this one.

Perform a query on the GeoLite2 database

MaxMind maintains the GeoIP2 PHP API repository in GitHub, an API that allows you to read data from the GeoIP2 and GeoLite2 databases and web services.

You can download the library with Composer by using a console command or create the composer.json file with this content and install the required dependencies with your IDE.

{
  "require": {
    "geoip2/geoip2": "^2.11"
  }
}

Once GEOIP2 PHP API is installed, integrate it in your script with this command:

require 'vendor/autoload.php';

Then create an instance of the Reader object. A reusable PHP object with inside the method used to read the database data:

$reader = new GeoIp2\Database\Reader( $file_path );

You can finally retrieve the country based on the IP with the country() method. Note that an exception is used to catch possible errors.

try {
    $record = $reader->country( $ip_address );
} catch ( Exception $e ) {
    return null;
}

The ISO 3166-1 alpha-2 code is now available inside properties of $record:

$country_iso_code = $record->country->isoCode;

You used GeoLite2 to find the country associated with an IP address. Now let’s see how to use this information to our advantage in a real-world situation.

Verify if a user is located in the European Union

The European Union includes 27 countries. You can save the ISO 3166-1 alpha-2 code of these countries in a PHP array.

//An array with the ISO code of all the European Union countries
$european_countries = ['be','bg','cz','dk','de','ee','ie','el','es','fr','hr','it','cy','lv','lt','lu','hu','mt','nl','at','pl','pt','ro','si','sk','fi','se'];

And then compare the list of countries with the ISO code retrieved by GeoLite2.

//Verify if the detected locale is present in the list of the countries.
foreach ( $european_countries as $single_country ) {
   if ( mb_strtolower( $single_country ) === mb_strtolower( $country_iso_code ) ) {
      $found = true;
   }
}

The ready-to-use script below generates a text message that states if the current user is browsing the internet from a country that is part of the European Union or not.

<?php

require 'vendor/autoload.php';

$result = false;

//An array with the iso code of all the European countries
$european_countries = ['be','bg','cz','dk','de','ee','ie','el','es','fr','hr','it','cy','lv','lt','lu','hu','mt','nl','at','pl','pt','ro','si','sk','fi','se'];

//Get the IP address of the user (more complex methods might be adopted)
//$ip_address = $_SERVER['REMOTE_ADDR'];
$ip_address = '68.97.42.217';
$ip_address = get_ip_address();

//Create the Reader object
$file_path = 'geolite2.mmdb';
$reader = new GeoIp2\Database\Reader( $file_path );

//Get the country ISO code
try {
    $record = $reader->country( $ip_address );
} catch ( Exception $e ) {
    return null;
}

//Get the list of the countries from the "Geolocation Locale" option.
$country_iso_code = $record->country->isoCode;


//Verify if the detected locale is present in the list of the countries.
foreach ( $european_countries as $single_country ) {
    if ( mb_strtolower( $single_country ) === mb_strtolower( $country_iso_code ) ) {
        $result = true;
    }
}

echo $result ? 'This country is part of the European union.' : 'This country is not part of the European union.';

WordPress plugins that geolocate with GeoLite2

We use GeoLite2 to display a cookie banner based on the visitor’s geographic location in the Lightweight Cookie Notice plugin for WordPress. You can inspect the source of the lite version in the Lightweight Cookie Notice Free plugin on the WordPress.org repository.

In this plugin, the administrator can enter its GeoLite2 license key in the plugin options. The plugin uses this information to automatically downloads the GeoLite2 database from the MaxMind website. WP Cron is used for updating the GeoLite2 database every week.

Another example of a plugin that uses GeoLite2 is WooCommerce. The popular e-commerce plugin uses geolocation to identify the customer location. You can find more implementation details in the WooCommerce repository.

Keep the GeoLite2 database updated

To keep the GeoLite2 database updated, you can schedule a cron job that runs the file used to update the database. I created for you a function that downloads the database (compressed with GZIP) from the MaxMind website and then decompresses the archive.

/**
 * This function downloads and extracts the MaxMind GeoLite2 database.
 */
function download_and_extract_geolite2($license_key){

    //Download the file with CURL
    $download_uri = 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=' . $license_key . '&suffix=tar.gz';
    $path = 'GeoLite2-Country.tar.gz';
    $ch = curl_init( $download_uri );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    $data = curl_exec( $ch );
    curl_close( $ch );
    file_put_contents( $path, $data );

    //Extract the downloaded archive
    try {
        $file = new PharData( $path );
        $file->extractTo( 'database/', null, true );
    } catch ( Exception $exception ) {
        echo 'Error';
    }

}

As you may have noted, the function uses the $license_key parameter. You can generate this value in the Manage License Keys section of your MaxMind account.

The "License Key" page in the MaxMind website.
The License Key page in the MaxMind website.

Note that the script above has only basic functionalities. You can improve it by moving the extracted file to a custom location, deleting the old database file, etc.