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/v2Version 2.0 includes significant improvements:
- Modern API: Uses netip.Addrinstead ofnet.IPfor better performance
- Custom Unmarshaling: Implement Unmarshalerinterface 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
- Integrity Checks: Validate databases with Reader.Verify()and access metadata helpers such asMetadata.BuildTime()
See MIGRATION.md for guidance on updating existing v1 code.
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 {
	mapIter, size, err := d.ReadMap()
	if err != nil {
		return err
	}
	// Pre-allocate with correct capacity for better performance
	_ = size // Use for pre-allocation if storing map data
	for key, err := range mapIter {
		if err != nil {
			return err
		}
		switch string(key) {
		case "country":
			countryIter, _, err := d.ReadMap()
			if err != nil {
				return err
			}
			for countryKey, countryErr := range countryIter {
				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 Readeris 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.24 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.