MaxMind IP Adress GeoIP2 and GeoLite2

Laravel Packages: MaxMind IP Adress GeoIP2 and GeoLite2

Download & Update

https://support.maxmind.com/hc/en-us/articles/4408216129947

Understanding database updates

Database Formats

https://support.maxmind.com/hc/en-us/articles/4408216157723

Format Description
MMDB format MaxMind database format has been developed especially for IP lookup
CSV format Standard CSV (comma separate values) format. CSV files can easily be imported into other database platforms like SQL

Database type & Update schedule

Database Update Schedule Description
GeoLite2 Country Every Tuesday and Friday. The country, subdivisions (regions) associated with IPv4 and IPv6 addresses worldwide.
GeoLite2 City Every Tuesday and Friday. The country, subdivisions (regions), city, and postal code associated with IPv4 and IPv6 addresses worldwide.
GeoLite2 ASN Every Tuesday and Friday. Look up the autonomous system number and autonomous system organization associated with IPv4 and IPv6 addresses
GeoIP2 Country Every Tuesday and Friday. Paid version of the GeoIP2 Country, with more detail information
GeoIP2 City Every Tuesday and Friday. Paid version of the GeoIP2 City, with more detail information
GeoIP2 Connection Type Every Tuesday. Connection type of your visitors based on their IP address. The database identifies cellular, cable/DSL, and corporate connection speeds.
GeoIP2 ISP Every Tuesday and Friday. The Internet Service Provider, organization name, and autonomous system organization and number associated with an IP address.
GeoIP2 Domain Name Every fourth Tuesday. Look up the second level domain names associated with IPv4 and IPv6 addresses.
GeoIP2 Anonymous IP Every day. GeoIP2 Anonymous IP CSV database helps protect your business by identifying proxy, VPN, hosting, and other anonymous IP addresses.
GeoIP2 Enterprise Every Tuesday and Friday. Determine geolocation data such as country, region, state, city, ZIP/postal code, and additional intelligence such as confidence factors, ISP, domain, and connection type.

Which Database type can you choose?

DO NOT import every database type to your table

You have to decide what kind of granularity that you want on your project. And choose one of them to import into your database.

GeoLite2 Country (Free & Paid)

GeoLite2 Country categorizes the data from the Country dimension, so the raw data will include country, subdivisions (regions)

GeoLite2 City (Free & Paid)

GeoLite2 City categorizes the data from the City dimension, so the raw data will include country, subdivisions (regions), city, and postal code

GeoIP2 Enterprise (Paid)

GeoIP2 Enterprise categorizes the data from the minimum dimension, so the raw data will include country, region, state, city, ZIP/postal code, and additional intelligence such as confidence factors, ISP, domain, and connection type

CSV Example

GeoLite2-Country-Locations-en.csv

geoname_id locale_code continent_code continent_name country_iso_code country_name is_in_european_union
49518 en AF Africa RW Rwanda 0
51537 en AF Africa SO Somalia 0
69543 en AS Asia YE Yemen 0
99237 en AS Asia IQ Iraq 0
102358 en AS Asia SA “Saudi Arabia” 0
130758 en AS Asia IR Iran 0

GeoLite2-Country-Blocks-IPv4.csv

network geoname_id registered_country_geoname_id represented_country_geoname_id is_anonymous_proxy is_satellite_provider
1.0.0.0/24 2077456 2077456 0 0
1.0.1.0/24 1814991 1814991 0 0
1.0.2.0/23 1814991 1814991 0 0
1.0.4.0/22 2077456 2077456 0 0
1.0.8.0/21 1814991 1814991 0 0

GeoLite2-City-Locations-en.csv

geoname_id locale_code continent_code continent_name country_iso_code country_name subdivision_1_iso_code subdivision_1_name subdivision_2_iso_code subdivision_2_name city_name metro_code time_zone is_in_european_union
1392 en AS Asia IR Iran 02 “Māzandarān” Shahr Asia/Tehran 0
7240 en AS Asia IR Iran 28 “North Khorasan” Jahan Asia/Tehran 0
10293 en AS Asia IR Iran 26 “Qazvin Province” Kaman Asia/Tehran 0
11797 en AS Asia IR Iran 02 “Māzandarān” Afra Asia/Tehran 0
14928 en AS Asia IR Iran 06 Khuzestan Lir Asia/Tehran 0
18918 en EU Europe CY Cyprus 04 Ammochostos Protaras Asia/Famagusta 1
20939 en AS Asia IR Iran 04 “West Azerbaijan Province” Post Asia/Tehran 0
24711 en AS Asia IR Iran 05 “Kermanshah Province” Aftab Asia/Tehran 0

GeoLite2-City-Blocks-IPv4.csv

network geoname_id registered_country_geoname_id represented_country_geoname_id is_anonymous_proxy is_satellite_provider postal_code latitude longitude accuracy_radius
1.0.0.0/24 2158177 2077456 0 0 3135 -37.8333 145.2375 500
1.0.1.0/24 1814991 1814991 0 0 34.7732 113.7220 1000
1.0.2.0/23 1814991 1814991 0 0 34.7732 113.7220 1000
1.0.4.0/22 2147714 2077456 0 0 2000 -33.8715 151.2006 500
1.0.8.0/21 1814991 1814991 0 0 34.7732 113.7220 1000
1.0.16.0/20 1861060 1861060 0 0 35.6897 139.6895 500
1.0.32.0/19 1814991 1814991 0 0 34.7732 113.7220 1000

Manual database download

When you login MaxMind. You can click the Download Files link on the left side menu, and you can see all available download files are on the right side.

  • GeoLite2 Country
  • GeoLite2 City
  • GeoLite2 ASN

Manual database download

Database download limits

Feature Description
Database download limits 2,000 / day

Automate database updates

Directly downloading databases

In order to download the databases from a script or program, please use the permalinks found on the GeoIP download page.

  1. In the “Download Links” column, click “Get Permalink(s)” for the desired database.
  2. Copy the permalink(s) provided in the modal window.
  3. Replace YOUR_LICENSE_KEY with your license key.
  4. If you are using wget or curl from a shell script, please be sure to quote the URL.
Checking for the Latest Release Date
curl -I 'https://download.maxmind.com/app/geoip_download?edition_id=GeoIP2-City-CSV&license_key=YOUR_LICENSE_KEY&suffix=zip'
Type Permalinks
GeoLite2 ASN mmdb Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-ASN&license_key=YOUR_LICENSE_KEY&suffix=tar.gz
GeoLite2 ASN CSV Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-ASN-CSV&license_key=YOUR_LICENSE_KEY&suffix=zip
GeoLite2 City mmdb Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=YOUR_LICENSE_KEY&suffix=tar.gz
GeoLite2 City CSV Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City-CSV&license_key=YOUR_LICENSE_KEY&suffix=zip
GeoLite2 ASN mmdb Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_LICENSE_KEY&suffix=tar.gz
GeoLite2 ASN CSV Format https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=YOUR_LICENSE_KEY&suffix=zip

Importing Databases (PostgreSQL)

https://dev.maxmind.com/geoip/importing-databases?lang=en

https://dev.maxmind.com/geoip/importing-databases/postgresql?lang=en

Create a table for network data

  • GeoLite2-City-Blocks-IPv4.csv
  • GeoLite2-City-Blocks-IPv6.csv
  • GeoLite2-Country-Blocks-IPv4.csv
  • GeoLite2-Country-Blocks-IPv6.csv

geoip2_network table schema

-- official version
create table geoip2_network (
  network cidr not null,
  geoname_id int,
  registered_country_geoname_id int,
  represented_country_geoname_id int,
  is_anonymous_proxy bool,
  is_satellite_provider bool,
  postal_code text,
  latitude numeric,
  longitude numeric,
  accuracy_radius int
);

-- or https://colinwilson.uk/2019/07/22/how-to-import-maxminds-geolite2-database-to-postgresql/

CREATE TABLE geoip2_network (
    network cidr,
    geoname_id bigint,
    registered_country_geoname_id bigint,
    represented_country_geoname_id bigint,
    is_anonymous_proxy bool,
    is_satellite_provider bool,
    postal_code varchar(8),
    latitude decimal(9,6),
    longitude decimal(9,6),
    accuracy_radius smallint
);

Index our table for faster searching

create index on geoip2_network using gist (network inet_ops);

Full Laravel migration for geoip2_network table

Hint: You have to install tpetry/laravel-postgresql-enhanced packages to enable the ipNetwork field on the PostgreSQL

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('geoip2_network', function (Blueprint $table) {
            $table->ipNetwork('network');
            $table->bigInteger('geoname_id')->nullable();
            $table->bigInteger('registered_country_geoname_id')->nullable();
            $table->bigInteger('represented_country_geoname_id')->nullable();
            $table->boolean('is_anonymous_proxy')->nullable();
            $table->boolean('is_satellite_provider')->nullable();
            $table->text('postal_code')->nullable();
            $table->decimal('latitude', 9, 6)->nullable();
            $table->decimal('longitude', 9, 6)->nullable();
            $table->integer('accuracy_radius')->nullable();

            $table->dateTimeTz('created_at')->useCurrent();
            $table->dateTimeTz('updated_at')->useCurrent();
        });

        DB::statement('CREATE INDEX gn_network ON geoip2_network USING gist (network inet_ops)');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('geoip2_network');
    }
};

Load data into the network table

-- Official version
\copy geoip2_network(
  network, geoname_id, registered_country_geoname_id, represented_country_geoname_id,
  is_anonymous_proxy, is_satellite_provider, postal_code, latitude, longitude, accuracy_radius
) from 'GeoIP2-City-Blocks-IPv4.csv' with (format csv, header);

\copy geoip2_network(
  network, geoname_id, registered_country_geoname_id, represented_country_geoname_id,
  is_anonymous_proxy, is_satellite_provider, postal_code, latitude, longitude, accuracy_radius
) from 'GeoIP2-City-Blocks-IPv6.csv' with (format csv, header);


/* If user is not a superuser or member of the pg_read_server_files role use
psql's \copy meta command to import CSV files to database */
copy geoip2_network from '/tmp/GeoLite2-City-Blocks-IPv4.csv' delimiter ',' csv header;
copy geoip2_network from '/tmp/GeoLite2-City-Blocks-IPv6.csv' delimiter ',' csv header;

Load data into the network table

Load data into the network table

Test IP query

select * from geoip2_network where network >> '146.243.121.22';

Create a table for locations data

  • GeoLite2-City-Locations-de.csv
  • GeoLite2-City-Locations-en.csv
  • GeoLite2-City-Locations-es.csv
  • GeoLite2-City-Locations-fr.csv
  • GeoLite2-City-Locations-ja.csv
  • GeoLite2-City-Locations-pt-BR.csv
  • GeoLite2-City-Locations-ru.csv
  • GeoLite2-City-Locations-zh-CN.csv
  • GeoLite2-Country-Locations-de.csv
  • GeoLite2-Country-Locations-en.csv
  • GeoLite2-Country-Locations-es.csv
  • GeoLite2-Country-Locations-fr.csv
  • GeoLite2-Country-Locations-ja.csv
  • GeoLite2-Country-Locations-pt-BR.csv
  • GeoLite2-Country-Locations-ru.csv
  • GeoLite2-Country-Locations-zh-CN.csv

geoip2_location table schema

-- official version
create table geoip2_location (
  geoname_id int not null,
  locale_code text not null,
  continent_code text not null,
  continent_name text not null,
  country_iso_code text,
  country_name text,
  subdivision_1_iso_code text,
  subdivision_1_name text,
  subdivision_2_iso_code text,
  subdivision_2_name text,
  city_name text,
  metro_code int,
  time_zone text,
  is_in_european_union bool not null,
  primary key (geoname_id, locale_code)
);

-- or https://colinwilson.uk/2019/07/22/how-to-import-maxminds-geolite2-database-to-postgresql/

CREATE TABLE geoip2_location (
    geoname_id bigint,
    locale_code varchar(2),
    continent_code varchar(2),
    continent_name varchar(255),
    country_iso_code varchar(2),
    country_name varchar(255),
    subdivision_1_iso_code varchar(3),
    subdivision_1_name varchar(255),
    subdivision_2_iso_code varchar(3),
    subdivision_2_name varchar(255),
    city_name varchar(255),
    metro_code varchar(3),
    time_zone varchar(255),
    is_in_european_union bool
);

Full Laravel migration for geoip2_location table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('geoip2_location', function (Blueprint $table) {
            $table->bigInteger('geoname_id');
            $table->string('locale_code', 3);
            $table->text('continent_code');
            $table->text('continent_name');
            $table->text('country_iso_code')->nullable();
            $table->text('country_name')->nullable();
            $table->text('subdivision_1_iso_code')->nullable();
            $table->text('subdivision_1_name')->nullable();
            $table->text('subdivision_2_iso_code')->nullable();
            $table->text('subdivision_2_name')->nullable();
            $table->text('city_name')->nullable();
            $table->integer('metro_code')->nullable();
            $table->text('time_zone')->nullable();
            $table->boolean('is_in_european_union');

            $table->dateTimeTz('created_at')->useCurrent();
            $table->dateTimeTz('updated_at')->useCurrent();

            $table->primary(['geoname_id', 'locale_code'], 'geoip2_location_pk');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('geoip2_location');
    }
};

Load data into the locations table


\copy geoip2_location(
  geoname_id, locale_code, continent_code, continent_name, country_iso_code, country_name,
  subdivision_1_iso_code, subdivision_1_name, subdivision_2_iso_code, subdivision_2_name,
  city_name, metro_code, time_zone, is_in_european_union
) from 'GeoIP2-City-Locations-en.csv' with (format csv, header);


copy geoip2_location from '/tmp/GeoLite2-City-Locations-en.csv' delimiter ',' csv header encoding 'UTF8';

Load data into the network table

Test Query

select latitude, longitude, accuracy_radius, continent_name, country_name, subdivision_1_name, city_name
from geoip2_network net
left join geoip2_location location on (
  net.geoname_id = location.geoname_id
  and location.locale_code = 'en'
)
where network >> '146.243.121.22';

Create a table for asn data

  • GeoLite2-ASN-Blocks-IPv4.csv
  • GeoLite2-ASN-Blocks-IPv6.csv

geoip2_asn table schema

CREATE TABLE geoip2_asn (
    network cidr,
    autonomous_system_number bigint,
	autonomous_system_organization varchar(255)
);

CREATE INDEX asn_blocks_network_idx ON asn_blocks USING gist (network inet_ops);

Full Laravel migration for geoip2_asn table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('geoip2_asn', function (Blueprint $table) {
            $table->ipNetwork('network');
            $table->bigInteger('autonomous_system_number');
            $table->string('autonomous_system_organization', 255);

            $table->dateTimeTz('created_at')->useCurrent();
            $table->dateTimeTz('updated_at')->useCurrent();
        });

        DB::statement('CREATE INDEX ga_network ON geoip2_asn USING gist (network inet_ops)');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('geoip2_asn');
    }
};

Load data into the asn table

copy geoip2_asn from '/tmp/GeoLite2-ASN-Blocks-IPv4.csv' delimiter ',' csv header;
copy geoip2_asn from '/tmp/GeoLite2-ASN-Blocks-IPv6.csv' delimiter ',' csv header;

Test Query

select * from geoip2_asn where network >> '146.243.121.22';

License

The GeoLite2 end-user license agreement incorporates components of the Creative Commons Attribution-ShareAlike 4.0 International License. The attribution requirement may be met by including the following in all advertising and documentation mentioning features of or use of GeoLite2 data:

This product includes GeoLite2 data created by MaxMind, available from
<a href="https://www.maxmind.com">https://www.maxmind.com</a>.

Laravel Geoip Packages

https://lyften.com/projects/laravel-geoip/

https://github.com/Torann/laravel-geoip

Install

composer require torann/geoip
php artisan vendor:publish --provider="Torann\GeoIP\GeoIPServiceProvider" --tag=config

Setting your license key to .env

You can get your MaxMind user_id and license key from your account License Key Page

MAXMIND_USER_ID=
MAXMIND_LICENSE_KEY=

Get MaxMind License Key

Setting config/geoip.php

Update 'service' => 'maxmind_database' to load the local geoip file database

// config/geoip.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Logging Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure the log settings for when a location is not found
    | for the IP provided.
    |
    */

    'log_failures' => true,

    /*
    |--------------------------------------------------------------------------
    | Include Currency in Results
    |--------------------------------------------------------------------------
    |
    | When enabled the system will do it's best in deciding the user's currency
    | by matching their ISO code to a preset list of currencies.
    |
    */

    'include_currency' => true,

    /*
    |--------------------------------------------------------------------------
    | Default Service
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default storage driver that should be used
    | by the framework.
    |
    | Supported: "maxmind_database", "maxmind_api", "ipapi"
    |
    */

    'service' => 'maxmind_database',

    /*
    |--------------------------------------------------------------------------
    | Storage Specific Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure as many storage drivers as you wish.
    |
    */

    'services' => [

        'maxmind_database' => [
            'class' => \Torann\GeoIP\Services\MaxMindDatabase::class,
            'database_path' => storage_path('app/geoip.mmdb'),
            'update_url' => sprintf('https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')),
            'locales' => ['en'],
        ],

        'maxmind_api' => [
            'class' => \Torann\GeoIP\Services\MaxMindWebService::class,
            'user_id' => env('MAXMIND_USER_ID'),
            'license_key' => env('MAXMIND_LICENSE_KEY'),
            'locales' => ['en'],
        ],

        'ipapi' => [
            'class' => \Torann\GeoIP\Services\IPApi::class,
            'secure' => true,
            'key' => env('IPAPI_KEY'),
            'continent_path' => storage_path('app/continents.json'),
            'lang' => 'en',
        ],

        'ipgeolocation' => [
            'class' => \Torann\GeoIP\Services\IPGeoLocation::class,
            'secure' => true,
            'key' => env('IPGEOLOCATION_KEY'),
            'continent_path' => storage_path('app/continents.json'),
            'lang' => 'en',
        ],

        'ipdata' => [
            'class'  => \Torann\GeoIP\Services\IPData::class,
            'key'    => env('IPDATA_API_KEY'),
            'secure' => true,
        ],

        'ipfinder' => [
            'class'  => \Torann\GeoIP\Services\IPFinder::class,
            'key'    => env('IPFINDER_API_KEY'),
            'secure' => true,
            'locales' => ['en'],
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Default Cache Driver
    |--------------------------------------------------------------------------
    |
    | Here you may specify the type of caching that should be used
    | by the package.
    |
    | Options:
    |
    |  all  - All location are cached
    |  some - Cache only the requesting user
    |  none - Disable cached
    |
    */

    'cache' => 'all',

    /*
    |--------------------------------------------------------------------------
    | Cache Tags
    |--------------------------------------------------------------------------
    |
    | Cache tags are not supported when using the file or database cache
    | drivers in Laravel. This is done so that only locations can be cleared.
    |
    */

    'cache_tags' => ['torann-geoip-location'],

    /*
    |--------------------------------------------------------------------------
    | Cache Expiration
    |--------------------------------------------------------------------------
    |
    | Define how long cached location are valid.
    |
    */

    'cache_expires' => 60,

    /*
    |--------------------------------------------------------------------------
    | Default Location
    |--------------------------------------------------------------------------
    |
    | Return when a location is not found.
    |
    */

    'default_location' => [
        'ip' => '127.0.0.0',
        'iso_code' => 'US',
        'country' => 'United States',
        'city' => 'New Haven',
        'state' => 'CT',
        'state_name' => 'Connecticut',
        'postal_code' => '06510',
        'lat' => 41.31,
        'lon' => -72.92,
        'timezone' => 'America/New_York',
        'continent' => 'NA',
        'default' => true,
        'currency' => 'USD',
    ],

];

Get the latest MaxMind geoip file database

php artisan geoip:update

Here is the maxmind_database setting, so the file database will be stored at the storage_path('app/geoip.mmdb').

And the update_url will get from the sprintf('https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')). If you want to change your database update url then you can change the update_url

'maxmind_database' => [
    'class' => \Torann\GeoIP\Services\MaxMindDatabase::class,
    'database_path' => storage_path('app/geoip.mmdb'),
    'update_url' => sprintf('https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')),
    'locales' => ['en'],
],

Get IP location

geoip()->getLocation('27.974.399.65');

Reference

Packages

Service

File Format

Import

Database

API