IP Geolocation API

A free, open source REST API to geolocate IPv4 and IPv6 addresses. Returns country, city, timezone, and coordinates โ€” powered by the MaxMind GeoLite2 database, self-hosted with no third-party calls.

โœ“ Free & Open Source โœ“ No API Key Required Self-Hostable Offline Database MIT License

Overview

The API uses the MaxMind GeoLite2-City database, which is bundled with the server. No external call is made at request time โ€” all lookups happen locally, making responses fast and privacy-preserving.

FieldDescriptionExample
country_codeISO 3166-1 alpha-2 country codeFR
country_nameFull country nameFrance
continentContinent nameEurope
cityCity name (may be null)Paris
postal_codePostal / ZIP code (may be null)75001
latitudeApproximate latitude48.8534
longitudeApproximate longitude2.3488
timezoneIANA timezone identifierEurope/Paris
accuracy_radius_kmEstimated accuracy in km50

โš ๏ธ Geolocation is approximate. City-level accuracy is typical but not guaranteed. Do not use for legal enforcement, precise targeting, or security-critical decisions.

Base URL

https://ip-geolocation-api-31u6.onrender.com

All responses are application/json. Supports IPv4 and IPv6.

โš ๏ธ The public instance runs on Render's free tier and may spin down after inactivity. The first request after a cold start can take up to 60 seconds (the database is also downloaded at startup) โ€” subsequent requests are fast.

Authentication

๐Ÿ”“ No authentication required. All endpoints are publicly accessible. CORS is enabled for all origins.

Rate Limiting

EndpointLimit
GET /geolocate/{ip}60 requests / minute per IP
GET /geolocate/me60 requests / minute per IP
POST /geolocate/batch10 requests / minute per IP
GET /country/{ip}120 requests / minute per IP
GET /timezone/{ip}120 requests / minute per IP

Exceeded limits return HTTP 429 with a Retry-After header.

GeoLite2 Database

This API uses the MaxMind GeoLite2-City database, available for free under the Creative Commons Attribution-ShareAlike 4.0 license.

The database is updated by MaxMind every Tuesday. For self-hosted instances, we recommend scheduling a weekly update.

๐Ÿ“ฆ The .mmdb database file is not included in the repository (it's in .gitignore). Download it from dev.maxmind.com and place it in the project root before starting the server.

Endpoints

GET /geolocate/{ip} Full geolocation for an IP address

Path Parameters

ParameterTypeDescription
ipstringIPv4 or IPv6 address to geolocate.

Example Request

curl https://ip-geolocation-api-31u6.onrender.com/geolocate/8.8.8.8

Example Response

{
  "ip": "8.8.8.8",
  "country_code": "US",
  "country_name": "United States",
  "continent": "North America",
  "city": "Mountain View",
  "postal_code": "94043",
  "latitude": 37.386,
  "longitude": -122.0838,
  "timezone": "America/Los_Angeles",
  "accuracy_radius_km": 1000
}
GET /geolocate/me Geolocate the caller's IP address

Detects the IP from the X-Forwarded-For header (set by Render's proxy) or the direct connection IP. Returns the same schema as /geolocate/{ip}.

Example Request

curl https://ip-geolocation-api-31u6.onrender.com/geolocate/me
POST /geolocate/batch Geolocate up to 10 IPs at once

Request Body

FieldTypeRequiredDescription
ipsstring[]requiredArray of IP addresses. Max 10.

Example Request

curl -X POST https://ip-geolocation-api-31u6.onrender.com/geolocate/batch \
  -H "Content-Type: application/json" \
  -d '{"ips": ["8.8.8.8", "1.1.1.1"]}'

Example Response

{
  "count": 2,
  "results": [
    { "ip": "8.8.8.8", "country_code": "US", "country_name": "United States", "city": "Mountain View", "timezone": "America/Los_Angeles", "..." : "..." },
    { "ip": "1.1.1.1", "country_code": "AU", "country_name": "Australia", "city": "Sydney", "timezone": "Australia/Sydney", "...": "..." }
  ]
}
GET /country/{ip} Lightweight country-only lookup

Faster and lighter than the full geolocation โ€” returns only country and continent data.

Example Request

curl https://ip-geolocation-api-31u6.onrender.com/country/8.8.8.8

Example Response

{
  "ip": "8.8.8.8",
  "country_code": "US",
  "country_name": "United States",
  "continent": "North America"
}
GET /timezone/{ip} Get timezone and coordinates for an IP

Example Request

curl https://ip-geolocation-api-31u6.onrender.com/timezone/8.8.8.8

Example Response

{
  "ip": "8.8.8.8",
  "timezone": "America/Los_Angeles",
  "latitude": 37.386,
  "longitude": -122.0838
}
GET /health Health check โ€” also reports database status
{ "status": "ok", "database": "available" }

Returns "database": "missing" if the .mmdb file is not present.

Error Codes

CodeMeaningCommon Cause
400Bad RequestInvalid IP address format, batch exceeds 10 items.
422Unprocessable EntityPOST body is not valid JSON or missing Content-Type: application/json header (affects POST /geolocate/batch).
404Not FoundIP address not found in the database (private ranges, unallocated blocks).
429Too Many RequestsRate limit exceeded.
503Service UnavailableGeoLite2 database file is missing from the server.

Error Response Format

{ "detail": "No data found for IP: 192.168.1.1" }

๐Ÿ’ก Private IP ranges (10.x.x.x, 192.168.x.x, 127.x.x.x) will return a 404 โ€” they are not in the geolocation database by design.

Self-Hosting

1. Get the GeoLite2 database

Create a free account at dev.maxmind.com, download GeoLite2-City.mmdb, and place it in the project root.

2. Run locally

git clone https://github.com/GregorySpro/ip-geolocation-api
cd ip-geolocation-api
pip install -r requirements.txt
# Place GeoLite2-City.mmdb in this directory
uvicorn main:app --reload

3. Keep the database up to date

MaxMind updates GeoLite2 every Tuesday. Use their GeoIP Update tool or a weekly cron job to refresh the file.

Deploy on Render

The repo includes a start.sh script that automatically downloads the GeoLite2-City database from MaxMind at startup using your license key. Set the MAXMIND_LICENSE_KEY environment variable in your Render service, then set the Start Command to bash start.sh. The render.yaml handles the rest.