Getting Started
The GeoAxis API lets you upload any image and get back its geographic location. Two search modes are available:
AI analyzes visual clues to locate the image anywhere in the world.
Matches against a city's indexed database — fast, sub-300ms results.
https://api.geoaxis.aiInstallation
Install the official Python wrapper from PyPI:
pip install pygeoaxis
Or use the API directly with any HTTP client — requests, fetch, curl, etc. No SDK required.
Python SDK Usage
from pygeoaxis import GeoAxis # Initialize with your API key client = GeoAxis(token="<your_api_key>") # The SDK wraps the REST API — see below for endpoints
Requirements
- Python 3.6+
- A GeoAxis account with an active Pro or Business subscription
- Your API key (from Dashboard → Settings)
Authentication
All protected endpoints require your API key in the Authorization header:
Authorization: Bearer <your_api_key>
Getting Your API Key
- Sign in at
geoaxis.ai/login - Subscribe to a Pro or Business plan at
geoaxis.ai/pricing - Open your Dashboard
- Click your avatar (bottom-left) → "API Key"
- Click "Reveal" to see your key, then "Copy"
Using Your Key
import requests
API_KEY = "<your_api_key>"
# Pass in every request:
headers = {"Authorization": f"Bearer {API_KEY}"}const API_KEY = "<your_api_key>";
// Pass in every request:
headers: { "Authorization": `Bearer ${API_KEY}` }Quick Start
Geolocate an image in 4 lines of Python:
import requests, base64
API_KEY = "<your_api_key>"
image = base64.b64encode(open("photo.jpg", "rb").read()).decode()
res = requests.post(
"https://api.geoaxis.ai/api/search",
headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
json={"image_base64": image, "global": True}
)
loc = res.json()["location"]
print(f"{loc['location_name']}, {loc['country']}")
print(f"Coordinates: ({loc['lat']}, {loc['lng']})")
print(f"Confidence: {loc['confidence']:.0%}")Paris, France Coordinates: (48.8566, 2.3522) Confidence: 85%
POST /api/search — Global
Search anywhere in the world. Our AI analyzes visual clues — signs, architecture, vegetation, terrain — to predict the location.
| Parameter | Type | Required | Description |
|---|---|---|---|
| image | file | Yes | Image file (multipart upload) |
| global | string | Yes | Must be "true" |
| context | string | No | Hint to narrow search, e.g. "somewhere in Europe" |
Python (file upload)
import requests
res = requests.post(
"https://api.geoaxis.ai/api/search",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": open("photo.jpg", "rb")},
data={"global": "true", "context": "looks like Southeast Asia"},
)
loc = res.json()["location"]
print(f"{loc['location_name']}, {loc['country']}")
print(f"({loc['lat']}, {loc['lng']}) ± {loc['radius_km']}km")
print(f"Confidence: {loc['confidence']:.0%}")
print(f"Analysis: {loc['analysis_summary']}")
print(f"Key clues: {', '.join(loc['key_indicators'])}")JavaScript
const formData = new FormData();
formData.append("image", fileInput.files[0]);
formData.append("global", "true");
formData.append("context", "European city");
const res = await fetch("https://api.geoaxis.ai/api/search", {
method: "POST",
headers: { "Authorization": `Bearer ${API_KEY}` },
body: formData,
});
const { location } = await res.json();
console.log(`${location.location_name}, ${location.country}`);
console.log(`Confidence: ${(location.confidence * 100).toFixed(0)}%`);Response
{
"success": true,
"search_type": "global",
"location": {
"lat": 48.8566,
"lng": 2.3522,
"radius_km": 5.0,
"radius_meters": 5000,
"confidence": 0.85,
"location_name": "Paris",
"country": "France",
"analysis_summary": "Eiffel Tower visible, Haussmann architecture...",
"key_indicators": ["Eiffel Tower", "French street signs", "Haussmann buildings"]
}
}POST /api/search — City
Search against a specific city's indexed database for fast, precise matching — sub-300ms response times.
| Parameter | Type | Required | Description |
|---|---|---|---|
| image | file | Yes | Image file (multipart upload) |
| city_path | string | Yes | City index path, e.g. "US/Texas/Dallas" |
| k | integer | No | Number of results (default: 10) |
Python
import requests
res = requests.post(
"https://api.geoaxis.ai/api/search",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": ("photo.jpg", open("photo.jpg", "rb"), "image/jpeg")},
data={"city_path": "US/Texas/Dallas", "k": "5"},
)
data = res.json()
for r in data["results"]:
print(f" lat={r['lat']}, lng={r['lng']}, score={r['score']}")Response
{
"success": true,
"search_type": "city",
"city_path": "US/Texas/Dallas",
"results": [
{ "lat": 32.7767, "lng": -96.7970, "score": 0.95 },
{ "lat": 32.7800, "lng": -96.8010, "score": 0.89 }
],
"total": 2,
"timing": {
"feature_extraction_ms": 245.3,
"index_search_ms": 18.7,
"total_ms": 264.0
}
}GET /api/locations
List all available indexed cities you can search against. Use this to populate a city selector in your UI.
curl https://api.geoaxis.ai/api/locations \ -H "Authorization: Bearer <your_api_key>"
res = requests.get(
"https://api.geoaxis.ai/api/locations",
headers={"Authorization": f"Bearer {API_KEY}"},
)
cities = res.json()["locations"]
for city in cities:
print(city["path"]) # e.g. "US/Texas/Dallas"GET /api/health
Check if the server is ready. No authentication required.
curl https://api.geoaxis.ai/api/health
{
"status": "ok",
"model_loaded": true,
"device": "cuda",
"indexes_loaded": 17,
"total_vectors": 95640224,
"queue": { "queue_length": 0, "active": 0, "total_processed": 5678 }
}Base64 JSON Mode
Instead of multipart file upload, you can send the image as a base64-encoded string in a JSON body. This is useful when you already have the image in memory or as a data URI.
| Parameter | Type | Required | Description |
|---|---|---|---|
| image_base64 | string | Yes | Base64-encoded image (raw or data URI) |
| format | string | No | Image format: jpg, png, webp (default: jpg) |
| global | boolean | No | true for global search |
| city_path | string | No* | Required if global is not true |
| context | string | No | Hint for global search |
| k | integer | No | Number of results (default: 10) |
Python
import requests, base64
image_b64 = base64.b64encode(open("photo.jpg", "rb").read()).decode()
# Global search
res = requests.post(
"https://api.geoaxis.ai/api/search",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"image_base64": image_b64,
"format": "jpg",
"global": True,
"context": "somewhere in Asia",
},
)
print(res.json()["location"])JavaScript (Browser)
// Convert file input to base64 and send as JSON
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = async () => {
const res = await fetch("https://api.geoaxis.ai/api/search", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_base64: reader.result, // data:image/jpeg;base64,... works
global: true,
}),
});
const { location } = await res.json();
console.log(location);
};
reader.readAsDataURL(file);Node.js
const fs = require("fs");
const imageBase64 = fs.readFileSync("photo.jpg").toString("base64");
const res = await fetch("https://api.geoaxis.ai/api/search", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_base64: imageBase64,
format: "jpg",
city_path: "US/Texas/Dallas",
k: 5,
}),
});
console.log(await res.json());Rate Limits
| Requests per user | 1 every 10 seconds |
| Max image size | 16 MB |
| Accepted formats | PNG, JPG, JPEG, HEIC, BMP, WebP |
| Max queue depth | 50 concurrent requests |
When rate limited you receive 429:
{ "error": "Rate limited. Try again in 7s.", "retry_after": 8 }Error Codes
| Code | Meaning | When |
|---|---|---|
| 400 | Bad Request | Missing image, invalid format, missing city_path |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | No active subscription |
| 404 | Not Found | City not indexed |
| 413 | Too Large | Image exceeds 16 MB |
| 429 | Rate Limited | > 1 request per 10s |
| 503 | Unavailable | Model loading or queue full (50 max) |
cURL Examples
# Health check (no auth)
curl https://api.geoaxis.ai/api/health
# List available cities
curl https://api.geoaxis.ai/api/locations \
-H "Authorization: Bearer <your_api_key>"
# Global search (file upload)
curl -X POST https://api.geoaxis.ai/api/search \
-H "Authorization: Bearer <your_api_key>" \
-F "image=@photo.jpg" \
-F "global=true" \
-F "context=European city"
# City search (file upload)
curl -X POST https://api.geoaxis.ai/api/search \
-H "Authorization: Bearer <your_api_key>" \
-F "image=@photo.jpg" \
-F "city_path=US/Texas/Dallas" \
-F "k=10"
# Global search (base64 JSON)
curl -X POST https://api.geoaxis.ai/api/search \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d "{
\"image_base64\": \"$(base64 -w0 photo.jpg)\",
\"global\": true,
\"context\": \"somewhere in Europe\"
}"Need help? contact@geoaxis.ai