GeoIP2-python
geoip2 for Python: MaxMind's official client for GeoIP2 and GeoLite2 IP geolocation, over the hosted web service or local MMDB databases.
Repository Health
Technical Analysis
geoip2 is MaxMind’s official Python API for looking up IP address geolocation, network, and threat-intelligence data. It provides two interchangeable access patterns: a synchronous and asynchronous client for MaxMind’s hosted GeoIP2 and GeoLite2 web services, and a local file reader for MaxMind’s binary MMDB databases, both exposed through the same set of typed methods (city, country, asn, isp, domain, connection_type, anonymous_ip, anonymous_plus, enterprise).
Responses are returned as structured model objects with dotted attribute access (response.country.iso_code, response.location.latitude) instead of raw dictionaries, with typed exceptions for address-not-found, authentication, and rate-limit conditions. The package is maintained directly by MaxMind and serves as the reference implementation for integrating GeoIP2/GeoLite2 data into Python applications, from ad-hoc IP lookups to production request-time enrichment.
What You Get
- Unified lookup API — the same method names (city, country, asn, isp, domain, enterprise, anonymous_ip, anonymous_plus, connection_type) work against both the hosted web service and local MMDB files.
- Sync and async web service clients — geoip2.webservice.Client (requests) and AsyncClient (aiohttp) share one BaseClient implementation for URI building, auth, and error handling.
- Local database reader — geoip2.database.Reader opens GeoIP2/GeoLite2 .mmdb files directly, with an optional C-extension mode for high-throughput lookups.
- Typed exception hierarchy — AddressNotFoundError, AuthenticationError, InvalidRequestError, OutOfQueriesError, and HTTPError replace generic exceptions, with AddressNotFoundError exposing the unmatched subnet for efficient enumeration.
- Multi-locale place names — a constructor-level locales argument controls which language a record’s .names dict resolves to via its .name property.
Common Use Cases
- Request-time IP enrichment - a web app looks up country/city/ASN for each incoming request using a local GeoLite2-City.mmdb file to avoid network round-trips.
- Fraud and risk scoring - a service calls the Insights or Enterprise web service endpoint to pull confidence-scored location and anonymizer signals (VPN, Tor, proxy) for a given IP.
- Content localization - an app queries the country/subdivision for a visitor’s IP to select a default language or currency.
- Subnet enumeration and auditing - scripts use AddressNotFoundError’s returned network/prefix to walk and classify entire IP ranges efficiently.
Under The Hood
Architecture
The package has a dual-mode design: geoip2.webservice.BaseClient/Client/AsyncClient for the hosted web service API, and geoip2.database.Reader for local MMDB file lookups, both sharing a common geoip2.models/geoip2.records layer for typed model construction. Web-service-shaped nested responses use an inheritance chain (Country → City → Insights/Enterprise), while per-address database lookups use a parallel SimpleModel-based hierarchy (AnonymousIP, AnonymousPlus, ASN, ConnectionType, Domain, ISP). Reader delegates raw byte-level MMDB parsing to the external maxminddb package and only wraps its get_with_prefix_len() result into typed models via _model_for/_flat_model_for, keeping database.py a thin ~320-line adapter; webservice.py mirrors this by having BaseClient build the request URI/UA/auth while sync (requests) vs async (aiohttp) transport lives in the client subclasses, so swapping transport never touches response-shaping logic. Changing the Model/SimpleModel base in models.py would ripple through every one of the eleven model classes and every reader/client method.
Tech Stack
Python >=3.10, packaged with the uv_build backend and a committed uv.lock. Core runtime dependencies are maxminddb (MMDB binary-format parser with an optional C extension), requests for the sync web service client, and aiohttp for the async one — no ORM or web framework, since this is a client library rather than a service. Dev tooling runs pytest with pytest-httpserver to mock the web service in tests, mypy plus ruff (configured with the maximal select = ["ALL"] ruleset) for static analysis, tox-uv to drive a matrix across Python 3.10–3.14, a CodeQL workflow for security scanning, and ReadTheDocs for hosted docs.
Code Quality
Tests are organized as database_test.py, models_test.py, and webservice_test.py, with pytest-httpserver standing in for the real web service so webservice_test.py needs no live network access. CI enforces both mypy type checking and ruff check/ruff format --check against the strict ALL rule set, so types and style are both gated. Naming is consistent snake_case throughout, type hints are pervasive with from __future__ import annotations and TYPE_CHECKING-guarded imports to avoid runtime cost, and errors use an explicit typed hierarchy (GeoIP2Error base with AddressNotFoundError, AuthenticationError, InvalidRequestError, OutOfQueriesError, HTTPError, PermissionRequiredError) rather than generic exceptions.
API Design
Both backends expose an identical method surface (city(), country(), asn(), etc.), so switching from hosted web-service lookups to a local database reader — or back — requires no change to calling code beyond construction, and both support the context-manager (with ... as) pattern for cleanup. Errors are specific rather than generic: AddressNotFoundError carries the containing network/prefix, letting callers efficiently skip whole unmatched subnets, a pattern the README documents directly. Locale handling for the multi-language names dict is centralized as a single constructor argument instead of needing per-call configuration. The main friction points are that the C-extension database reader requires installing the separate libmaxminddb C library outside of pip, and the record/model class hierarchy is up to three levels deep (e.g. Insights → City → Country → Model), which can make introspection less obvious for newcomers.
Used by 3 apps in this directory
authentik
Authentication · Security
The self-hosted Identity Provider that replaces Okta, Auth0, and Entra ID with a unified SSO platform supporting SAML, OAuth2/OIDC, LDAP, RADIUS, and WebAuthn.
Odoo
ERP · CRM · Productivity
The open source ERP platform that integrates CRM, accounting, inventory, manufacturing, and 60+ business apps into one seamlessly connected suite.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.