This is a Go reader for the MaxMind DB format. Although this can be used to read GeoLite2 and GeoIP2 databases, geoip2 provides a higher-level API for doing so.
This is not an official MaxMind API.
go get github.com/oschwald/maxminddb-golang/v2
Version 2.0 includes significant improvements:
- Modern API: Uses
netip.Addr
instead ofnet.IP
for better performance - Custom Unmarshaling: Implement
Unmarshaler
interface for zero-allocation decoding - Network Iteration: Iterate over all networks in a database with
Networks()
andNetworksWithin()
- Enhanced Performance: Optimized data structures and decoding paths
- Go 1.24+ Support: Takes advantage of modern Go features including iterators
- Better Error Handling: More detailed error types and improved debugging
package main
import (
"fmt"
"log"
"net/netip"
"github.com/oschwald/maxminddb-golang/v2"
)
func main() {
db, err := maxminddb.Open("GeoLite2-City.mmdb")
if err != nil {
log.Fatal(err)
}
defer db.Close()
ip, err := netip.ParseAddr("81.2.69.142")
if err != nil {
log.Fatal(err)
}
var record struct {
Country struct {
ISOCode string `maxminddb:"iso_code"`
Names map[string]string `maxminddb:"names"`
} `maxminddb:"country"`
City struct {
Names map[string]string `maxminddb:"names"`
} `maxminddb:"city"`
}
err = db.Lookup(ip).Decode(&record)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Country: %s (%s)\n", record.Country.Names["en"], record.Country.ISOCode)
fmt.Printf("City: %s\n", record.City.Names["en"])
}
db, err := maxminddb.Open("GeoLite2-City.mmdb")
if err != nil {
log.Fatal(err)
}
defer db.Close()
var record any
ip := netip.MustParseAddr("1.2.3.4")
err = db.Lookup(ip).Decode(&record)
type City struct {
Country struct {
ISOCode string `maxminddb:"iso_code"`
Names struct {
English string `maxminddb:"en"`
German string `maxminddb:"de"`
} `maxminddb:"names"`
} `maxminddb:"country"`
}
var city City
err = db.Lookup(ip).Decode(&city)
type FastCity struct {
CountryISO string
CityName string
}
func (c *FastCity) UnmarshalMaxMindDB(d *maxminddb.Decoder) error {
for key, err := range d.ReadMap() {
if err != nil {
return err
}
switch string(key) {
case "country":
for countryKey, countryErr := range d.ReadMap() {
if countryErr != nil {
return countryErr
}
if string(countryKey) == "iso_code" {
c.CountryISO, err = d.ReadString()
if err != nil {
return err
}
} else {
if err := d.SkipValue(); err != nil {
return err
}
}
}
default:
if err := d.SkipValue(); err != nil {
return err
}
}
}
return nil
}
// Iterate over all networks in the database
for result := range db.Networks() {
var record struct {
Country struct {
ISOCode string `maxminddb:"iso_code"`
} `maxminddb:"country"`
}
err := result.Decode(&record)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %s\n", result.Prefix(), record.Country.ISOCode)
}
// Iterate over networks within a specific prefix
prefix := netip.MustParsePrefix("192.168.0.0/16")
for result := range db.NetworksWithin(prefix) {
// Process networks within 192.168.0.0/16
}
var countryCode string
err = db.Lookup(ip).DecodePath(&countryCode, "country", "iso_code")
var cityName string
err = db.Lookup(ip).DecodePath(&cityName, "city", "names", "en")
This library supports all MaxMind DB (.mmdb) format databases, including:
MaxMind Official Databases:
- GeoLite/GeoIP City: Comprehensive location data including city, country, subdivisions
- GeoLite/GeoIP Country: Country-level geolocation data
- GeoLite ASN: Autonomous System Number and organization data
- GeoIP Anonymous IP: Anonymous network and proxy detection
- GeoIP Enterprise: Enhanced City data with additional business fields
- GeoIP ISP: Internet service provider information
- GeoIP Domain: Second-level domain data
- GeoIP Connection Type: Connection type identification
Third-Party Databases:
- DB-IP databases: Compatible with DB-IP's .mmdb format databases
- IPinfo databases: Works with IPinfo's MaxMind DB format files
- Custom databases: Any database following the MaxMind DB file format specification
The library is format-agnostic and will work with any valid .mmdb file regardless of the data provider.
- Reuse Reader instances: The
Reader
is thread-safe and should be reused across goroutines - Use specific structs: Only decode the fields you need rather than using
any
- Implement Unmarshaler: For high-throughput applications, implement custom unmarshaling
- Consider caching: Use
Result.Offset()
as a cache key for database records
Download from MaxMind's GeoLite page.
- Go 1.23 or later
- MaxMind DB file in .mmdb format
Contributions welcome! Please fork the repository and open a pull request with your changes.
This is free software, licensed under the ISC License.