MaxMind GeoIP2 API for IP geolocation using web services and databases
—
Local database reader for MaxMind's MMDB (MaxMind Database) format files. The Reader class provides offline IP geolocation queries with support for all MaxMind database types including City, Country, ASN, ISP, Domain, Connection-Type, Anonymous IP, Anonymous Plus, and Enterprise databases.
import os
from collections.abc import Sequence
from typing import IO, AnyStr, Optional, Union
import maxminddb
from geoip2.models import (
ASN, ISP, AnonymousIP, AnonymousPlus, City, ConnectionType,
Country, Domain, Enterprise
)
from geoip2.types import IPAddressThe Reader class provides high-performance local database lookups without requiring network connectivity.
class Reader:
def __init__(self, fileish: Union[AnyStr, int, os.PathLike, IO],
locales: Optional[Sequence[str]] = None, mode: int = MODE_AUTO):
"""
Create a GeoIP2 database reader.
Parameters:
- fileish: Path to MMDB file, file descriptor, or file-like object
- locales: List of locale codes for name properties (default: ['en'])
Valid codes: 'de', 'en', 'es', 'fr', 'ja', 'pt-BR', 'ru', 'zh-CN'
- mode: Database access mode (default: MODE_AUTO)
"""
def city(self, ip_address: IPAddress) -> City:
"""
Get City object for the IP address from City or Enterprise database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
City model object with geographic data including city, country, subdivisions
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support city lookups
"""
def country(self, ip_address: IPAddress) -> Country:
"""
Get Country object for the IP address from Country, City, or Enterprise database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
Country model object with country-level geographic data
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support country lookups
"""
def asn(self, ip_address: IPAddress) -> ASN:
"""
Get ASN object for the IP address from ASN database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
ASN model object with autonomous system information
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support ASN lookups
"""
def isp(self, ip_address: IPAddress) -> ISP:
"""
Get ISP object for the IP address from ISP database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
ISP model object with ISP and organization information
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support ISP lookups
"""
def anonymous_ip(self, ip_address: IPAddress) -> AnonymousIP:
"""
Get AnonymousIP object for the IP address from Anonymous IP database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
AnonymousIP model object with anonymity indicators
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support anonymous IP lookups
"""
def anonymous_plus(self, ip_address: IPAddress) -> AnonymousPlus:
"""
Get AnonymousPlus object for the IP address from Anonymous Plus database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
AnonymousPlus model object with enhanced anonymity information
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support anonymous plus lookups
"""
def connection_type(self, ip_address: IPAddress) -> ConnectionType:
"""
Get ConnectionType object for the IP address from Connection-Type database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
ConnectionType model object with connection type information
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support connection type lookups
"""
def domain(self, ip_address: IPAddress) -> Domain:
"""
Get Domain object for the IP address from Domain database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
Domain model object with domain information
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support domain lookups
"""
def enterprise(self, ip_address: IPAddress) -> Enterprise:
"""
Get Enterprise object for the IP address from Enterprise database.
Parameters:
- ip_address: IPv4 or IPv6 address as string
Returns:
Enterprise model object with comprehensive geographic and network data
Raises:
- AddressNotFoundError: IP address not found in database
- TypeError: Database type doesn't support enterprise lookups
"""
def metadata(self) -> maxminddb.reader.Metadata:
"""
Get metadata for the open database.
Returns:
Metadata object containing database information including build time,
database type, IP version, record size, and node count
"""
def close(self):
"""Close the GeoIP2 database and free resources."""
def __enter__(self) -> "Reader": ...
def __exit__(self, exc_type, exc_value, traceback): ...Constants for controlling how the database is accessed, providing trade-offs between performance and memory usage.
from geoip2.database import (
MODE_AUTO, MODE_FD, MODE_FILE, MODE_MEMORY, MODE_MMAP, MODE_MMAP_EXT
)
MODE_AUTO: int # Try MODE_MMAP_EXT, MODE_MMAP, MODE_FILE in order (default)
MODE_FD: int # fileish parameter is file descriptor, use MODE_MEMORY
MODE_FILE: int # Read database as standard file (pure Python)
MODE_MEMORY: int # Load entire database into memory (pure Python)
MODE_MMAP: int # Memory map database file (pure Python)
MODE_MMAP_EXT: int # Memory map with C extension (fastest performance)import geoip2.database
# City database lookup
with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader:
response = reader.city('203.0.113.0')
print(f"Country: {response.country.name}")
print(f"City: {response.city.name}")
print(f"Coordinates: {response.location.latitude}, {response.location.longitude}")
print(f"Postal: {response.postal.code}")
print(f"Subdivision: {response.subdivisions.most_specific.name}")with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader:
response = reader.asn('203.0.113.0')
print(f"ASN: {response.autonomous_system_number}")
print(f"Organization: {response.autonomous_system_organization}")
print(f"Network: {response.network}")with geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') as reader:
response = reader.anonymous_ip('203.0.113.0')
print(f"Is Anonymous: {response.is_anonymous}")
print(f"Is VPN: {response.is_anonymous_vpn}")
print(f"Is Tor: {response.is_tor_exit_node}")
print(f"Is Hosting Provider: {response.is_hosting_provider}")with geoip2.database.Reader('/path/to/GeoIP-Anonymous-Plus.mmdb') as reader:
response = reader.anonymous_plus('203.0.113.0')
print(f"Anonymizer Confidence: {response.anonymizer_confidence}")
print(f"Is Anonymous: {response.is_anonymous}")
print(f"Is VPN: {response.is_anonymous_vpn}")
print(f"Is Tor: {response.is_tor_exit_node}")
print(f"Network Last Seen: {response.network_last_seen}")
print(f"Provider Name: {response.provider_name}")with geoip2.database.Reader('/path/to/GeoIP2-Connection-Type.mmdb') as reader:
response = reader.connection_type('203.0.113.0')
print(f"Connection Type: {response.connection_type}") # 'Corporate', 'Cable/DSL', etc.with geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') as reader:
response = reader.isp('203.0.113.0')
print(f"ISP: {response.isp}")
print(f"Organization: {response.organization}")
print(f"ASN: {response.autonomous_system_number}")
print(f"Mobile Country Code: {response.mobile_country_code}")with geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') as reader:
response = reader.domain('203.0.113.0')
print(f"Domain: {response.domain}")with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader:
response = reader.enterprise('203.0.113.0')
# Enterprise includes all city data plus confidence scores
print(f"Country: {response.country.name} (confidence: {response.country.confidence})")
print(f"City: {response.city.name} (confidence: {response.city.confidence})")
print(f"Subdivision: {response.subdivisions.most_specific.name} (confidence: {response.subdivisions.most_specific.confidence})")# Use German with English fallback, memory-mapped access
with geoip2.database.Reader(
'/path/to/GeoLite2-City.mmdb',
locales=['de', 'en'],
mode=geoip2.database.MODE_MMAP
) as reader:
response = reader.city('203.0.113.0')
print(response.country.name) # German name if availablewith geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader:
metadata = reader.metadata()
print(f"Database Type: {metadata.database_type}")
print(f"Build Date: {metadata.build_epoch}")
print(f"IP Version: {metadata.ip_version}")
print(f"Record Size: {metadata.record_size}")import geoip2.database
import geoip2.errors
import ipaddress
# Efficiently enumerate entire subnets using AddressNotFoundError.network
with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader:
network = ipaddress.ip_network("192.128.0.0/15")
ip_address = network[0]
while ip_address in network:
try:
response = reader.asn(ip_address)
response_network = response.network
print(f"{response_network}: ASN {response.autonomous_system_number}")
except geoip2.errors.AddressNotFoundError as e:
response_network = e.network
print(f"{response_network}: No data")
# Move to next subnet
ip_address = response_network[-1] + 1import geoip2.database
from geoip2.errors import AddressNotFoundError
try:
with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader:
response = reader.city('127.0.0.1') # Private IP
except AddressNotFoundError as e:
print(f"Address {e.ip_address} not found")
print(f"Largest network with no data: {e.network}")
except FileNotFoundError:
print("Database file not found")
except PermissionError:
print("Permission denied accessing database file")IPAddress = Union[str, IPv6Address, IPv4Address]Install with Tessl CLI
npx tessl i tessl/pypi-geoip2