Skip to main content

GeoInfer Python SDK

The official Python client library for the GeoInfer API — AI-powered image geolocation without GPS, EXIF, or metadata.

PyPI version Python License


What is GeoInfer?

GeoInfer determines where a photo was taken by analysing its visual content alone — no GPS signal, no EXIF data, no metadata required. Results are delivered in under a second, with global coverage including remote regions, conflict zones, and GPS-denied environments.

The API exposes two model families:

Model type Output Accuracy
Global Geographic clusters with coordinates and radius 1 km – 100 km, worldwide
Accuracy (regional) Ranked coordinate predictions with confidence scores Metre-level, within a specific region

Note: Accuracy models are region-specific and generally whitelisted — they are not available to the general public. Contact geoinfer.com to enquire about access.


Requirements

  • Python 3.9 or later
  • A GeoInfer API key — get one at geoinfer.com

Installation

pip install geoinfer

Quick start

from geoinfer import GeoInfer

client = GeoInfer(api_key="geo_...")

# List models your API key has access to
for m in client.predictions.models():
    print(m.model_id, m.model_type, f"{m.credits_per_use} credit(s)")

# Global model — returns geographic clusters
result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
top = result.prediction.clusters[0]
print(top.location.name, top.center.latitude, top.center.longitude)

# Accuracy / regional model — returns ranked predictions
result = client.predictions.predict("photo.jpg", model_id="pais_vasco_v0_1")
top = result.prediction.top_prediction
if top:
    print(top.latitude, top.longitude, f"{top.confidence:.1%} confidence")

Authentication

Pass your API key at client construction. It is sent as the X-GeoInfer-Key header on every request.

client = GeoInfer(api_key="geo_...")

API keys can be managed from your dashboard at geoinfer.com.


Model access

Available models are determined by your API key — some models are public and some are whitelisted per account. models() returns only the models your key has access to:

models = client.predictions.models()
for m in models:
    print(m.model_id, m.model_type, m.credits_per_use)

The model list is fetched on first use and cached for 5 minutes. Passing a model_id that is unknown to your account or disabled raises InvalidModelError immediately — before any prediction request is made.


Async support

AsyncGeoInfer mirrors the synchronous client and is safe to use in any asyncio application:

import asyncio
from geoinfer import AsyncGeoInfer

async def main():
    async with AsyncGeoInfer(api_key="geo_...") as client:
        result = await client.predictions.predict("photo.jpg", model_id="global_v0_1")
        top = result.prediction.clusters[0]
        print(top.location.name, top.center.latitude, top.center.longitude)

asyncio.run(main())

File input

predict() accepts five input forms:

from pathlib import Path

# URL — the SDK fetches the image and uploads it automatically
client.predictions.predict("https://example.com/photo.jpg", model_id="global_v0_1")

# Path string
client.predictions.predict("photo.jpg", model_id="global_v0_1")

# pathlib.Path
client.predictions.predict(Path("photo.jpg"), model_id="global_v0_1")

# Raw bytes (already loaded into memory)
with open("photo.jpg", "rb") as f:
    client.predictions.predict(f.read(), model_id="global_v0_1")

# Binary file-like object (streamed)
with open("photo.jpg", "rb") as f:
    client.predictions.predict(f, model_id="global_v0_1")

URL inputs are fetched client-side and uploaded as bytes — the image is not stored or cached. Any http:// or https:// string is treated as a URL. File objects must be opened in binary mode ("rb"); passing a text-mode object raises TypeError.

Maximum file size: 10 MB.


Credits

Each prediction consumes credits according to the model used. Check your balance at any time:

summary = client.credits.summary()
print(summary.summary.total_available)    # total credits available now
print(summary.subscription.remaining)     # subscription allowance remaining
print(summary.summary.topup_credits)      # one-time top-up balance

Credits consumed are reported on every PredictionResponse:

result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
print(f"Used {result.credits_consumed} credit(s). ID: {result.prediction_id}")

Rate limits

Rate-limit metadata is attached to every PredictionResponse:

result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
rl = result.rate_limit
print(f"{rl.remaining} requests remaining, window resets in {rl.reset}s")

When the limit is exceeded RateLimitError is raised with a retry_after attribute:

import time
from geoinfer import RateLimitError

try:
    result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
except RateLimitError as e:
    if e.retry_after:
        time.sleep(e.retry_after)

Error handling

All SDK exceptions inherit from GeoInferError.

Exception HTTP status When raised
AuthenticationError 401 Missing or invalid API key
InsufficientCreditsError 402 Account has insufficient credits
ForbiddenError 403 Access denied to this resource
FileTooLargeError 413 Image exceeds the 10 MB limit
InvalidFileTypeError 422 File format is not supported
RateLimitError 429 Request rate limit exceeded
InvalidModelError — model_id is not in your account's model list or is disabled
APIError other Unexpected non-2xx response
from geoinfer import (
    GeoInferError,
    AuthenticationError,
    InsufficientCreditsError,
    InvalidModelError,
    RateLimitError,
)

try:
    result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
except InvalidModelError as e:
    print(e.message)                  # includes a list of your available model IDs
except RateLimitError as e:
    if e.retry_after:
        time.sleep(e.retry_after)
except InsufficientCreditsError:
    print("Top up credits at geoinfer.com")
except AuthenticationError:
    print("Check your API key at geoinfer.com")
except GeoInferError as e:
    print(e.message_code, e.message)

Context managers

Both clients support context managers for deterministic connection cleanup:

# Sync
with GeoInfer(api_key="geo_...") as client:
    result = client.predictions.predict("photo.jpg", model_id="global_v0_1")

# Async
async with AsyncGeoInfer(api_key="geo_...") as client:
    result = await client.predictions.predict("photo.jpg", model_id="global_v0_1")

Configuration

Parameter Default Description
api_key (required) Your GeoInfer API key
base_url https://api.geoinfer.com Override the API base URL
timeout 60 HTTP request timeout in seconds
model_cache_ttl 300 Seconds to cache the model list before re-fetching

Type safety

All response objects are immutable frozen dataclasses. Narrow on result.prediction.result_type to get the specific prediction type:

from geoinfer.types import CoordinatePredictionResult, AccuracyPredictionResult

result = client.predictions.predict("photo.jpg", model_id="global_v0_1")
if isinstance(result.prediction, CoordinatePredictionResult):
    print(result.prediction.clusters[0].location.name)
elif isinstance(result.prediction, AccuracyPredictionResult):
    print(result.prediction.top_prediction.confidence)

License

Apache 2.0 — see LICENSE.

Metadata

Release files for geoinfer 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for geoinfer 0.0.1
File Size Uploaded
geoinfer-0.0.1.tar.gz 62.0 kB Details

Release files / geoinfer-0.0.1.tar.gz

Download URL geoinfer-0.0.1.tar.gz
Size 62.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9e354414243ebbec5adc07a8302b18d8cd48d32f11197cdf471a6bb8ae49ba08
BLAKE2b-256 checksum
How to use checksums
3e78face23860eecff2c26e73ba7426826d8b559a7aef5e93370a77188f2681e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.1 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page