Geo::IP(3pm)
π Geo::IP β the manual page, but make it cute
okay bestie, welcome to the Geo::IP docs π β this is the perl module page (that's the 3pm bit, iykyk) for looking up location and network information by IP address πβ¨
VERSION β it's giving version 1.51 π
β¨ SYNOPSIS β¨
no cap, here's the whole vibe in code:
use Geo::IP;
my $gi = Geo::IP->new(GEOIP_MEMORY_CACHE);
# look up IP address '24.24.24.24'
# returns undef if country is unallocated, or not defined in our database
my $country = $gi->country_code_by_addr('24.24.24.24');
$country = $gi->country_code_by_name('yahoo.com');
# $country is equal to "US"
use Geo::IP;
my $gi = Geo::IP->open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);
my $record = $gi->record_by_addr('24.24.24.24');
print $record->country_code,
$record->country_code3,
$record->country_name,
$record->region,
$record->region_name,
$record->city,
$record->postal_code,
$record->latitude,
$record->longitude,
$record->time_zone,
$record->area_code,
$record->continent_code,
$record->metro_code;
# the IPv6 support is currently only avail if you use the CAPI which is much
# faster anyway. ie: print Geo::IP->api equals to 'CAPI'
use Socket;
use Socket6;
use Geo::IP;
my $g = Geo::IP->open('/usr/local/share/GeoIP/GeoIPv6.dat') or die;
print $g->country_code_by_ipnum_v6(inet_pton AF_INET6, '::24.24.24.24');
print $g->country_code_by_addr_v6('2a02:e88::');
likeβ¦ look at all those accessor methods just sitting there serving looks π
π DESCRIPTION π
so the tea is: this module uses the GeoIP Legacy file based database. That database is literally just IP blocks as keys, and countries as values ποΈβ‘οΈπΊπΈ. And the glow-up? This database should be more complete and accurate than reverse DNS lookups β¨ periodt.
what's it for, bestie? everything:
- automatically selecting the geographically closest mirror
- analyzing your web server logs to figure out what countries your visitors are in
- credit card fraud detection
- software export controls
main character energy for all four, honestly π
π IP GEOLOCATION USAGE π
real talk, read this before you @ me: IP geolocation is inherently imprecise. Locations are often near the center of the population. Any location provided by a GeoIP database or web service should not be used to identify a particular address or household π«Ά
lowkey important: don't doxx anybody with this, bestie. that's not the vibe, that's a crime π
π IP ADDRESS TO COUNTRY DATABASES π
free monthly updates?? yes bestie, obsessed:
http://dev.maxmind.com/geoip/geolite
This free database is similar to the database contained in IP::Country, as well as many paid databases π. It uses ARIN, RIPE, APNIC, and LACNIC whois to obtain the IP->Country mappings.
want it more accurate? okay, rich girl π
If you require greater accuracy, MaxMind offers a database on a paid subscription basis. Also included with this is a service that updates your database automatically each month, by running a program called geoipupdate included with the C API from a cronjob β°. For more details on the differences between the free and paid databases, see:
http://www.maxmind.com/en/geolocation_landing
do NOT miss the city database, described in Geo::IP::Record ποΈβ¨
And make sure to use the geolite-mirror-simple.pl script from the example directory to stay current with the databases πΈ
π₯ BENCHMARK π₯
the lookups are fast. like, fast fast. this is my laptop (examples/benchmark.pl):
Benchmark: running city_mem, city_std, country_mem, country_std, country_v6_mem, country_v6_std, isp_mem, isp_std for at least 10 CPU seconds...
city_mem: 10.3121 wallclock secs (10.30 usr + 0.01 sys = 10.31 CPU) @ 387271.48/s (n=3992769)
city_std: 10.0658 wallclock secs ( 2.86 usr + 7.17 sys = 10.03 CPU) @ 54392.62/s (n=545558)
country_mem: 10.1772 wallclock secs (10.16 usr + 0.00 sys = 10.16 CPU) @ 1077507.97/s (n=10947481)
country_std: 10.1432 wallclock secs ( 2.30 usr + 7.85 sys = 10.15 CPU) @ 83629.56/s (n=848840)
country_v6_mem: 10.2579 wallclock secs (10.25 usr + -0.00 sys = 10.25 CPU) @ 365997.37/s (n=3751473)
country_v6_std: 10.8541 wallclock secs ( 1.77 usr + 9.07 sys = 10.84 CPU) @ 10110.42/s (n=109597)
isp_mem: 10.147 wallclock secs (10.13 usr + 0.01 sys = 10.14 CPU) @ 590109.66/s (n=5983712)
isp_std: 10.0484 wallclock secs ( 2.71 usr + 7.33 sys = 10.04 CPU) @ 73186.35/s (n=734791)
a million lookups a second on country_memβ¦ ate and left no crumbs π
π
π¦ CLASS METHODS π¦
$gi = Geo::IP->new( $flags );
Constructs a new Geo::IP object with the default database located inside your system's datadir, typically /usr/local/share/GeoIP/GeoIP.dat πβ¨
now the flags, bestie, listen up:
Flags can be set to either GEOIP_STANDARD, or β for faster performance (at a cost of using more memory π) β GEOIP_MEMORY_CACHE. When using memory cache you can force a reload if the file is updated by setting GEOIP_CHECK_CACHE π. GEOIP_INDEX_CACHE caches the most frequently accessed index portion of the database, resulting in faster lookups than GEOIP_STANDARD, but less memory usage than GEOIP_MEMORY_CACHE β useful for larger databases such as GeoIP Legacy Organization and GeoIP City ποΈ. Note, for GeoIP Country, Region and Netspeed databases, GEOIP_INDEX_CACHE is equivalent to GEOIP_MEMORY_CACHE.
lore drop π΅: Prior to geoip-api version 1.6.3, the C API would leak diagnostic messages ontostderrunconditionally. From Geo::IP v1.44 onwards, the flag squelching this behavior (GEOIP_SILENCE) is implicitly added to the flags passed innew(),open(), andopen_type()π€«
To combine flags, use the bitwise OR operator, |. For example, to cache the database in memory, but check for an updated GeoIP.dat file, use:
Geo::IP->new( GEOIP_MEMORY_CACHE | GEOIP_CHECK_CACHE );
$gi = Geo::IP->open( $database_filename, $flags );
Constructs a new Geo::IP object with the database located at $database_filename ππ«Ά
$gi = Geo::IP->open_type( $database_type, $flags );
Constructs a new Geo::IP object with the $database_type database located in the standard location. For example:
$gi = Geo::IP->open_type( GEOIP_CITY_EDITION_REV1 , GEOIP_STANDARD );
opens the database file in the standard location for GeoIP Legacy City, typically /usr/local/share/GeoIP/GeoIPCity.dat β¨
okay bestie that's part 1, the rest is comingβ¦ stay tuned π
π OBJECT METHODS π
okay bestie, this is the part you actually came for β the stuff you call on a $gi object once you've already opened the database. every single one, no skipping, let's go. π«Ά
$code = $gi->country_code_by_addr( $ipaddr );β feed it an IP address, get back the ISO 3166 country code. two letters, that's the whole vibe. β¨$code = $gi->country_code_by_name( $hostname );β same energy, but you hand it a hostname instead. it returns the ISO 3166 country code for that hostname. πΈ$code = $gi->country_code3_by_addr( $ipaddr );β like the above but β¨threeβ¨ letters, fam. returns the 3 letter country code for an IP address.$code = $gi->country_code3_by_name( $hostname );β the 3 letter country code, but for a hostname. periods.$name = $gi->country_name_by_addr( $ipaddr );β not an abbreviation this time, the whole full government name. returns the full country name for an IP address. π$name = $gi->country_name_by_name( $hostname );β full country name, hostname edition. iconic.$r = $gi->record_by_addr( $ipaddr );β and now for the glow-up: returns aGeo::IP::Recordobject containing the city location for an IP address. yes it's an object. yes you're gonna be obsessed. π$r = $gi->record_by_name( $hostname );β aGeo::IP::Recordobject with the city location, but for a hostname.$org = $gi->org_by_addr( $ipaddr );β β οΈ deprecated, use"name_by_addr"instead. returns the Organization, ISP name or Domain Name for an IP address.$org = $gi->org_by_name( $hostname );β β οΈ deprecated, use"name_by_name"instead. returns the Organization, ISP name or Domain Name for a hostname.$info = $gi->database_info;β returns the database string, which includes the version, the date, the build number and the copyright notice. receipts! π§Ύ$old_charset = $gi->set_charset( $charset );β sets the charset for the city name. it defaults toGEOIP_CHARSET_ISO_8859_1. want UTF8? passGEOIP_CHARSET_UTF8toset_charset. and heads up: for perl >= 5.008 the utf8 flag is honored. π€$charset = $gi->charset;β gets the charset that's currently in use. no cap.( $country, $region ) = $gi->region_by_addr('24.24.24.24');β returns a list containing country and region. if the region and/or the country is unknown,undefcomes back at you. and yeah, this only works for region databases. π( $country, $region ) = $gi->region_by_name('www.xyz.com');β list with country and region, hostname version. if region and/or country is unknown you getundef. again: only works for region databases, bestie.$netmask = $gi->last_netmask;β gets the netmask of the network block from the last lookup.$gi->netmask(12);β sets the netmask for the last lookup. πͺmy ( $from, $to ) = $gi->range_by_ip('24.24.24.24');β returns the start and the end of the current network block. and the method tries to join several continuous netblocks together, which is lowkey overachieving of it. π«‘$api = $gi->api or $api = Geo::IP->apiβ returns the currently used API. so like:
# prints either CAPI or PurePerl
print Geo::IP->api;
$continent = $gi->continent_code_by_country_code('US');β returns the continent code by country code. give it a country, get a continent. π$dbe = $gi->database_editionβ returns thedatabase_editionof the currently opened database. so you can do stuff like:
if ( $gi->database_edition == GEOIP_COUNTRY_EDITION ){
...
}
$isp = $gi->isp_by_addr('24.24.24.24');β returns the isp for24.24.24.24. π‘$isp = $gi->isp_by_name('www.maxmind.com');β returns the isp forwww.something.de.my $time_zone = $gi->time_zone('US', 'AZ');β returns the time zone for country/region. watch how it behaves, because the examples are giving everything:
# undef
print $gi->time_zone('US', '');
# America/Phoenix
print $gi->time_zone('US', 'AZ');
# Europe/Berlin
print $gi->time_zone('DE', '00');
# Europe/Berlin
print $gi->time_zone('DE', '');
$id = $gi->id_by_addr('24.24.24.24');β returns thecountry_idfor24.24.24.24. thecountry_idmight be useful as an array index. and remember:0is unknown. π«$id = $gi->id_by_name('www.maxmind.com');β returns thecountry_idforwww.maxmind.com. also might be useful as an array index. also0is unknown.
and now, the IPv6 girlies. you knew she was coming. π¦
$cc = $gi->country_code3_by_addr_v6('::24.24.24.24');$cc = $gi->country_code3_by_name_v6('ipv6.google.com');$cc = $gi->country_code_by_addr_v6('2a02:ea0::');$cc = $gi->country_code_by_ipnum_v6($ipnum);β and here's the full recipe so you can actually run it:
use Socket;
use Socket6;
use Geo::IP;
my $g = Geo::IP->open('/usr/local/share/GeoIP/GeoIPv6.dat') or die;
print $g->country_code_by_ipnum_v6(inet_pton AF_INET6, '::24.24.24.24');
$cc = $gi->country_code_by_name_v6('ipv6.google.com');name_by_addrβ returns the Organization, ISP name or Domain Name for a IP address.name_by_addr_v6β returns the Organization, ISP name or Domain Name for an IPv6 address.name_by_ipnum_v6β returns the Organization, ISP name or Domain Name for an ipnum.name_by_nameβ returns the Organization, ISP name or Domain Name for a hostname.name_by_name_v6β returns the Organization, ISP name or Domain Name for a hostname.org_by_addr_v6β β οΈ deprecated, use"name_by_addr_v6". returns the Organization, ISP name or Domain Name for an IPv6 address.org_by_name_v6β β οΈ deprecated, use"name_by_name_v6". returns the Organization, ISP name or Domain Name for a hostname.teredoβ returns the current setting for teredo. π³οΈenable_teredoβ enable / disable teredo, like so:
$gi->enable_teredo(1); # enable
$gi->enable_teredo(0); # disable
lib_versionβ but only flex it if you're on CAPI, bestie:
if ( $gi->api eq 'CAPI' ){
print $gi->lib_version;
}
π ISSUE TRACKER AND GIT repo π
it's available from GitHub, see:
https://github.com/maxmind/geoip-api-perl
no gatekeeping here. come hang out. β¨
π SEE ALSO π
GeoIP2β database reader for the GeoIP2 format. (the newer sibling, fyi π)
π SUPPORT π
bugs may be submitted through <https://github.com/maxmind/geoip-api-perl/issues>.
like, if something's broken, tell them, don't suffer in silence. π«Ά
π AUTHORS π
- Dave Rolsky <drolsky@maxmind.com>
- Greg Oschwald <goschwald@maxmind.com>
π CONTRIBUTORS π
the whole group chat, absolute legends, every single one:
- asb-cpan <asb-cpan@users.noreply.github.com>
- Boris Zentner <bzentner@maxmind.com>
- Boris Zentner <bzm@2bz.de>
- John SJ Anderson <genehack@genehack.org>
- Olaf Alders <oalders@maxmind.com>
- Philip A. Prindeville <philipp@redfish-solutions.com>
- shawniverson <shawniverson@gmail.com>
- Thomas J Mather <tjmather@maxmind.com>
- Tina Mueller <TINITA@cpan.org>
- Will Storey <will@summercat.com>
π COPYRIGHT AND LICENSE π
this software is copyright (c) 2002 - 2017 by MaxMind, Inc.
this is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
aaaand that's the whole page, bestie. this one's perl v5.42.3, dated 2026-08-19, and it's Geo::IP(3pm). you made it to the end, so proud of you β go look up some countries. ππΈβ¨
π¦ where this page comes from
- ubuntu stonking: libgeo-ip-perl 1.51-4build5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms