Official Python library for IPInfo IP address geolocation and data lookups
—
Response objects, caching system, exception handling, and utility functions for data formatting, validation, and configuration management in the IPInfo Python library.
The primary response object that encapsulates IP address information with attribute-based access and data enrichment functionality.
class Details:
def __init__(self, details):
"""
Initialize Details object with IP information dictionary.
Parameters:
- details (dict): Dictionary containing IP address information
"""
def __getattr__(self, attr):
"""
Return attribute if it exists in details, else raise AttributeError.
Parameters:
- attr (str): Attribute name to access
Returns:
Any: Value of the requested attribute
Raises:
AttributeError: When attribute doesn't exist in details
"""
@property
def all(self):
"""
Return all details as dictionary.
Returns:
dict: Complete details dictionary
"""Specialized exception classes for handling API errors, quota limits, and timeout conditions.
class RequestQuotaExceededError(Exception):
"""
Error indicating that user's monthly request quota has been exceeded.
Raised when API returns 429 status code.
"""
class TimeoutExceededError(Exception):
"""
Error indicating that some timeout has been exceeded.
Raised when operation exceeds specified timeout limits.
"""
class APIError(Exception):
def __init__(self, error_code, error_json):
"""
General API error with status code and response details.
Parameters:
- error_code (int): HTTP status code
- error_json (dict): Error response JSON
"""
def __str__(self):
"""
Return formatted error string with code and JSON response.
Returns:
str: Formatted error message
"""Abstract cache interface and default LRU implementation for efficient IP data caching.
class CacheInterface:
"""Abstract interface for custom cache implementations."""
def __contains__(self, key):
"""Check if key exists in cache."""
def __setitem__(self, key, value):
"""Set cache value for key."""
def __getitem__(self, key):
"""Get cache value for key."""
def __delitem__(self, key):
"""Delete cache entry for key."""
class DefaultCache(CacheInterface):
def __init__(self, **cache_options):
"""
Default in-memory LRU cache with TTL support.
Parameters:
- **cache_options: Options passed to cachetools.TTLCache
- maxsize (int): Maximum cache entries (default: 4096)
- ttl (int): Time to live in seconds (default: 86400)
"""
def __contains__(self, key):
"""Check if key exists in cache."""
def __setitem__(self, key, value):
"""Set cache value for key."""
def __getitem__(self, key):
"""Get cache value for key."""
def __delitem__(self, key):
"""Delete cache entry for key."""Helper functions for HTTP headers, data formatting, file I/O, and cache key management.
def get_headers(access_token, custom_headers):
"""
Build headers for request to IPinfo API.
Parameters:
- access_token (str, optional): API access token
- custom_headers (dict, optional): Custom HTTP headers
Returns:
dict: Complete headers dictionary with user-agent, accept, and authorization
"""
def format_details(details, countries, eu_countries, countries_flags, countries_currencies, continents):
"""
Format details dictionary with additional country and geographic data.
Adds country_name, isEU, country_flag_url, country_flag,
country_currency, continent, latitude, and longitude fields.
Parameters:
- details (dict): Raw IP details to format
- countries (dict): Country code to name mappings
- eu_countries (list): List of EU country codes
- countries_flags (dict): Country flag data
- countries_currencies (dict): Country currency data
- continents (dict): Continent mappings
"""
def read_coords(location):
"""
Parse location string into latitude and longitude tuple.
Parameters:
- location (str): Location string in format "lat,lon"
Returns:
tuple: (latitude, longitude) as strings, or (None, None) if invalid
"""
def read_json_file(json_file):
"""
Read and parse JSON file from package data directory.
Parameters:
- json_file (str): Filename relative to package directory
Returns:
dict: Parsed JSON data
"""
def return_or_fail(raise_on_fail, e, v):
"""
Either raise exception or return value based on flag.
Parameters:
- raise_on_fail (bool): Whether to raise exception
- e (Exception): Exception to raise
- v (Any): Value to return if not raising
Returns:
Any: Returns v if raise_on_fail is False
Raises:
Exception: Raises e if raise_on_fail is True
"""
def cache_key(k):
"""
Transform user input key into versioned cache key.
Parameters:
- k (str): User input key
Returns:
str: Versioned cache key
"""Functions for identifying private and reserved IP address ranges.
def is_bogon(ip_address):
"""
Check if IP address is a bogon (private/reserved address).
Parameters:
- ip_address (str): IP address to check
Returns:
bool: True if IP is in bogon networks, False otherwise
"""
# Predefined bogon networks
BOGON_NETWORKS = [
# IPv4 bogon networks
ipaddress.ip_network("0.0.0.0/8"), # This network
ipaddress.ip_network("10.0.0.0/8"), # Private-use
ipaddress.ip_network("127.0.0.0/8"), # Loopback
ipaddress.ip_network("169.254.0.0/16"), # Link-local
ipaddress.ip_network("172.16.0.0/12"), # Private-use
ipaddress.ip_network("192.168.0.0/16"), # Private-use
# ... additional bogon networks
]Pre-loaded geographic and internationalization data for response enrichment.
# Geographic data mappings
continents = {
"US": {"code": "NA", "name": "North America"},
"GB": {"code": "EU", "name": "Europe"},
# ... complete country to continent mappings
}
countries = {
"US": "United States",
"GB": "United Kingdom",
# ... complete country code to name mappings
}
countries_currencies = {
"US": {"code": "USD", "symbol": "$"},
"GB": {"code": "GBP", "symbol": "£"},
# ... complete currency mappings
}
eu_countries = [
"AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
"DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
"PL", "PT", "RO", "SK", "SI", "ES", "SE"
]
countries_flags = {
"US": {"emoji": "🇺🇸", "unicode": "U+1F1FA U+1F1F8"},
"GB": {"emoji": "🇬🇧", "unicode": "U+1F1EC U+1F1E7"},
# ... complete flag mappings
}
# API endpoints and configuration
API_URL = "https://ipinfo.io"
LITE_API_URL = "https://api.ipinfo.io/lite"
COUNTRY_FLAGS_URL = "https://cdn.ipinfo.io/static/images/countries-flags/"
BATCH_MAX_SIZE = 1000
CACHE_MAXSIZE = 4096
CACHE_TTL = 86400 # 24 hours
REQUEST_TIMEOUT_DEFAULT = 2
BATCH_REQ_TIMEOUT_DEFAULT = 5import ipinfo
from ipinfo.cache.interface import CacheInterface
import redis
class RedisCache(CacheInterface):
"""Redis-based cache implementation"""
def __init__(self, redis_client, ttl=86400):
self.redis = redis_client
self.ttl = ttl
def __contains__(self, key):
return self.redis.exists(key)
def __setitem__(self, key, value):
import json
self.redis.setex(key, self.ttl, json.dumps(value))
def __getitem__(self, key):
import json
value = self.redis.get(key)
if value is None:
raise KeyError(key)
return json.loads(value)
def __delitem__(self, key):
self.redis.delete(key)
# Use custom cache
redis_client = redis.Redis()
custom_cache = RedisCache(redis_client)
handler = ipinfo.getHandler('token', cache=custom_cache)import ipinfo
handler = ipinfo.getHandler('your_token')
details = handler.getDetails('8.8.8.8')
# Access individual attributes
print(details.city) # Mountain View
print(details.country) # US
print(details.country_name) # United States
print(details.isEU) # False
print(details.latitude) # 37.3860
print(details.longitude) # -122.0838
# Access all data as dictionary
all_data = details.all
print(all_data['hostname']) # dns.google
# Handle missing attributes
try:
print(details.nonexistent_field)
except AttributeError as e:
print(f"Field not available: {e}")import ipinfo
from ipinfo.exceptions import RequestQuotaExceededError, TimeoutExceededError
from ipinfo.error import APIError
handler = ipinfo.getHandler('invalid_token')
try:
details = handler.getDetails('8.8.8.8')
except RequestQuotaExceededError:
print("Quota exceeded - upgrade your plan")
except APIError as e:
print(f"API Error {e.error_code}")
print(f"Details: {e.error_json}")
except TimeoutExceededError:
print("Request timed out")from ipinfo.bogon import is_bogon
# Check if IP is private/reserved
print(is_bogon('192.168.1.1')) # True (private)
print(is_bogon('8.8.8.8')) # False (public)
print(is_bogon('127.0.0.1')) # True (loopback)import ipinfo
# Custom country names (e.g., for localization)
custom_countries = {
"US": "États-Unis",
"FR": "France",
"DE": "Allemagne"
}
# Custom EU country list
custom_eu = ["FR", "DE", "IT", "ES"] # Subset for example
handler = ipinfo.getHandler(
'your_token',
countries=custom_countries,
eu_countries=custom_eu
)
details = handler.getDetails('8.8.8.8')
print(details.country_name) # Uses custom mapping
print(details.isEU) # Uses custom EU list# Details object structure
DetailsDict = {
# Core API fields
'ip': str,
'hostname': str,
'city': str,
'region': str,
'country': str,
'loc': str, # "latitude,longitude"
'org': str,
'postal': str,
'timezone': str,
# Enhanced fields (added by library)
'country_name': str,
'latitude': str,
'longitude': str,
'isEU': bool,
'country_flag': dict, # {"emoji": str, "unicode": str}
'country_currency': dict, # {"code": str, "symbol": str}
'continent': dict, # {"code": str, "name": str}
'country_flag_url': str,
# Optional fields (may be present)
'asn': dict, # ASN information
'company': dict, # Company information
'carrier': dict, # Mobile carrier info
'privacy': dict, # Privacy/VPN detection
'abuse': dict, # Abuse contact info
'domains': dict # Associated domains
}
# Cache interface type
CacheInterface = {
'__contains__': callable,
'__getitem__': callable,
'__setitem__': callable,
'__delitem__': callable
}
# Geographic data types
CountryMapping = dict # Country code -> name
ContinentMapping = dict # Country code -> {"code": str, "name": str}
FlagMapping = dict # Country code -> {"emoji": str, "unicode": str}
CurrencyMapping = dict # Country code -> {"code": str, "symbol": str}Install with Tessl CLI
npx tessl i tessl/pypi-ipinfo