Reverse geocoding for Traccar without Google
Traccar shows raw latitude/longitude on positions until you configure a reverse
geocoder. The built-in options either send every position to Google/HERE (a
privacy and cost problem) or point at the shared photon.komoot.io instance,
which is fair-use only and has no uptime guarantee.
ChibiGeo is a hosted Photon endpoint: flat-rate, EU-only, with a hard monthly cap and no overage billing. Traccar already speaks Photon's format, so wiring it up is a few config lines — no code, no plugin, no surprise invoice.
Prerequisites
- A running Traccar server (self-hosted).
- A ChibiGeo API key. The Self-Hoster plan (€9.99/mo) is built for exactly this — supported self-hosted apps like Traccar. Grab a key at app.chibigeo.com.
Configuration
Edit your conf/traccar.xml and add these entries inside the <properties>
block:
<entry key='geocoder.enable'>true</entry>
<entry key='geocoder.type'>geocodejson</entry>
<entry key='geocoder.url'>https://app.chibigeo.com/v1/photon/reverse</entry>
<entry key='geocoder.key'>ck_your_key_here</entry>
<entry key='geocoder.language'>en</entry>
What each line does:
| Key | Value | Why |
|---|---|---|
geocoder.type | geocodejson | Selects Traccar's GeocodeJsonGeocoder, which parses Photon's GeoJSON response |
geocoder.url | https://app.chibigeo.com/v1/photon/reverse | ChibiGeo's Photon-compatible reverse endpoint |
geocoder.key | your ck_… key | Traccar sends this as &key=; ChibiGeo authenticates the request from it |
geocoder.language | en (or de, fr, …) | Language for returned place names |
Restart Traccar. New positions will now be reverse-geocoded to addresses.
Optional tuning
Traccar caches results and can skip geocoding for stationary positions:
<entry key='geocoder.cacheSize'>10000</entry>
<entry key='geocoder.ignorePositions'>false</entry>
<entry key='geocoder.processInvalidPositions'>false</entry>
<entry key='geocoder.onlyAddress'>false</entry>
geocoder.cacheSize is the single biggest lever on your quota — a device that
sits in one place all day resolves to one cached address, not thousands of
lookups.
Verifying it works
Send a test request with the same shape Traccar uses:
curl "https://app.chibigeo.com/v1/photon/reverse?lat=52.516&lon=13.377&key=ck_your_key_here"
You should get a GeoJSON FeatureCollection back with properties.name,
properties.street, properties.city, and properties.country. In the Traccar
UI, open a device's position — the address column now shows a street address
instead of coordinates.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Addresses still show as coordinates | Geocoder not enabled or cached miss | Confirm geocoder.enable=true; restart; move the device |
401 invalid_api_key in Traccar logs | Wrong or revoked key | Re-copy the key from your dashboard |
429 Too Many Requests | Monthly cap reached | ChibiGeo hard-caps rather than billing overage — raise geocoder.cacheSize or upgrade the plan |
| Wrong language | geocoder.language unset | Set it to your ISO language code |
Why ChibiGeo over the alternatives
- vs Google/HERE: no per-request billing surprises, no sending fleet positions to an ad company, EU data residency.
- vs
photon.komoot.io: a real cap and rate limit you can rely on, plus a status page — the public komoot instance is best-effort and will throttle a fleet without warning. See photon.komoot.io rate limits. - vs self-hosting Photon: no ~95 GB planet index on SSD, no 64 GB RAM budget, no multi-hour import. A key works in two minutes. See what it takes to self-host Photon.