MaxMind GeoIP2 API for IP geolocation using web services and databases
—
Structured data models representing geographic and network information returned by web services and database lookups. Models contain nested record classes for hierarchical geographic data, providing comprehensive access to location, network, and ISP information.
import datetime
import ipaddress
from collections.abc import Sequence
from ipaddress import IPv4Address, IPv6Address
from typing import Optional, Union
import geoip2.records
from geoip2.types import IPAddressModels representing comprehensive geographic information from continent to city level, including location coordinates, postal codes, and administrative subdivisions.
The most comprehensive geographic model containing city-level data along with all country-level information.
class City:
def __init__(self, locales: Optional[Sequence[str]], *, city: Optional[dict] = None,
continent: Optional[dict] = None, country: Optional[dict] = None,
location: Optional[dict] = None, ip_address: Optional[IPAddress] = None,
maxmind: Optional[dict] = None, postal: Optional[dict] = None,
prefix_len: Optional[int] = None, registered_country: Optional[dict] = None,
represented_country: Optional[dict] = None, subdivisions: Optional[list[dict]] = None,
traits: Optional[dict] = None, **_): ...
# Geographic records
continent: geoip2.records.Continent # Continent information
country: geoip2.records.Country # Country information
city: geoip2.records.City # City information
location: geoip2.records.Location # Coordinates and location data
postal: geoip2.records.Postal # Postal code information
subdivisions: geoip2.records.Subdivisions # State/province information
# Administrative records
registered_country: geoip2.records.Country # ISP registered country
represented_country: geoip2.records.RepresentedCountry # Military base country
# Network and account records
traits: geoip2.records.Traits # Network and IP characteristics
maxmind: geoip2.records.MaxMind # MaxMind account informationCountry-level geographic model containing continent and country information without city-specific details.
class Country:
def __init__(self, locales: Optional[Sequence[str]], *, continent: Optional[dict] = None,
country: Optional[dict] = None, ip_address: Optional[IPAddress] = None,
maxmind: Optional[dict] = None, prefix_len: Optional[int] = None,
registered_country: Optional[dict] = None, represented_country: Optional[dict] = None,
traits: Optional[dict] = None, **_): ...
# Geographic records
continent: geoip2.records.Continent # Continent information
country: geoip2.records.Country # Country information
# Administrative records
registered_country: geoip2.records.Country # ISP registered country
represented_country: geoip2.records.RepresentedCountry # Military base country
# Network and account records
traits: geoip2.records.Traits # Network and IP characteristics
maxmind: geoip2.records.MaxMind # MaxMind account informationclass Insights(City):
"""
Model for GeoIP2 Insights web service.
Extends City with user behavior analytics and enhanced traits.
"""
class Enterprise(City):
"""
Model for GeoIP2 Enterprise database.
Extends City with confidence scores and enhanced data accuracy.
"""Models representing network and ISP information with simplified structure focused on autonomous system and connectivity data.
class SimpleModel:
def __init__(self, ip_address: IPAddress, network: Optional[str], prefix_len: Optional[int]): ...
@property
def ip_address(self) -> Union[IPv4Address, IPv6Address]:
"""The IP address for the record."""
@property
def network(self) -> Optional[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
"""The network associated with the record."""class ASN(SimpleModel):
def __init__(self, ip_address: IPAddress, *, autonomous_system_number: Optional[int] = None,
autonomous_system_organization: Optional[str] = None, network: Optional[str] = None,
prefix_len: Optional[int] = None, **_): ...
autonomous_system_number: Optional[int] # ASN number
autonomous_system_organization: Optional[str] # ASN organization nameclass ISP(ASN):
def __init__(self, ip_address: IPAddress, *, autonomous_system_number: Optional[int] = None,
autonomous_system_organization: Optional[str] = None, isp: Optional[str] = None,
mobile_country_code: Optional[str] = None, mobile_network_code: Optional[str] = None,
organization: Optional[str] = None, network: Optional[str] = None,
prefix_len: Optional[int] = None, **_): ...
# Inherits ASN fields plus:
isp: Optional[str] # ISP name
mobile_country_code: Optional[str] # Mobile country code (MCC)
mobile_network_code: Optional[str] # Mobile network code (MNC)
organization: Optional[str] # Organization nameclass ConnectionType(SimpleModel):
def __init__(self, ip_address: IPAddress, *, connection_type: Optional[str] = None,
network: Optional[str] = None, prefix_len: Optional[int] = None, **_): ...
connection_type: Optional[str] # 'Dialup', 'Cable/DSL', 'Corporate', 'Cellular', 'Satellite'class Domain(SimpleModel):
def __init__(self, ip_address: IPAddress, *, domain: Optional[str] = None,
network: Optional[str] = None, prefix_len: Optional[int] = None, **_): ...
domain: Optional[str] # Domain associated with IPModels for detecting and classifying anonymous networks, VPNs, proxies, and other privacy-focused services.
class AnonymousIP(SimpleModel):
def __init__(self, ip_address: IPAddress, *, is_anonymous: bool = False,
is_anonymous_vpn: bool = False, is_hosting_provider: bool = False,
is_public_proxy: bool = False, is_residential_proxy: bool = False,
is_tor_exit_node: bool = False, network: Optional[str] = None,
prefix_len: Optional[int] = None, **_): ...
is_anonymous: bool # Belongs to any anonymous network
is_anonymous_vpn: bool # Registered to anonymous VPN provider
is_hosting_provider: bool # Belongs to hosting or VPN provider
is_public_proxy: bool # Belongs to public proxy
is_residential_proxy: bool # Residential ISP anonymizing network
is_tor_exit_node: bool # Tor exit nodeclass AnonymousPlus(AnonymousIP):
def __init__(self, ip_address: IPAddress, *, anonymizer_confidence: Optional[int] = None,
is_anonymous: bool = False, is_anonymous_vpn: bool = False,
is_hosting_provider: bool = False, is_public_proxy: bool = False,
is_residential_proxy: bool = False, is_tor_exit_node: bool = False,
network: Optional[str] = None, network_last_seen: Optional[str] = None,
prefix_len: Optional[int] = None, provider_name: Optional[str] = None, **_): ...
# Inherits AnonymousIP fields plus:
anonymizer_confidence: Optional[int] # Confidence score 1-99 for active VPN service
network_last_seen: Optional[datetime.date] # Last day network was seen in analysis
provider_name: Optional[str] # VPN provider name (e.g., 'NordVPN')Detailed record classes containing the actual data within model objects, organized hierarchically from continent to city level.
class Continent:
def __init__(self, locales: Optional[Sequence[str]], *, code: Optional[str] = None,
geoname_id: Optional[int] = None, names: Optional[dict[str, str]] = None, **_): ...
code: Optional[str] # Two-character continent code ('NA', 'EU', etc.)
geoname_id: Optional[int] # GeoNames database ID
names: dict[str, str] # Localized names by language code
name: Optional[str] # Name in preferred locale
class Country:
def __init__(self, locales: Optional[Sequence[str]], *, confidence: Optional[int] = None,
geoname_id: Optional[int] = None, is_in_european_union: bool = False,
iso_code: Optional[str] = None, names: Optional[dict[str, str]] = None, **_): ...
confidence: Optional[int] # Confidence 0-100 (Insights/Enterprise only)
geoname_id: Optional[int] # GeoNames database ID
is_in_european_union: bool # EU membership status
iso_code: Optional[str] # ISO 3166-1 alpha-2 country code
names: dict[str, str] # Localized names by language code
name: Optional[str] # Name in preferred locale
class City:
def __init__(self, locales: Optional[Sequence[str]], *, confidence: Optional[int] = None,
geoname_id: Optional[int] = None, names: Optional[dict[str, str]] = None, **_): ...
confidence: Optional[int] # Confidence 0-100 (Insights/Enterprise only)
geoname_id: Optional[int] # GeoNames database ID
names: dict[str, str] # Localized names by language code
name: Optional[str] # Name in preferred locale
class Subdivision:
def __init__(self, locales: Optional[Sequence[str]], *, confidence: Optional[int] = None,
geoname_id: Optional[int] = None, iso_code: Optional[str] = None,
names: Optional[dict[str, str]] = None, **_): ...
confidence: Optional[int] # Confidence 0-100 (Insights/Enterprise only)
geoname_id: Optional[int] # GeoNames database ID
iso_code: Optional[str] # ISO 3166-2 subdivision code
names: dict[str, str] # Localized names by language code
name: Optional[str] # Name in preferred locale
class Subdivisions(tuple):
"""
Tuple-like collection of subdivisions from largest to smallest.
For UK address, England would be first, Oxfordshire second.
"""
@property
def most_specific(self) -> Subdivision:
"""The most specific (smallest) subdivision available."""class Location:
def __init__(self, *, average_income: Optional[int] = None, accuracy_radius: Optional[int] = None,
latitude: Optional[float] = None, longitude: Optional[float] = None,
metro_code: Optional[int] = None, population_density: Optional[int] = None,
time_zone: Optional[str] = None, **_): ...
average_income: Optional[int] # Average income in USD (Insights only)
accuracy_radius: Optional[int] # Accuracy radius in kilometers
latitude: Optional[float] # Approximate latitude
longitude: Optional[float] # Approximate longitude
metro_code: Optional[int] # Metro code (deprecated)
population_density: Optional[int] # Population per sq km (Insights only)
time_zone: Optional[str] # IANA time zone
class Postal:
def __init__(self, *, code: Optional[str] = None, confidence: Optional[int] = None, **_): ...
code: Optional[str] # Postal code
confidence: Optional[int] # Confidence 0-100 (Insights/Enterprise only)
class MaxMind:
def __init__(self, *, queries_remaining: Optional[int] = None, **_): ...
queries_remaining: Optional[int] # Remaining queries for accountComprehensive network characteristics and user behavior data.
class Traits:
def __init__(self, *, autonomous_system_number: Optional[int] = None,
autonomous_system_organization: Optional[str] = None, connection_type: Optional[str] = None,
domain: Optional[str] = None, is_anonymous: bool = False, is_anonymous_proxy: bool = False,
is_anonymous_vpn: bool = False, is_hosting_provider: bool = False,
is_legitimate_proxy: bool = False, is_public_proxy: bool = False,
is_residential_proxy: bool = False, is_satellite_provider: bool = False,
is_tor_exit_node: bool = False, isp: Optional[str] = None,
ip_address: Optional[str] = None, network: Optional[str] = None,
organization: Optional[str] = None, prefix_len: Optional[int] = None,
static_ip_score: Optional[float] = None, user_count: Optional[int] = None,
user_type: Optional[str] = None, mobile_country_code: Optional[str] = None,
mobile_network_code: Optional[str] = None, is_anycast: bool = False, **_): ...
# Network identification
autonomous_system_number: Optional[int] # ASN number
autonomous_system_organization: Optional[str] # ASN organization
connection_type: Optional[str] # Connection type
domain: Optional[str] # Associated domain
isp: Optional[str] # ISP name
organization: Optional[str] # Organization name
# Anonymity flags
is_anonymous: bool # Any anonymous network
is_anonymous_proxy: bool # Anonymous proxy (deprecated)
is_anonymous_vpn: bool # Anonymous VPN provider
is_anycast: bool # Anycast network
is_hosting_provider: bool # Hosting/VPN provider
is_legitimate_proxy: bool # Corporate VPN/proxy
is_public_proxy: bool # Public proxy
is_residential_proxy: bool # Residential anonymizing network
is_satellite_provider: bool # Satellite provider (deprecated)
is_tor_exit_node: bool # Tor exit node
# Mobile network
mobile_country_code: Optional[str] # Mobile country code (MCC)
mobile_network_code: Optional[str] # Mobile network code (MNC)
# User behavior (Insights only)
static_ip_score: Optional[float] # Static IP score 0-99.99
user_count: Optional[int] # Estimated users sharing IP (24hr)
user_type: Optional[str] # User classification
# Network properties
@property
def ip_address(self) -> Optional[Union[IPv4Address, IPv6Address]]:
"""The IP address that the data is for."""
@property
def network(self) -> Optional[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
"""The network associated with the record."""response = client.city('203.0.113.0')
# Continent information
print(f"Continent: {response.continent.name} ({response.continent.code})")
# Country information
print(f"Country: {response.country.name} ({response.country.iso_code})")
print(f"EU Member: {response.country.is_in_european_union}")
# Subdivision (state/province) information
most_specific = response.subdivisions.most_specific
print(f"Subdivision: {most_specific.name} ({most_specific.iso_code})")
# City information
print(f"City: {response.city.name}")
# Location coordinates
print(f"Lat/Lon: {response.location.latitude}, {response.location.longitude}")
print(f"Time Zone: {response.location.time_zone}")
# Postal code
print(f"Postal: {response.postal.code}")# From City/Country response traits
print(f"ASN: {response.traits.autonomous_system_number}")
print(f"ISP: {response.traits.isp}")
print(f"Connection: {response.traits.connection_type}")
print(f"Network: {response.traits.network}")
# From dedicated ASN lookup
asn_response = reader.asn('203.0.113.0')
print(f"ASN: {asn_response.autonomous_system_number}")
print(f"Org: {asn_response.autonomous_system_organization}")anon_response = reader.anonymous_ip('203.0.113.0')
print(f"Anonymous: {anon_response.is_anonymous}")
print(f"VPN: {anon_response.is_anonymous_vpn}")
print(f"Tor: {anon_response.is_tor_exit_node}")
print(f"Hosting: {anon_response.is_hosting_provider}")# Using multiple locales
with Client(42, 'key', locales=['es', 'en']) as client:
response = client.country('203.0.113.0')
# All available names
print(response.country.names) # {'en': 'United States', 'es': 'Estados Unidos', ...}
# Name in preferred locale (Spanish first, English fallback)
print(response.country.name) # 'Estados Unidos'IPAddress = Union[str, IPv6Address, IPv4Address]Install with Tessl CLI
npx tessl i tessl/pypi-geoip2