- Notifications
You must be signed in to change notification settings - Fork207
Java API for GeoIP2 webservice client and database reader
License
maxmind/GeoIP2-java
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This distribution provides an API for the GeoIP2 and GeoLite2webservices anddatabases.
We recommend installing this package withMaven.To do this, add the dependency to your pom.xml:
<dependency> <groupId>com.maxmind.geoip2</groupId> <artifactId>geoip2</artifactId> <version>5.0.0</version> </dependency>
Add the following to yourbuild.gradle file:
repositories { mavenCentral()}dependencies { compile 'com.maxmind.geoip2:geoip2:5.0.0'}If you are unable to use Maven or Gradle, you may include thegeoip2.jarfile and its dependencies in your classpath. Download the JAR files from theGitHub Releases page.
IP geolocation is inherently imprecise. Locations are often near the center ofthe population. Any location provided by a GeoIP2 database or web serviceshould not be used to identify a particular address or household.
To use the web service API, you must create a newWebServiceClient using theWebServiceClient.Builder. You must provide theBuilder constructor yourMaxMindaccountId andlicenseKey. To use the GeoLite2 web services insteadof GeoIP2, set thehost method on the builder togeolite.info. To usethe Sandbox GeoIP2 web services instead of the production GeoIP2 webservices, set thehost method on the builder tosandbox.maxmind.com.You may also set atimeout or set thelocales fallback order using themethods on theBuilder. After you have created theWebServiceClient,you may then call the method corresponding to a specific web service, passingit the IP address you want to look up.
If the request succeeds, the method call will return a model class for the endpoint you called. This model in turn contains multiple record classes, each ofwhich represents part of the data returned by the web service.
If the request fails, the client class throws an exception.
TheWebServiceClient object is safe to share across threads. If you aremaking multiple requests, the object should be reused so that new connectionsare not created for each request.
See theAPI documentation formore details.
// This creates a WebServiceClient object that is thread-safe and can be// reused across requests. Reusing the object will allow it to keep// connections alive for future requests.//// Replace "42" with your account ID and "license_key" with your license key.// To use the GeoLite2 web service instead of the GeoIP2 web service, call the// host method on the builder with "geolite.info", e.g.// new WebServiceClient.Builder(42, "license_key").host("geolite.info").build()// To use the Sandbox GeoIP2 web service instead of the production GeoIP2// web service, call the host method on the builder with// "sandbox.maxmind.com", e.g.// new WebServiceClient.Builder(42, "license_key").host("sandbox.maxmind.com").build()WebServiceClientclient =newWebServiceClient.Builder(42,"license_key") .build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");// Do the lookupCountryResponseresponse =client.country(ipAddress);Countrycountry =response.getCountry();System.out.println(country.getIsoCode());// 'US'System.out.println(country.getName());// 'United States'System.out.println(country.getNames().get("zh-CN"));// '美国'
// This creates a WebServiceClient object that is thread-safe and can be// reused across requests. Reusing the object will allow it to keep// connections alive for future requests.//// Replace "42" with your account ID and "license_key" with your license key.// To use the GeoLite2 web service instead of the GeoIP2 web service, call the// host method on the builder with "geolite.info", e.g.// new WebServiceClient.Builder(42, "license_key").host("geolite.info").build()// To use the Sandbox GeoIP2 web service instead of the production GeoIP2// web service, call the host method on the builder with// "sandbox.maxmind.com", e.g.// new WebServiceClient.Builder(42, "license_key").host("sandbox.maxmind.com").build()WebServiceClientclient =newWebServiceClient.Builder(42,"license_key") .build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");// Do the lookupCityResponseresponse =client.city(ipAddress);Countrycountry =response.getCountry();System.out.println(country.getIsoCode());// 'US'System.out.println(country.getName());// 'United States'System.out.println(country.getNames().get("zh-CN"));// '美国'Subdivisionsubdivision =response.getMostSpecificSubdivision();System.out.println(subdivision.getName());// 'Minnesota'System.out.println(subdivision.getIsoCode());// 'MN'Citycity =response.getCity();System.out.println(city.getName());// 'Minneapolis'Postalpostal =response.getPostal();System.out.println(postal.getCode());// '55455'Locationlocation =response.getLocation();System.out.println(location.getLatitude());// 44.9733System.out.println(location.getLongitude());// -93.2323
// This creates a WebServiceClient object that is thread-safe and can be// reused across requests. Reusing the object will allow it to keep// connections alive for future requests.//// Replace "42" with your account ID and "license_key" with your license key.// Please note that the GeoLite2 web service does not support Insights.// To use the Sandbox GeoIP2 web service instead of the production GeoIP2// web service, call the host method on the builder with// "sandbox.maxmind.com", e.g.// new WebServiceClient.Builder(42, "license_key").host("sandbox.maxmind.com").build()WebServiceClientclient =newWebServiceClient.Builder(42,"license_key") .build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");// Do the lookupInsightsResponseresponse =client.insights(ipAddress);Countrycountry =response.getCountry();System.out.println(country.getIsoCode());// 'US'System.out.println(country.getName());// 'United States'System.out.println(country.getNames().get("zh-CN"));// '美国'System.out.println(country.getConfidence());// 99Subdivisionsubdivision =response.getMostSpecificSubdivision();System.out.println(subdivision.getName());// 'Minnesota'System.out.println(subdivision.getIsoCode());// 'MN'System.out.println(subdivision.getConfidence());// 90Citycity =response.getCity();System.out.println(city.getName());// 'Minneapolis'System.out.println(city.getConfidence());// 50Postalpostal =response.getPostal();System.out.println(postal.getCode());// '55455'System.out.println(postal.getConfidence());// 40Locationlocation =response.getLocation();System.out.println(location.getLatitude());// 44.9733System.out.println(location.getLongitude());// -93.2323System.out.println(location.getAccuracyRadius());// 3System.out.println(location.getTimeZone());// 'America/Chicago'System.out.println(response.getTraits().getUserType());// 'college'
To use the database API, you must create a newDatabaseReader using theDatabaseReader.Builder. You must provide theBuilder constructor either anInputStream orFile for your GeoIP2 database. You may also specify thefileMode and thelocales fallback order using the methods on theBuilderobject.
After you have created theDatabaseReader, you may then call one of theappropriate methods, e.g.,city ortryCity, for your database. Thesemethods take the IP address to be looked up. The methods with thetryprefix return anOptional object, which will be empty if the value isnot present in the database. The method without the prefix will throw anAddressNotFoundException if the address is not in the database. If youare looking up many IPs that are not contained in the database, thetrymethod will be slightly faster as they do not need to construct and throwan exception. These methods otherwise behave the same.
If the lookup succeeds, the method call will return a response class for theGeoIP2 lookup. The class in turn contains multiple record classes, each ofwhich represents part of the data returned by the database.
We recommend reusing theDatabaseReader object rather than creating a newone for each lookup. The creation of this object is relatively expensive as itmust read in metadata for the file. It is safe to share the object acrossthreads.
See theAPI documentation formore details.
The database API supports pluggable caching (by default, no caching isperformed). A simple implementation is provided bycom.maxmind.db.CHMCache.Using this cache, lookup performance is significantly improved at the cost ofa small (~2MB) memory overhead.
Usage:
newDatabaseReader.Builder(file).withCache(newCHMCache()).build();
If you are packaging the database file as a resource in a JAR file usingMaven, you mustdisable binary file filtering.Failure to do so will result inInvalidDatabaseException exceptions beingthrown when querying the database.
// A File object pointing to your GeoIP2 or GeoLite2 databaseFiledatabase =newFile("/path/to/GeoIP2-City.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.DatabaseReaderreader =newDatabaseReader.Builder(database).build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");// Replace "city" with the appropriate method for your database, e.g.,// "country".CityResponseresponse =reader.city(ipAddress);Countrycountry =response.getCountry();System.out.println(country.getIsoCode());// 'US'System.out.println(country.getName());// 'United States'System.out.println(country.getNames().get("zh-CN"));// '美国'Subdivisionsubdivision =response.getMostSpecificSubdivision();System.out.println(subdivision.getName());// 'Minnesota'System.out.println(subdivision.getIsoCode());// 'MN'Citycity =response.getCity();System.out.println(city.getName());// 'Minneapolis'Postalpostal =response.getPostal();System.out.println(postal.getCode());// '55455'Locationlocation =response.getLocation();System.out.println(location.getLatitude());// 44.9733System.out.println(location.getLongitude());// -93.2323
// A File object pointing to your GeoIP2 Anonymous IP databaseFiledatabase =newFile("/path/to/GeoIP2-Anonymous-IP.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.try (DatabaseReaderreader =newDatabaseReader.Builder(database).build()) {InetAddressipAddress =InetAddress.getByName("85.25.43.84");AnonymousIpResponseresponse =reader.anonymousIp(ipAddress);System.out.println(response.isAnonymous());// trueSystem.out.println(response.isAnonymousVpn());// falseSystem.out.println(response.isHostingProvider());// falseSystem.out.println(response.isPublicProxy());// falseSystem.out.println(response.isResidentialProxy());// falseSystem.out.println(response.isTorExitNode());//true}
// A File object pointing to your GeoIP2 Anonymous Plus databaseFiledatabase =newFile("/path/to/GeoIP-Anonymous-Plus.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.try (DatabaseReaderreader =newDatabaseReader.Builder(database).build()) {InetAddressipAddress =InetAddress.getByName("85.25.43.84");AnonymousIpResponseresponse =reader.anonymousPlus(ipAddress);System.out.println(response.getAnonymizerConfidence());// 30System.out.println(response.isAnonymous());// trueSystem.out.println(response.isAnonymousVpn());// falseSystem.out.println(response.isHostingProvider());// falseSystem.out.println(response.isPublicProxy());// falseSystem.out.println(response.isResidentialProxy());// falseSystem.out.println(response.isTorExitNode());// trueSystem.out.println(response.getNetworkLastSeen());// "2025-04-14"System.out.println(response.getProviderName());// "FooBar VPN"}
// A File object pointing to your GeoLite2 ASN databaseFiledatabase =newFile("/path/to/GeoLite2-ASN.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.try (DatabaseReaderreader =newDatabaseReader.Builder(database).build()) {InetAddressipAddress =InetAddress.getByName("128.101.101.101");AsnResponseresponse =reader.asn(ipAddress);System.out.println(response.getAutonomousSystemNumber());// 217System.out.println(response.getAutonomousSystemOrganization());// 'University of Minnesota'}
// A File object pointing to your GeoIP2 Connection-Type databaseFiledatabase =newFile("/path/to/GeoIP2-Connection-Type.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.DatabaseReaderreader =newDatabaseReader.Builder(database).build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");ConnectionTypeResponseresponse =reader.connectionType(ipAddress);// getConnectionType() returns a ConnectionType enumConnectionTypetype =response.getConnectionType();System.out.println(type);// 'Corporate'
// A File object pointing to your GeoIP2 Domain databaseFiledatabase =newFile("/path/to/GeoIP2-Domain.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.DatabaseReaderreader =newDatabaseReader.Builder(database).build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");DomainResponseresponse =reader.domain(ipAddress);System.out.println(response.getDomain());// 'umn.edu'
// A File object pointing to your GeoIP2 Enterprise databaseFiledatabase =newFile("/path/to/GeoIP2-Enterprise.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.try (DatabaseReaderreader =newDatabaseReader.Builder(database).build()) {InetAddressipAddress =InetAddress.getByName("128.101.101.101");// Use the enterprise(ip) method to do a lookup in the Enterprise databaseEnterpriseResponseresponse =reader.enterprise(ipAddress);Countrycountry =response.getCountry();System.out.println(country.getIsoCode());// 'US'System.out.println(country.getName());// 'United States'System.out.println(country.getNames().get("zh-CN"));// '美国'System.out.println(country.getConfidence());// 99Subdivisionsubdivision =response.getMostSpecificSubdivision();System.out.println(subdivision.getName());// 'Minnesota'System.out.println(subdivision.getIsoCode());// 'MN'System.out.println(subdivision.getConfidence());// 77Citycity =response.getCity();System.out.println(city.getName());// 'Minneapolis'System.out.println(city.getConfidence());// 11Postalpostal =response.getPostal();System.out.println(postal.getCode());// '55455'System.out.println(postal.getConfidence());// 5Locationlocation =response.getLocation();System.out.println(location.getLatitude());// 44.9733System.out.println(location.getLongitude());// -93.2323System.out.println(location.getAccuracyRadius());// 50}
// A File object pointing to your GeoIP2 ISP databaseFiledatabase =newFile("/path/to/GeoIP2-ISP.mmdb");// This creates the DatabaseReader object. To improve performance, reuse// the object across lookups. The object is thread-safe.DatabaseReaderreader =newDatabaseReader.Builder(database).build();InetAddressipAddress =InetAddress.getByName("128.101.101.101");IspResponseresponse =reader.isp(ipAddress);System.out.println(response.getAutonomousSystemNumber());// 217System.out.println(response.getAutonomousSystemOrganization());// 'University of Minnesota'System.out.println(response.getIsp());// 'University of Minnesota'System.out.println(response.getOrganization());// 'University of Minnesota'
For details on the possible errors returned by the web service itself,seethe GeoIP2 web servicedocumentation.
If the web service returns an explicit error document, this is thrown as anAddressNotFoundException, anAuthenticationException, anInvalidRequestException, or anOutOfQueriesException.
If some sort of transport error occurs, anHttpException is thrown. Thisis thrown when some sort of unanticipated error occurs, such as the webservice returning a 500 or an invalid error document. If the web servicerequest returns any status code besides 200, 4xx, or 5xx, this also becomesanHttpException.
Finally, if the web service returns a 200 but the body is invalid, the clientthrows aGeoIp2Exception. This exception also is the parent exception tothe above exceptions.
We strongly discourage you from using a value from anygetNames method asa key in a database or map.
These names may change between releases. Instead we recommend using one of thefollowing:
com.maxmind.geoip2.record.City-City.getGeoNameIdcom.maxmind.geoip2.record.Continent-Continent.getCodeorContinent.getGeoNameIdcom.maxmind.geoip2.record.Countryandcom.maxmind.geoip2.record.RepresentedCountry-Country.getIsoCodeorCountry.getGeoNameIdcom.maxmind.geoip2.record.Subdivision-Subdivision.getIsoCodeorSubdivision.getGeoNameId
This API fully supports use in multi-threaded applications. When using theDatabaseReader or theWebServiceClient in a multi-threaded application,we suggest creating one object and sharing that across threads.
While many of the location databases and web services return the samebasic records, the attributes populated can vary. In addition, MaxMind doesnot always have every piece of data for any given IP address.
Because of these factors, it is possible for any web service to return a recordwhere some or all of the attributes are unpopulated.
See our web-service developerdocumentation fordetails on what data each web service may return.
The only piece of data which is always returned is theip_addressavailable atlookup.getTraits().getIpAddress().
GeoNames offers web services and downloadabledatabases with data on geographical features around the world, includingpopulated places. They offer both free and paid premium data. Eachfeature is uniquely identified by ageonameId, which is an integer.
Many of the records returned by the GeoIP2 web services and databasesinclude agetGeoNameId() method. This is the ID of a geographicalfeature (city, region, country, etc.) in the GeoNames database.
Some of the data that MaxMind provides is also sourced from GeoNames. Wesource things like place names, ISO codes, and other similar data fromthe GeoNames premium data set.
If the problem you find is that an IP address is incorrectly mapped,pleasesubmit your correction to MaxMind.
If you find some other sort of mistake, like an incorrect spelling,please checkthe GeoNames site first. Onceyou've searched for a place and found it on the GeoNames map view, thereare a number of links you can use to correct data ("move", "edit","alternate names", etc.). Once the correction is part of the GeoNamesdata set, it will be automatically incorporated into future MaxMindreleases.
If you are a paying MaxMind customer and you're not sure where to submita correction, pleasecontact MaxMind supportfor help.
Please report all issues with this code using theGitHub issue tracker.
If you are having an issue with a MaxMind service that is not specificto the client API, pleasecontact MaxMind support.
MaxMind has tested this API with Java 11 and above.
Patches and pull requests are encouraged. Please include unit testswhenever possible.
The GeoIP2 Java API usesSemantic Versioning.
This software is Copyright (c) 2013-2025 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.
About
Java API for GeoIP2 webservice client and database reader
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.