evo.locate
Public repository (MIT license): github.com/kellymichels/evo.locate
Self-hosted IP geolocation API. No account, no API key, no per-query cost, and no visitor IP ever leaves the machine it runs on.
It answers with the same JSON field names as ip2location.io's free tier, so it is a drop-in replacement for anything already written against that API — repoint the URL and you are done.
Data comes from DB-IP's free Lite databases, held locally and refreshed monthly by the service itself.
Why
Commercial IP geolocation is priced per lookup, and the free tiers that aren't priced per lookup want an account, a key that expires, and a verified email. For the common case — "which country and network is this log line from?" — you do not need any of that. The data is a 140 MB file you can just hold.
Running it yourself also means visitor IP addresses are never sent to a third party, which is usually the whole reason the question came up.
Guides
| Guide | What it covers |
|---|---|
| API reference | Endpoints, status codes, caching, and the ip2location drop-in mapping |
| Deploying | Docker, bare Python, systemd, configuration, and troubleshooting |
Quick start
bash
docker compose up -dOn first boot it downloads the DB-IP Lite databases (~62 MB compressed, ~140 MB on disk) and starts serving. That takes a minute or two; /health answers 503 until it is ready.
bash
curl localhost:9100/v1/lookup/8.8.8.8json
{
"ip": "8.8.8.8",
"country_code": "US",
"country_name": "United States",
"region_name": "California",
"city_name": "Mountain View",
"latitude": 37.422,
"longitude": -122.085,
"asn": "15169",
"as": "Google LLC"
}That is the whole surface for most users. Everything else — running it without Docker, keeping it alive as a service, tuning refresh behaviour — is in Deploying.
Attribution — required
The DB-IP Lite databases are licensed CC BY 4.0. If you display results from this service on a web page, you must credit DB-IP with a link:
html
IP Geolocation by <a href="https://db-ip.com">DB-IP</a>Every response carries an X-Data-Attribution header as a reminder, and GET /v1/attribution returns the text and URL, so compliance does not depend on anyone reading this page.
This obligation is yours as the operator. The service code itself is MIT licensed; the data is CC BY.
Development
bash
python -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/pytestThe test suite builds tiny in-memory .mmdb fixtures rather than downloading anything, so it is fast, offline and deterministic.
README.txt is a plain-text rendering of the repository README for terminals and anywhere markdown doesn't render. It is generated — never edit it by hand:
bash
python scripts/readme_txt.pyThe test suite fails if it drifts out of sync with README.md.
To check the real download path and real data end to end:
bash
python scripts/smoke_real_db.pyThat one does hit the network and pulls ~62 MB, which is why it is not part of the suite.
Licence
Code: MIT. Data: CC BY 4.0, © DB-IP.