### Install geoip2 from source Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Install the geoip2 module using pip from the source directory. ```bash python -m pip install . ``` -------------------------------- ### Install geoip2 module Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use pip to install the geoip2 module from PyPI. Alternatively, install from the source directory using `python -m pip install .`. ```bash pip install geoip2 ``` ```bash python -m pip install . ``` -------------------------------- ### Install geoip2 module Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Use pip to install the geoip2 module from PyPI. ```bash pip install geoip2 ``` -------------------------------- ### Install Dependencies with uv Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Installs all project dependencies, including development and testing groups, using the uv package manager. ```bash uv sync --all-groups ``` -------------------------------- ### Install uv and Dependencies Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Installs the uv package manager and synchronizes all project dependencies, including development and linting groups. ```bash # Install uv if not already installed curl -LsSf https://astral.sh/uv/install.sh | sh # Install all dependencies including dev and lint groups uv sync --all-groups ``` -------------------------------- ### Model Constructor Example Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Illustrates the constructor pattern for model and record classes, emphasizing keyword-only arguments and handling of optional parameters. ```python def __init__( self, locales: Sequence[str] | None, # positional for records *, continent: dict[str, Any] | None = None, country: dict[str, Any] | None = None, # ... other keyword-only parameters **_: Any, # ignore unknown keys ) -> None: ``` -------------------------------- ### City Database Lookup Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md This example demonstrates how to query the City database locally using `geoip2.database.Reader`. Create a Reader object once and reuse it for multiple lookups. Replace the path with your actual database file. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader: # Replace "city" with the method corresponding to the database # that you are using, e.g., "country". response = reader.city('203.0.113.0') response.country.iso_code 'US' response.country.name 'United States' response.country.names['zh-CN'] u'美国' response.subdivisions.most_specific.name 'Minnesota' response.subdivisions.most_specific.iso_code 'MN' response.city.name 'Minneapolis' response.postal.code '55455' response.location.latitude 44.9733 response.location.longitude -93.2323 response.traits.network IPv4Network('203.0.113.0/24') ``` -------------------------------- ### HISTORY.rst Changelog Format Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of the structured format for updating the HISTORY.rst file with versioned changes. ```rst 5.2.0 ++++++++++++++++++ * IMPORTANT: Python 3.10 or greater is required. If you are using an older version, please use an earlier release. * A new ``field_name`` property has been added to ``geoip2.models.ModelName``. This field provides information about... * The ``old_field`` property in ``geoip2.models.ModelName`` has been deprecated. Please use ``new_field`` instead. ``` -------------------------------- ### Synchronous GeoIP2 Web Service Client Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Example of using the synchronous GeoIP2 web service client. Replace account ID and license key. The 'host' argument can be set to 'geolite.info' for GeoLite2 or 'sandbox.maxmind.com' for the Sandbox GeoIP2 service. The method 'city' can be replaced with 'country' or 'insights'. ```python import geoip2.webservice # This creates a Client object that can be reused across requests. # Replace "42" with your account ID and "license_key" with your license # key. Set the "host" keyword argument to "geolite.info" to use the # GeoLite2 web service instead of the GeoIP2 web service. Set the # "host" keyword argument to "sandbox.maxmind.com" to use the Sandbox # GeoIP2 web service instead of the production GeoIP2 web service. with geoip2.webservice.Client(42, 'license_key') as client: # Replace "city" with the method corresponding to the web service # that you are using, i.e., "country", "city", or "insights". Please # note that Insights is not supported by the GeoLite2 web service. response = client.city('203.0.113.0') response.country.iso_code response.country.name response.country.names['zh-CN'] response.subdivisions.most_specific.name response.subdivisions.most_specific.iso_code response.city.name response.postal.code response.location.latitude response.location.longitude response.traits.network ``` -------------------------------- ### Parse Date String in Constructor Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of parsing a date string from the API into a datetime.date object, handling None values. ```python import datetime self.network_last_seen = ( datetime.date.fromisoformat(network_last_seen) if network_last_seen else None ) ``` -------------------------------- ### Async Web Service Client for Multiple IP Lookups Source: https://context7.com/maxmind/geoip2-python/llms.txt Use `AsyncClient` with aiohttp for concurrent, non-blocking IP address lookups via the MaxMind web service. Ideal for high-throughput applications. Ensure you have `aiohttp` installed. ```python import asyncio import geoip2.webservice from geoip2.errors import GeoIP2Error async def lookup_multiple_ips(): async with geoip2.webservice.AsyncClient( account_id=42, license_key='your_license_key', host='geoip.maxmind.com', locales=['en'], timeout=60, proxy='http://proxy.example.com:8080' # Optional proxy support ) as client: # Concurrent lookups for multiple IPs ips = ['203.0.113.1', '198.51.100.2', '192.0.2.3'] async def lookup_ip(ip): try: response = await client.city(ip) return { 'ip': ip, 'country': response.country.iso_code, 'city': response.city.name, 'latitude': response.location.latitude, 'longitude': response.location.longitude } except GeoIP2Error as e: return {'ip': ip, 'error': str(e)} # Execute all lookups concurrently results = await asyncio.gather(*[lookup_ip(ip) for ip in ips]) for result in results: print(result) # Single async lookup response = await client.country('8.8.8.8') print(f"Google DNS Country: {response.country.name}") # Insights lookup (async) insights = await client.insights('me') print(f"My anonymizer status: {insights.anonymizer.is_anonymous}") # Run the async function asyncio.run(lookup_multiple_ips()) ``` -------------------------------- ### Asynchronous GeoIP2 Web Service Client Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Example of using the asynchronous GeoIP2 web service client within an asyncio event loop. Replace account ID and license key. The 'host' argument can be set to 'geolite.info' for GeoLite2 or 'sandbox.maxmind.com' for the Sandbox GeoIP2 service. The method 'city' can be replaced with 'country' or 'insights'. ```python import asyncio import geoip2.webservice async def main(): # This creates an AsyncClient object that can be reused across # requests on the running event loop. If you are using multiple event # loops, you must ensure the object is not used on another loop. # # Replace "42" with your account ID and "license_key" with your license # key. Set the "host" keyword argument to "geolite.info" to use the # GeoLite2 web service instead of the GeoIP2 web service. Set the # "host" keyword argument to "sandbox.maxmind.com" to use the Sandbox # GeoIP2 web service instead of the production GeoIP2 web service. async with geoip2.webservice.AsyncClient(42, 'license_key') as client: # Replace "city" with the method corresponding to the web service # that you are using, i.e., "country", "city", or "insights". Please # note that Insights is not supported by the GeoLite2 web service. response = await client.city('203.0.113.0') response.country.iso_code response.country.name ``` -------------------------------- ### Annotate Date Field Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of annotating a field that holds a date or None. ```python network_last_seen: datetime.date | None ``` -------------------------------- ### Add New Field to Model Constructor Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of adding a new field with type hints and default value to a model's __init__ method. ```python def __init__( self, # ... existing params *, field_name: int | None = None, # new field # ... other params ) -> None: ``` -------------------------------- ### Add Class-Level Type Annotation and Docstring Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of adding a class-level type annotation and docstring for a new field. ```python field_name: int | None """Description of the field, its source, and availability.""" ``` -------------------------------- ### Assign Field in Constructor Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of assigning a parameter to a class attribute within the constructor. ```python self.field_name = field_name ``` -------------------------------- ### Test Anonymous Plus Model Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example test case for the AnonymousPlus model, asserting specific field values. ```python def test_anonymous_plus_full(self) -> None: model = geoip2.models.AnonymousPlus( "1.2.3.4", anonymizer_confidence=99, network_last_seen=datetime.date(2025, 4, 14), provider_name="FooBar VPN", is_anonymous=True, is_anonymous_vpn=True, # ... other fields ) assert model.anonymizer_confidence == 99 assert model.network_last_seen == datetime.date(2025, 4, 14) assert model.provider_name == "FooBar VPN" ``` -------------------------------- ### Read Anonymous IP Database with GeoIP2 Python Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Utilize `geoip2.database.Reader` to access an Anonymous IP database. This example demonstrates looking up an IP address and checking various anonymity-related properties like `is_anonymous`, `is_hosting_provider`, and `is_tor_exit_node`. Reuse the reader instance for efficiency. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') as reader: response = reader.anonymous_ip('203.0.113.0') response.is_anonymous response.is_anonymous_vpn response.is_hosting_provider response.is_public_proxy response.is_residential_proxy response.is_tor_exit_node response.ip_address response.network ``` -------------------------------- ### Handle AddressNotFoundError for Subnet Enumeration Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst This example demonstrates how to handle `AddressNotFoundError` to efficiently enumerate entire subnets. It iterates through IP addresses within a network, attempting to find data and printing the network or response. The `Reader` object should be reused. ```python import geoip2.database import geoip2.errors import ipaddress # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. 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 except geoip2.errors.AddressNotFoundError as e: response = None response_network = e.network print(f"{response_network}: {response!r}") ``` -------------------------------- ### Access Enterprise Database for Comprehensive IP Intelligence Source: https://context7.com/maxmind/geoip2-python/llms.txt Use the Enterprise database to get a combination of city-level geolocation, confidence scores, ISP data, and user type classification for an IP address. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: response = reader.enterprise('203.0.113.0') # Location with confidence scores print(f"Country: {response.country.name} (confidence: {response.country.confidence}%)") print(f"City: {response.city.name} (confidence: {response.city.confidence}%)") print(f"Postal: {response.postal.code} (confidence: {response.postal.confidence}%)") print(f"Subdivision: {response.subdivisions.most_specific.name} (confidence: {response.subdivisions.most_specific.confidence}%)") # Enhanced location data print(f"Latitude: {response.location.latitude}") print(f"Longitude: {response.location.longitude}") print(f"Accuracy Radius: {response.location.accuracy_radius}km") # Network traits print(f"ISP: {response.traits.isp}") print(f"Organization: {response.traits.organization}") print(f"Domain: {response.traits.domain}") print(f"Connection Type: {response.traits.connection_type}") print(f"User Type: {response.traits.user_type}") print(f"Is Legitimate Proxy: {response.traits.is_legitimate_proxy}") print(f"Network: {response.traits.network}") ``` -------------------------------- ### Apply Ruff Formatting Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Automatically format the codebase according to ruff's formatting rules. ```bash uv run ruff format . ``` -------------------------------- ### Deprecate Field in Docstring Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Example of marking a field as deprecated in its docstring, including version and alternative. ```python metro_code: int | None """The metro code of the location. .. deprecated:: 5.0.0 The code values are no longer being maintained. """ ``` -------------------------------- ### Check Ruff Formatting Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Check the code formatting against ruff's standards and show differences. ```bash uv run ruff format --check --diff . ``` -------------------------------- ### Run Ruff Linting Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Execute ruff linting checks on the codebase. ```bash uv run ruff check ``` -------------------------------- ### Pre-Commit Development Checks Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Commands to run before committing code, including formatting, linting, type checking, and running tests. ```bash # Format code uv run ruff format . # Check linting uv run ruff check --fix # Type check uv run mypy src tests # Run tests uv run pytest # Or run everything via tox uv run tox ``` -------------------------------- ### Read ISP Information from GeoIP2 Database Source: https://context7.com/maxmind/geoip2-python/llms.txt Use the ISP database to get detailed ISP and organization information for a given IP address. This includes ASN and mobile network details. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') as reader: response = reader.isp('203.0.113.0') print(f"IP Address: {response.ip_address}") print(f"Network: {response.network}") # ASN information print(f"ASN: {response.autonomous_system_number}") print(f"AS Organization: {response.autonomous_system_organization}") # ISP information print(f"ISP: {response.isp}") print(f"Organization: {response.organization}") # Mobile network information (for cellular IPs) print(f"Mobile Country Code: {response.mobile_country_code}") print(f"Mobile Network Code: {response.mobile_network_code}") ``` -------------------------------- ### Property-based Network Calculation Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Demonstrates the use of a property for lazy calculation and caching of the network address from IP address and prefix length. ```python @property def network(self) -> ipaddress.IPv4Network | ipaddress.IPv6Network | None: # Lazy calculation and caching of network from ip_address and prefix_len ``` -------------------------------- ### Run All Linting Checks Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Execute all configured linting checks, including mypy, ruff check, and ruff format check, using tox. ```bash uv run tox -e lint ``` -------------------------------- ### Synchronous Web Service IP Geolocation Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use the `geoip2.webservice.Client` to perform synchronous IP geolocation lookups. Replace placeholders with your account ID and license key. The `host` can be set to `geolite.info` for GeoLite2 or `sandbox.maxmind.com` for the sandbox service. The method (e.g., `city`, `country`, `insights`) should match the web service being used. ```python import geoip2.webservice with geoip2.webservice.Client(42, 'license_key') as client: response = client.city('203.0.113.0') response.country.iso_code response.country.name response.country.names['zh-CN'] response.subdivisions.most_specific.name response.subdivisions.most_specific.iso_code response.city.name response.postal.code response.location.latitude response.location.longitude response.traits.network ``` -------------------------------- ### Run Tests with Coverage Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Execute tests using pytest and generate an HTML coverage report. ```bash uv run pytest --cov=geoip2 --cov-report=html ``` -------------------------------- ### Read City Database with GeoIP2 Python Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Use the `geoip2.database.Reader` to open a City database file and perform IP address lookups. Instantiate the reader once and reuse it for multiple requests as creation is expensive. The `city()` method returns a response object with detailed location information. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader: response = reader.city('203.0.113.0') response.country.iso_code response.country.name response.country.names['zh-CN'] response.subdivisions.most_specific.name response.subdivisions.most_specific.iso_code response.city.name response.postal.code response.location.latitude response.location.longitude response.traits.network ``` -------------------------------- ### Async Web Service Lookup Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use this snippet to perform asynchronous IP address lookups via the GeoIP2 web service. Ensure you replace placeholders with your account ID and license key. The client can be reused across requests within the same event loop. ```python import asyncio import geoip2.webservice async def main(): # This creates an AsyncClient object that can be reused across # requests on the running event loop. If you are using multiple event # loops, you must ensure the object is not used on another loop. # # Replace "42" with your account ID and "license_key" with your license # key. Set the "host" keyword argument to "geolite.info" to use the # GeoLite2 web service instead of the GeoIP2 web service. Set the # "host" keyword argument to "sandbox.maxmind.com" to use the Sandbox # GeoIP2 web service instead of the production GeoIP2 web service. async with geoip2.webservice.AsyncClient(42, 'license_key') as client: # Replace "city" with the method corresponding to the web service # that you are using, i.e., "country", "city", or "insights". Please # note that Insights is not supported by the GeoLite2 web service. response = await client.city('203.0.113.0') response.country.iso_code 'US' response.country.name 'United States' response.country.names['zh-CN'] u'美国' response.subdivisions.most_specific.name 'Minnesota' response.subdivisions.most_specific.iso_code 'MN' response.city.name 'Minneapolis' response.postal.code '55455' response.location.latitude 44.9733 response.location.longitude -93.2323 response.traits.network IPv4Network('203.0.113.0/32') asyncio.run(main()) ``` -------------------------------- ### Anonymous IP Database Lookup Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md This snippet shows how to query the Anonymous IP database locally. Similar to the City database, instantiate the Reader once and reuse it. Ensure the path points to your downloaded Anonymous IP database file. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') as reader: response = reader.anonymous_ip('203.0.113.0') response.is_anonymous True response.is_anonymous_vpn False response.is_hosting_provider False response.is_public_proxy False response.is_residential_proxy False response.is_tor_exit_node True response.ip_address '203.0.113.0' response.network IPv4Network('203.0.113.0/24') ``` -------------------------------- ### Run Tests Across All Python Versions Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Execute tests using tox across all supported Python versions. ```bash uv run tox ``` -------------------------------- ### Query Enterprise Database Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Use the `.enterprise` method to query the Enterprise database. The `Reader` object should be created once and reused. ```pycon import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: # Use the .enterprise method to do a lookup in the Enterprise database response = reader.enterprise('203.0.113.0') print(response.country.confidence) print(response.country.iso_code) print(response.country.name) print(response.country.names['zh-CN']) print(response.subdivisions.most_specific.name) print(response.subdivisions.most_specific.iso_code) print(response.subdivisions.most_specific.confidence print(response.city.name) print(response.country.confidence) print(response.postal.code) print(response.location.accuracy_radius) print(response.location.latitude) print(response.location.longitude) print(response.traits.network) ``` -------------------------------- ### Run Mypy Type Checking Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Perform static type checking on the source and test files using mypy. ```bash uv run mypy src tests ``` -------------------------------- ### Query ISP Database Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Query the ISP database using the `Reader` object. Remember to reuse the `Reader` instance for efficiency. ```pycon import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') as reader: response = reader.isp('203.0.113.0') print(response.autonomous_system_number) print(response.autonomous_system_organization) print(response.isp) print(response.organization) print(response.ip_address) print(response.network) ``` -------------------------------- ### Handle Web Service Errors with geoip2-python Source: https://context7.com/maxmind/geoip2-python/llms.txt Safely perform lookups using the GeoIP2 web service, handling various exceptions like AuthenticationError, OutOfQueriesError, and HTTPError. Requires a MaxMind account and license key. ```python import geoip2.webservice from geoip2.errors import ( GeoIP2Error, AddressNotFoundError, AuthenticationError, HTTPError, InvalidRequestError, OutOfQueriesError, PermissionRequiredError ) # Web service error handling def safe_webservice_lookup(client, ip): try: return client.city(ip) except AddressNotFoundError: print(f"IP {ip} not found in MaxMind database") return None except AuthenticationError: print("Invalid account ID or license key") raise except OutOfQueriesError: print("Account has no remaining query credits") raise except PermissionRequiredError: print("Account lacks permission for this service") raise except InvalidRequestError as e: print(f"Invalid request: {e}") return None except HTTPError as e: print(f"HTTP error {e.http_status}: {e}") print(f"URI: {e.uri}") print(f"Response: {e.decoded_content}") raise except GeoIP2Error as e: print(f"General GeoIP2 error: {e}") raise # Example usage (assuming client is initialized elsewhere) # client = geoip2.webservice.Client(YOUR_ACCOUNT_ID, YOUR_LICENSE_KEY) # result = safe_webservice_lookup(client, '203.0.113.0') ``` -------------------------------- ### Query Domain Database Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Perform a lookup in the Domain database. The `Reader` object should be instantiated once and reused. ```pycon import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') as reader: response = reader.domain('203.0.113.0') print(response.domain) print(response.ip_address) ``` -------------------------------- ### Run All Tests with pytest Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Executes all tests in the project using pytest, managed by the uv package manager. ```bash uv run pytest ``` -------------------------------- ### Lookup ISP Data Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use the `isp` method to retrieve Internet Service Provider information for an IP address. It is recommended to create the `Reader` object once and reuse it. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-ISP.mmdb') as reader: response = reader.isp('203.0.113.0') response.autonomous_system_number response.autonomous_system_organization response.isp response.organization response.ip_address response.network ``` -------------------------------- ### Handling Database Reader Exceptions Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Demonstrates the import of necessary modules for handling potential exceptions during database operations, such as `FileNotFoundError`, `PermissionError`, `ValueError`, `maxminddb.InvalidDatabaseError`, and `AddressNotFoundError`. ```python import geoip2.database import geoip2.errors import ipaddress # This creates a Reader object. You should use the same object ``` -------------------------------- ### Local Database Reader for City and Country Lookups Source: https://context7.com/maxmind/geoip2-python/llms.txt Utilize the `Reader` class for high-performance, local IP address lookups from MMDB files. This avoids network latency and is suitable for applications needing fast, offline data retrieval. Ensure the specified MMDB file path is correct. ```python import geoip2.database from geoip2.errors import AddressNotFoundError from maxminddb import InvalidDatabaseError # Create a reader instance (reuse for multiple lookups - creation is expensive) with geoip2.database.Reader( '/path/to/GeoLite2-City.mmdb', locales=['en', 'fr', 'zh-CN'], # Preferred language order mode=geoip2.database.MODE_MMAP # Memory-mapped for best performance ) as reader: try: # City database lookup response = reader.city('203.0.113.0') # Country information print(f"Country: {response.country.name} ({response.country.iso_code})") print(f"Country Name (French): {response.country.names.get('fr')}") print(f"Country Name (Chinese): {response.country.names.get('zh-CN')}") print(f"In EU: {response.country.is_in_european_union}") print(f"Geoname ID: {response.country.geoname_id}") # Continent information print(f"Continent: {response.continent.name} ({response.continent.code})") # City information print(f"City: {response.city.name}") print(f"City Geoname ID: {response.city.geoname_id}") # Subdivisions (states/provinces/regions) for i, subdivision in enumerate(response.subdivisions): print(f"Subdivision {i}: {subdivision.name} ({subdivision.iso_code})") print(f"Most Specific Subdivision: {response.subdivisions.most_specific.name}") # Location data print(f"Latitude: {response.location.latitude}") print(f"Longitude: {response.location.longitude}") print(f"Accuracy Radius: {response.location.accuracy_radius}km") print(f"Time Zone: {response.location.time_zone}") # Postal code print(f"Postal Code: {response.postal.code}") # Network information print(f"Network: {response.traits.network}") print(f"IP Address: {response.traits.ip_address}") # Registered country (where ISP registered the IP block) print(f"Registered Country: {response.registered_country.iso_code}") # Database metadata metadata = reader.metadata() print(f"Database Type: {metadata.database_type}") print(f"Build Epoch: {metadata.build_epoch}") except AddressNotFoundError as e: print(f"Address not found: {e}") print(f"Searched network: {e.network}") # Largest subnet with no data except InvalidDatabaseError as e: print(f"Database error: {e}") ``` -------------------------------- ### Lookup Domain Data Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use the `domain` method to find the domain name associated with an IP address. Ensure the `Reader` object is created once and reused for multiple lookups. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') as reader: response = reader.domain('203.0.113.0') response.domain response.ip_address ``` -------------------------------- ### Handle Database Errors with geoip2-python Source: https://context7.com/maxmind/geoip2-python/llms.txt Safely perform lookups using a local GeoIP2 database, handling AddressNotFoundError, InvalidDatabaseError, and ValueErrors for invalid IP formats. Requires a GeoIP2 database file. ```python import geoip2.database from maxminddb import InvalidDatabaseError # Database error handling def safe_database_lookup(reader, ip): try: return reader.city(ip) except geoip2.errors.AddressNotFoundError as e: print(f"IP {e.ip_address} not found. Searched network: {e.network}") return None except InvalidDatabaseError as e: print(f"Database is corrupt or invalid: {e}") raise except ValueError as e: print(f"Invalid IP address format: {e}") return None # Example usage try: with geoip2.database.Reader('/path/to/GeoLite2-City.mmdb') as reader: result = safe_database_lookup(reader, '203.0.113.0') if result: print(f"Found: {result.city.name}, {result.country.iso_code}") except FileNotFoundError: print("Database file not found") except PermissionError: print("Cannot read database file - check permissions") ``` -------------------------------- ### Detect Anonymous IPs with geoip2-python Source: https://context7.com/maxmind/geoip2-python/llms.txt Use the Anonymous IP database to detect VPNs, proxies, Tor exit nodes, and hosting providers. Ensure the GeoIP2-Anonymous-IP.mmdb database is available. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoIP2-Anonymous-IP.mmdb') as reader: response = reader.anonymous_ip('203.0.113.0') print(f"IP Address: {response.ip_address}") print(f"Network: {response.network}") # Anonymity detection flags print(f"Is Anonymous: {response.is_anonymous}") print(f"Is Anonymous VPN: {response.is_anonymous_vpn}") print(f"Is Hosting Provider: {response.is_hosting_provider}") print(f"Is Public Proxy: {response.is_public_proxy}") print(f"Is Residential Proxy: {response.is_residential_proxy}") print(f"Is Tor Exit Node: {response.is_tor_exit_node}") # Example security check def assess_ip_risk(ip): try: r = reader.anonymous_ip(ip) risk_factors = [] if r.is_tor_exit_node: risk_factors.append("Tor exit node") if r.is_public_proxy: risk_factors.append("Public proxy") if r.is_anonymous_vpn: risk_factors.append("Anonymous VPN") if r.is_residential_proxy: risk_factors.append("Residential proxy") if r.is_hosting_provider: risk_factors.append("Hosting provider") return risk_factors if risk_factors else ["No anonymity detected"] except geoip2.errors.AddressNotFoundError: return ["IP not in database"] print(f"Risk factors: {assess_ip_risk('203.0.113.0')}") ``` -------------------------------- ### Efficient Subnet Enumeration with geoip2-python Source: https://context7.com/maxmind/geoip2-python/llms.txt Iterate through IP ranges and use network information from AddressNotFoundError to skip entire subnets, avoiding redundant lookups. Requires GeoLite2-ASN.mmdb. ```python import geoip2.database import geoip2.errors import ipaddress with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: target_network = ipaddress.ip_network("192.128.0.0/15") ip_address = target_network[0] results = [] while ip_address in target_network: try: response = reader.asn(ip_address) result = { 'network': str(response.network), 'asn': response.autonomous_system_number, 'org': response.autonomous_system_organization } response_network = response.network except geoip2.errors.AddressNotFoundError as e: result = { 'network': str(e.network), 'asn': None, 'org': 'Not in database' } response_network = e.network results.append(result) # Jump to the next subnet after the current one ip_address = response_network[-1] + 1 print(f"Total subnets found: {len(results)}") for r in results[:5]: # Show first 5 print(f" {r['network']}: AS{r['asn']} - {r['org']}") ``` -------------------------------- ### Query Connection-Type Database Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Query the Connection-Type database using the `Reader` object. Ensure the Reader object is reused for performance. ```pycon import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Connection-Type.mmdb') as reader: response = reader.connection_type('203.0.113.0') print(response.connection_type) print(response.ip_address) print(response.network) ``` -------------------------------- ### Iterate through IP Network with GeoIP2 Reader Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Demonstrates how to use the GeoIP2 database reader to iterate through IP addresses within a network and retrieve ASN information. Ensure the database file path is correct and handle potential AddressNotFoundError. ```python 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 except geoip2.errors.AddressNotFoundError as e: response = None response_network = e.network print(f"{response_network}: {response!r}") ip_address = response_network[-1] + 1 # move to next subnet ``` -------------------------------- ### Query ASN Database Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst Use the `Reader` object to query the ASN database for IP address information. Create the Reader object once and reuse it for multiple requests as it is expensive to create. ```pycon import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: response = reader.asn('203.0.113.0') print(response.autonomous_system_number) print(response.autonomous_system_organization) print(response.ip_address) print(response.network) ``` -------------------------------- ### Perform ASN Lookups with geoip2-python Source: https://context7.com/maxmind/geoip2-python/llms.txt Query the ASN database to retrieve Autonomous System Number and organization details for an IP address. Ensure the GeoLite2-ASN.mmdb database is available. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: response = reader.asn('203.0.113.0') print(f"IP Address: {response.ip_address}") print(f"Network: {response.network}") print(f"ASN: {response.autonomous_system_number}") print(f"Organization: {response.autonomous_system_organization}") # Example: Group IPs by ASN def get_asn_info(ip): try: r = reader.asn(ip) return f"AS{r.autonomous_system_number} ({r.autonomous_system_organization})" except geoip2.errors.AddressNotFoundError: return "Unknown ASN" ips = ['8.8.8.8', '1.1.1.1', '203.0.113.0'] for ip in ips: print(f"{ip}: {get_asn_info(ip)}") ``` -------------------------------- ### Lookup ASN Data Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use the `asn` method to retrieve Autonomous System Number and organization details for an IP address. It's recommended to reuse the `Reader` object for efficiency. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoLite2-ASN.mmdb') as reader: response = reader.asn('203.0.113.0') response.autonomous_system_number response.autonomous_system_organization response.ip_address response.network ``` -------------------------------- ### Auto-fix Ruff Issues Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Automatically fix linting issues identified by ruff. ```bash uv run ruff check --fix ``` -------------------------------- ### Run Tests on Specific Python Version Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Execute tests using tox for a specific Python version, e.g., 3.11. ```bash uv run tox -e 3.11 ``` -------------------------------- ### Lookup Enterprise Data Source: https://github.com/maxmind/geoip2-python/blob/main/docs/index.md Use the `enterprise` method for detailed geographic and network information. Create and reuse the `Reader` object for optimal performance. ```python import geoip2.database # This creates a Reader object. You should use the same object # across multiple requests as creation of it is expensive. with geoip2.database.Reader('/path/to/GeoIP2-Enterprise.mmdb') as reader: # Use the .enterprise method to do a lookup in the Enterprise database response = reader.enterprise('203.0.113.0') response.country.confidence response.country.iso_code response.country.name response.country.names['zh-CN'] response.subdivisions.most_specific.name response.subdivisions.most_specific.iso_code response.subdivisions.most_specific.confidence response.city.name response.country.confidence response.postal.code response.location.accuracy_radius response.location.latitude response.location.longitude response.traits.network ``` -------------------------------- ### Synchronous Web Service Client Source: https://context7.com/maxmind/geoip2-python/llms.txt Use the synchronous `Client` for blocking HTTP requests to MaxMind web services. Ensure you reuse the client instance across requests for efficiency. Handle potential errors like `AddressNotFoundError`, `AuthenticationError`, and `OutOfQueriesError`. ```python import geoip2.webservice from geoip2.errors import AddressNotFoundError, AuthenticationError, OutOfQueriesError # Create a reusable client instance (reuse across requests for efficiency) with geoip2.webservice.Client( account_id=42, license_key='your_license_key', host='geoip.maxmind.com', # Use 'geolite.info' for GeoLite2, 'sandbox.maxmind.com' for testing locales=['en', 'de'], # Preferred language order for names timeout=60 ) as client: try: # City Plus lookup - returns detailed location data response = client.city('203.0.113.0') print(f"Country: {response.country.name} ({response.country.iso_code})") print(f"Country (German): {response.country.names.get('de')}") print(f"City: {response.city.name}") print(f"Postal Code: {response.postal.code}") print(f"Subdivision: {response.subdivisions.most_specific.name} ({response.subdivisions.most_specific.iso_code})") print(f"Location: {response.location.latitude}, {response.location.longitude}") print(f"Accuracy Radius: {response.location.accuracy_radius}km") print(f"Time Zone: {response.location.time_zone}") print(f"Network: {response.traits.network}") print(f"ISP: {response.traits.isp}") print(f"Organization: {response.traits.organization}") # Country lookup - minimal data, lower latency country_response = client.country('8.8.8.8') print(f"Country only: {country_response.country.iso_code}") # Insights lookup - most detailed data (GeoIP2 only, not GeoLite2) insights = client.insights('203.0.113.0') print(f"User Type: {insights.traits.user_type}") print(f"Static IP Score: {insights.traits.static_ip_score}") # Use 'me' to look up the client's own IP my_location = client.city('me') print(f"My IP: {my_location.traits.ip_address}") except AddressNotFoundError: print("IP address not found in database") except AuthenticationError: print("Invalid account ID or license key") except OutOfQueriesError: print("Account has insufficient query credits") ``` -------------------------------- ### Read Anonymous Plus Database with GeoIP2 Python Source: https://github.com/maxmind/geoip2-python/blob/main/README.rst This snippet shows how to query an Anonymous Plus database using `geoip2.database.Reader`. It retrieves detailed anonymity information, including `anonymizer_confidence`, `is_anonymous_vpn`, and `provider_name`. Remember to reuse the reader object for performance. ```python import geoip2.database import datetime with geoip2.database.Reader('/path/to/GeoIP-Anonymous-Plus.mmdb') as reader: response = reader.anonymous_plus('203.0.113.0') response.anonymizer_confidence response.is_anonymous response.is_anonymous_vpn response.is_hosting_provider response.is_public_proxy response.is_residential_proxy response.is_tor_exit_node response.ip_address response.network response.network_last_seen response.provider_name ``` -------------------------------- ### Run Specific Test File with pytest Source: https://github.com/maxmind/geoip2-python/blob/main/CLAUDE.md Executes tests contained within a specific file using pytest, managed by uv. ```bash uv run pytest tests/models_test.py ``` -------------------------------- ### Perform Domain Lookup using GeoIP2 Database Source: https://context7.com/maxmind/geoip2-python/llms.txt Query the Domain database to retrieve the second-level domain associated with an IP address. This helps in identifying the organization using the IP. ```python import geoip2.database with geoip2.database.Reader('/path/to/GeoIP2-Domain.mmdb') as reader: response = reader.domain('203.0.113.0') print(f"IP Address: {response.ip_address}") print(f"Domain: {response.domain}") print(f"Network: {response.network}") ```