MCPcopy Create free account
hub / github.com/oschwald/maxminddb-golang

github.com/oschwald/maxminddb-golang @v2.4.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.4.1 ↗ · + Follow
485 symbols 2,113 edges 37 files ⚖ ISC 195 documented · 40% 52 cross-repo links updated 5d agov2.5.0 · 2026-08-08★ 7454 open issues

Browse by type

Functions 386 Types & classes 99
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

MaxMind DB Reader for Go

Go Reference

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.

Installation

go get github.com/oschwald/maxminddb-golang/v2

Version 2.0 Features

Version 2.0 includes significant improvements:

  • Modern API: Uses netip.Addr instead of net.IP for better performance
  • Custom Unmarshaling: Implement Unmarshaler interface for zero-allocation decoding
  • Network Iteration: Iterate over all networks in a database with Networks() and NetworksWithin()
  • Enhanced Performance: Optimized data structures and decoding paths
  • Better Error Handling: More detailed error types and improved debugging
  • Integrity Checks: Validate databases with Reader.Verify() and access metadata helpers such as Metadata.BuildTime()

See MIGRATION.md for guidance on updating existing v1 code.

Quick Start

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"])
}

Usage Patterns

Basic Lookup

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)

Custom Struct Decoding

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)

High-Performance Custom Unmarshaling

Import github.com/oschwald/maxminddb-golang/v2/mmdbdata for the decoder type.

type FastCity struct {
    CountryISO string
    CityName   string
}

func (c *FastCity) UnmarshalMaxMindDB(d *mmdbdata.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
}

Network Iteration

// 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
}

Path-Based Decoding

var countryCode string
err = db.Lookup(ip).DecodePath(&countryCode, "country", "iso_code")

var cityName string
err = db.Lookup(ip).DecodePath(&cityName, "city", "names", "en")

Supported Database Types

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.

Performance Tips

  1. Reuse Reader instances: Lookups, decoding, and iteration are safe to run concurrently. Close invalidates outstanding results and should run after readers are done.
  2. Use specific structs: Only decode the fields you need rather than using any
  3. Implement Unmarshaler: For high-throughput applications, implement custom unmarshaling
  4. Consider caching: Use Result.Offset() as a cache key for database records

Getting Database Files

Free GeoLite2 Databases

Download from MaxMind's GeoLite page.

Documentation

Requirements

  • Go 1.25 or later
  • MaxMind DB file in .mmdb format

Contributing

Contributions welcome! Please fork the repository and open a pull request with your changes.

License

This is free software, licensed under the ISC License.

Extension points exported contracts — how you extend this code

browse all types & interfaces →

Core symbols most depended-on inside this repo

browse all functions →

Shape

Function 244
Method 142
Struct 81
TypeAlias 10
Interface 5
FuncType 3

Languages

Go100%

Modules by API surface

reader_test.go89 symbols
internal/decoder/reflection.go59 symbols
internal/decoder/nested_unmarshaler_test.go44 symbols
internal/decoder/reflection_test.go31 symbols
internal/decoder/decoder.go28 symbols
internal/decoder/decoder_test.go26 symbols
internal/decoder/data_decoder.go25 symbols
reader.go24 symbols
internal/decoder/field_precedence_test.go15 symbols
internal/mmdberrors/context.go13 symbols
traverse.go12 symbols
traverse_test.go11 symbols

For agents

$ claude mcp add maxminddb-golang \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page