MaxMind GeoIP2 API for IP geolocation using web services and databases
—
Synchronous and asynchronous clients for accessing MaxMind's GeoIP2 and GeoLite2 web services. The clients provide access to Country, City Plus, and Insights endpoints with comprehensive authentication, error handling, and proxy support.
from collections.abc import Sequence
from typing import Optional
from geoip2.models import City, Country, Insights
from geoip2.types import IPAddressThe synchronous Client class provides blocking HTTP requests to MaxMind's web services using the requests library.
class Client:
def __init__(self, account_id: int, license_key: str, host: str = "geoip.maxmind.com",
locales: Optional[Sequence[str]] = None, timeout: float = 60,
proxy: Optional[str] = None):
"""
Create a synchronous GeoIP2 client.
Parameters:
- account_id: MaxMind account ID
- license_key: MaxMind license key
- host: Hostname for requests (default: "geoip.maxmind.com")
Use "geolite.info" for GeoLite2 web service
Use "sandbox.maxmind.com" for Sandbox GeoIP2 web service
- locales: List of locale codes for name properties (default: ['en'])
Valid codes: 'de', 'en', 'es', 'fr', 'ja', 'pt-BR', 'ru', 'zh-CN'
- timeout: Request timeout in seconds (default: 60)
- proxy: HTTP proxy URL with optional basic auth
"""
def city(self, ip_address: IPAddress = "me") -> City:
"""
Call City Plus endpoint with the specified IP.
Parameters:
- ip_address: IPv4 or IPv6 address as string, or "me" for caller's IP
Returns:
City model object containing geographic data
Raises:
- AddressNotFoundError: IP address not found in database
- AuthenticationError: Invalid credentials
- OutOfQueriesError: Account out of queries
- HTTPError: HTTP transport error
"""
def country(self, ip_address: IPAddress = "me") -> Country:
"""
Call GeoIP2 Country endpoint with the specified IP.
Parameters:
- ip_address: IPv4 or IPv6 address as string, or "me" for caller's IP
Returns:
Country model object containing country-level geographic data
Raises:
- AddressNotFoundError: IP address not found in database
- AuthenticationError: Invalid credentials
- OutOfQueriesError: Account out of queries
- HTTPError: HTTP transport error
"""
def insights(self, ip_address: IPAddress = "me") -> Insights:
"""
Call Insights endpoint with the specified IP.
Note: Insights is only supported by GeoIP2 web service, not GeoLite2.
Parameters:
- ip_address: IPv4 or IPv6 address as string, or "me" for caller's IP
Returns:
Insights model object containing comprehensive data including user behavior analytics
Raises:
- AddressNotFoundError: IP address not found in database
- AuthenticationError: Invalid credentials
- OutOfQueriesError: Account out of queries
- PermissionRequiredError: Account lacks Insights permission
- HTTPError: HTTP transport error
"""
def close(self):
"""Close underlying HTTP session and connections."""
def __enter__(self) -> "Client": ...
def __exit__(self, exc_type, exc_value, traceback): ...The AsyncClient class provides non-blocking HTTP requests using aiohttp for integration with asyncio applications.
class AsyncClient:
def __init__(self, account_id: int, license_key: str, host: str = "geoip.maxmind.com",
locales: Optional[Sequence[str]] = None, timeout: float = 60,
proxy: Optional[str] = None):
"""
Create an asynchronous GeoIP2 client.
Parameters are identical to synchronous Client.
Note: Client objects should not be shared across different event loops.
"""
async def city(self, ip_address: IPAddress = "me") -> City:
"""
Async version of city endpoint call.
Parameters and returns are identical to synchronous version.
"""
async def country(self, ip_address: IPAddress = "me") -> Country:
"""
Async version of country endpoint call.
Parameters and returns are identical to synchronous version.
"""
async def insights(self, ip_address: IPAddress = "me") -> Insights:
"""
Async version of insights endpoint call.
Parameters and returns are identical to synchronous version.
"""
async def close(self):
"""Close underlying aiohttp session and connections."""
async def __aenter__(self) -> "AsyncClient": ...
async def __aexit__(self, exc_type, exc_value, traceback): ...import geoip2.webservice
# Create client with credentials
with geoip2.webservice.Client(42, 'your_license_key') as client:
# Query an IP address
response = client.city('203.0.113.0')
# Access geographic data
print(f"Country: {response.country.name}")
print(f"City: {response.city.name}")
print(f"Coordinates: {response.location.latitude}, {response.location.longitude}")import asyncio
import geoip2.webservice
async def lookup_ip(ip_address):
async with geoip2.webservice.AsyncClient(42, 'your_license_key') as client:
response = await client.city(ip_address)
return response.country.name
# Run async function
country = asyncio.run(lookup_ip('203.0.113.0'))with geoip2.webservice.Client(42, 'license_key') as client:
# Country-level data only (faster, less detailed)
country_response = client.country('203.0.113.0')
# City-level data (includes country data plus city, subdivision, postal)
city_response = client.city('203.0.113.0')
# Insights data (includes city data plus user behavior analytics)
insights_response = client.insights('203.0.113.0')# Use GeoLite2 instead of GeoIP2
with geoip2.webservice.Client(42, 'license_key', host='geolite.info') as client:
response = client.city('203.0.113.0')
# Note: Insights is not available on GeoLite2# Custom locales, timeout, and proxy
with geoip2.webservice.Client(
account_id=42,
license_key='license_key',
locales=['es', 'en'], # Spanish first, English fallback
timeout=30, # 30 second timeout
proxy='http://proxy.example.com:8080'
) as client:
response = client.city('203.0.113.0')
print(response.country.name) # Name in Spanish if availableimport geoip2.webservice
from geoip2.errors import AddressNotFoundError, AuthenticationError, OutOfQueriesError
try:
with geoip2.webservice.Client(42, 'license_key') as client:
response = client.city('127.0.0.1') # Private IP
except AddressNotFoundError:
print("IP address not found in database")
except AuthenticationError:
print("Invalid account ID or license key")
except OutOfQueriesError:
print("Account is out of queries")IPAddress = Union[str, IPv6Address, IPv4Address]Install with Tessl CLI
npx tessl i tessl/pypi-geoip2