Skip to main content

A modern Python client library for ipapi.co IP geolocation API

Project description

IPyAPI

Tests Code Quality PyPI version Python versions License: MIT

A modern Python client library for the ipapi.co IP geolocation API. Built with httpx, full async support, automatic retries, and optional Pydantic v2 models.

Features

  • Sync & Async — both IPyAPI and AsyncIPyAPI clients
  • Typed returnsReturnType.OBJECT (dataclass), ReturnType.DICT, or ReturnType.PYDANTIC
  • Optional Pydantic v2 — install with ipyapi[pydantic] to get validated Pydantic models
  • Batch lookupsget_batch() for multiple IPs (async uses asyncio.gather)
  • Auto retry — exponential backoff on 429 rate limit responses
  • IP validation — client-side check before any network request
  • Complete API coverage — all fields, all response formats (JSON, XML, CSV, YAML, JSONP)
  • Full type hints@overload signatures for precise IDE inference
  • Python 3.10+

Installation

pip install ipyapi
# or
uv add ipyapi

With optional Pydantic support:

pip install 'ipyapi[pydantic]'
# or
uv add 'ipyapi[pydantic]'

Quick Start

Synchronous

from ipyapi import IPyAPI

with IPyAPI() as client:
    location = client.get_location("8.8.8.8")
    print(f"{location.city}, {location.country_name}")
    # Mountain View, United States

Asynchronous

import asyncio
from ipyapi import AsyncIPyAPI

async def main():
    async with AsyncIPyAPI() as client:
        location = await client.get_location("8.8.8.8")
        print(f"{location.city}, {location.country_name}")

asyncio.run(main())

Usage Examples

Return Types

from ipyapi import IPyAPI, ReturnType

with IPyAPI() as client:
    # Default — returns IPLocation dataclass
    location = client.get_location("8.8.8.8")
    print(location.country_name)

    # As dict
    data = client.get_location("8.8.8.8", return_type=ReturnType.DICT)
    print(data["country_name"])

    # As Pydantic model (requires ipyapi[pydantic])
    model = client.get_location("8.8.8.8", return_type=ReturnType.PYDANTIC)
    print(model.country_name)

Batch Lookup

with IPyAPI() as client:
    results = client.get_batch(["8.8.8.8", "1.1.1.1"])
    for r in results:
        print(f"{r.ip}{r.org}")

Async batch runs concurrently via asyncio.gather:

async with AsyncIPyAPI() as client:
    results = await client.get_batch(["8.8.8.8", "1.1.1.1"])

Retry Configuration

# Retry up to 5 times on 429, with 2s base backoff (sleeps 2, 4, 8, 16, 32s)
with IPyAPI(max_retries=5, retry_backoff=2.0) as client:
    location = client.get_location("8.8.8.8")

Single Fields

with IPyAPI() as client:
    print(client.get_ip())
    print(client.get_city("8.8.8.8"))
    print(client.get_country("8.8.8.8"))
    print(client.get_country_name("8.8.8.8"))
    print(client.get_timezone("8.8.8.8"))
    print(client.get_currency("8.8.8.8"))
    print(client.get_asn("8.8.8.8"))
    print(client.get_org("8.8.8.8"))

    # Any field by name
    postal = client.get_field("postal", "8.8.8.8")

Raw Response Formats

with IPyAPI() as client:
    json_data = client.get_location_raw("8.8.8.8", format="json")
    xml_data  = client.get_location_raw("8.8.8.8", format="xml")
    csv_data  = client.get_location_raw("8.8.8.8", format="csv")
    yaml_data = client.get_location_raw("8.8.8.8", format="yaml")

Error Handling

from ipyapi import IPyAPI
from ipyapi.exceptions import InvalidIPAddressError, RateLimitError, IPyAPIError

with IPyAPI() as client:
    try:
        location = client.get_location("not-an-ip")
    except InvalidIPAddressError:
        print("Invalid IP address")
    except RateLimitError:
        print("Rate limited — retries exhausted")
    except IPyAPIError as e:
        print(f"API error {e.status_code}: {e.message}")

API Reference

Client constructors

IPyAPI(
    api_key=None,       # API key for paid plans
    base_url="https://ipapi.co",
    timeout=10.0,       # seconds
    max_retries=3,      # retries on 429
    retry_backoff=1.0,  # base backoff in seconds (sleeps backoff * 2^attempt)
)

AsyncIPyAPI accepts the same parameters.

Methods

Method Returns
get_location(ip=None, return_type=ReturnType.OBJECT) IPLocation / dict / PydanticIPLocation
get_batch(ips, return_type=ReturnType.OBJECT) list[IPLocation] / list[dict] / list[PydanticIPLocation]
get_field(field, ip=None) str
get_location_raw(ip=None, format="json") str
get_ip() str
get_city(ip=None) str
get_country(ip=None) str
get_country_name(ip=None) str
get_timezone(ip=None) str
get_currency(ip=None) str
get_asn(ip=None) str
get_org(ip=None) str

IPLocation fields

ip, network, version, city, region, region_code, country, country_name, country_code, country_code_iso3, country_capital, country_tld, continent_code, in_eu, postal, latitude, longitude, timezone, utc_offset, country_calling_code, currency, currency_name, languages, country_area, country_population, asn, org, hostname, latlong

Exceptions

All inherit from IPyAPIError:

Exception Trigger
InvalidIPAddressError Invalid IP format (raised client-side)
ReservedIPAddressError Reserved/private IP (raised by API)
BadRequestError 400
ForbiddenError 403
NotFoundError 404
MethodNotAllowedError 405
RateLimitError 429 after all retries exhausted

Development

git clone https://github.com/wihlarkop/ipyapi.git
cd ipyapi
uv sync --all-extras

uv run pytest                                    # run tests
uv run pytest --cov=ipyapi --cov-report=html     # with coverage
uv run ruff check ipyapi/ tests/                 # lint
uv run ruff format ipyapi/ tests/                # format

Rate Limits

  • Free tier: 1,000 requests/day, 30 requests/minute
  • For higher limits see ipapi.co pricing

License

MIT — see LICENSE for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ipyapi-0.2.0.tar.gz (52.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ipyapi-0.2.0-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file ipyapi-0.2.0.tar.gz.

File metadata

  • Download URL: ipyapi-0.2.0.tar.gz
  • Upload date:
  • Size: 52.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ipyapi-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c800199d4be2fa0dce0e40a24a6ef3eb4dc52543a2c3f78d8ba71e50464ac667
MD5 3bbb23f7c3b10ed2454fc606d2e1fad2
BLAKE2b-256 c3d4b9a119fb4221410cc9558429f3e7d0d440351c53a16622c7d16641968912

See more details on using hashes here.

File details

Details for the file ipyapi-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: ipyapi-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ipyapi-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec407452dd1f5304a96106df2afdb924d60755a2eeef5bd2f331f75272b35120
MD5 92a42b99e542b08e584db609de13eeee
BLAKE2b-256 4f73ae3748659179c4451e52b814956c12ef088d3f4cf090a016c0d8c591fb48

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page