Overview
GeoFlux is Swarnandhra's self-hosted geospatial data service, built with agriculture in mind. It runs a full Overpass API instance over the OpenStreetMap (OSM) database for India, and exposes it securely over HTTPS to registered users with personal API keys.
Typical uses:
- Agriculture: farmland and orchard mapping, irrigation coverage, distance to mandis and input dealers, aquaculture and village-level fact sheets.
- Research and student projects: GIS analysis, urban planning, transport studies, environmental mapping.
- Applications: "nearest hospital / ATM / bus stop" features, location-aware apps, campus and city dashboards.
- Data science: build datasets of facilities, road networks or land use for machine-learning and statistics.
- Teaching: hands-on lessons in spatial queries without depending on rate-limited public servers.
Why not the public Overpass servers? Public instances are shared worldwide and throttle heavy users. GeoFlux is dedicated to our users, keeps your queries on our own infrastructure, and gives each project a predictable quota.
What data you get
GeoFlux returns raw OpenStreetMap data. OSM describes the world with three element types:
| Element | What it is | Examples |
|---|---|---|
node | A single point with latitude/longitude | ATM, bus stop, tree, shop, peak |
way | An ordered list of nodes: a line or a closed shape | Road, river, building outline, park |
relation | A group of nodes/ways/relations with roles | District boundary, bus route, large lake with islands |
Every element carries tags (key=value pairs) that describe it, e.g. amenity=hospital, name=Apollo Hospital, name:te=…, opening_hours=Mo-Su 00:00-24:00. Querying GeoFlux is mostly about filtering by tags and location.
Main categories
| Category | Useful tags |
|---|---|
| Amenities and services | amenity=hospital|clinic|pharmacy|school|college|university|bank|atm|restaurant|fuel|police|place_of_worship |
| Shops | shop=supermarket|convenience|clothes|electronics|… |
| Transport | highway=* (roads, bus_stop), railway=station|rail|subway, aeroway=aerodrome, public_transport=* |
| Buildings | building=*, building:levels, addr:* |
| Land use and nature | landuse=*, natural=water|wood|beach|peak, waterway=river|canal, leisure=park |
| Boundaries | boundary=administrative with admin_level (4 = state, 5 = district, 6 = sub-district/mandal, 8 = town/village in most of India) |
| Tourism | tourism=hotel|attraction|museum|viewpoint, historic=* |
| Utilities | power=line|substation|tower, man_made=water_tower|tower, amenity=charging_station |
Coverage and freshness
The database covers India. It is a snapshot of OpenStreetMap; the exact date is returned in every JSON response as osm3s.timestamp_osm_base, and by GET /api/me. Data outside the coverage area returns empty results.
OpenStreetMap is built by volunteers. Coverage is excellent for roads and major facilities, but completeness varies by place and tag. Always validate critical data before using it for decisions.
Quick start
1. Get an API key from the GeoFlux administrator (see API keys). It looks like gf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
2. Store it in an environment variable rather than in your code:
# Linux / macOS export GEOFLUX_KEY="gf_your_key_here" # Windows PowerShell $env:GEOFLUX_KEY = "gf_your_key_here"
3. Check the key works:
curl -H "X-API-Key: $GEOFLUX_KEY" https://api.geoflux.swarnandhra.ac.in/api/me
4. Run your first query, all cafés within 1 km of a point in Hyderabad:
curl -X POST https://api.geoflux.swarnandhra.ac.in/api/interpreter \ -H "X-API-Key: $GEOFLUX_KEY" \ --data-urlencode 'data=[out:json][timeout:25]; node["amenity"="cafe"](around:1000,17.3850,78.4867); out;'
The response is JSON with an elements array:
{
"version": 0.6,
"generator": "Overpass API 0.7.62",
"osm3s": { "timestamp_osm_base": "2026-03-25T00:53:14Z", "copyright": "… ODbL." },
"elements": [
{ "type": "node", "id": 2261567007, "lat": 17.3871359, "lon": 78.4776933,
"tags": { "amenity": "cafe", "name": "…" } }
]
}
API keys
GeoFlux is not open to the public. Every request needs a valid API key, which is issued by the administrator for a specific person or project.
Requesting a key
Send a request to the GeoFlux administrator with:
- Your name, department or organisation, and email
- The purpose of the project and the expected volume (queries per day)
- How long you need access (e.g. one semester)
- Optionally, the fixed server IP addresses that will call the API (for extra protection)
What a key includes
| Property | Meaning |
|---|---|
| Validity period | The key only works between its valid from and valid until dates. Ask for an extension before it expires. |
| Daily quota | Maximum number of requests per UTC day. |
| Rate limit | Maximum requests per minute. |
| Concurrency | How many queries may run at the same time. |
| Max timeout | Upper limit for the [timeout:N] setting in your queries. |
| IP allow-list | Optional. If set, the key only works from those IP addresses. |
Keep your key secret. It identifies you, and all usage is logged against it. Do not commit it to Git, paste it in public forums, or embed it in public web pages. If a key leaks, ask the administrator to rotate it; the old key stops working immediately.
Authentication
All API calls must use HTTPS. Plain HTTP requests are rejected. Send the key in one of these ways, in order of preference:
| Method | Example | Notes |
|---|---|---|
| Header (recommended) | X-API-Key: gf_… | Never appears in URLs or logs. |
| Bearer token | Authorization: Bearer gf_… | Handy for tools with built-in bearer auth. |
| Query parameter | ?key=gf_… | Only for tools that cannot send headers. URLs can end up in browser history and proxy logs. |
Endpoints
Base URL: https://api.geoflux.swarnandhra.ac.in
POSTGET /api/interpreter
Runs an Overpass query. This is the same interface as the standard Overpass API.
- POST, form-encoded (recommended): body
data=<url-encoded query>, content typeapplication/x-www-form-urlencoded. - POST, raw: the query text as the request body.
- GET:
/api/interpreter?data=<url-encoded query>. Fine for short queries.
Maximum query size: 1 MB. The response format depends on the query's [out:…] setting (JSON, XML or CSV) and is streamed as it is produced.
GET /api/me
Returns details about your key: validity dates, days left, limits, how many requests you have used today, and the data snapshot date. Calls to /api/me do not count against your quota.
{
"key": { "name": "GIS lab project", "prefix": "gf_a1B2c3D", "valid_until": "2027-03-31T23:59:59.000Z", "days_left": 167 },
"limits": { "daily_quota": 1000, "used_today": 42, "remaining_today": 958,
"rate_per_minute": 30, "max_concurrent": 2, "max_timeout_seconds": 180 },
"data": { "coverage": "India", "osm_snapshot": "2026-03-25T00:53:14Z" }
}
GET /health
Public, no key needed. Returns 200 {"status":"ok"} when the backend is answering, 503 otherwise.
Response headers
| Header | Meaning |
|---|---|
X-GeoFlux-Quota-Limit | Your daily request quota |
X-GeoFlux-Quota-Remaining | Requests left today (UTC) |
X-GeoFlux-RateLimit-Remaining | Requests left in the current minute |
X-GeoFlux-Key-Expires | When your key stops working |
Retry-After | Seconds to wait, on 429 responses |
Limits & quotas
- Daily quota: counted per UTC day and resets at 00:00 UTC (05:30 IST).
- Rate limit: a rolling one-minute window.
- Concurrency: extra simultaneous queries are rejected, not queued. Wait for one to finish.
- Timeout: if your query has no
[timeout:N], the server default (180 s, or your key's maximum if lower) applies. A larger timeout than your key allows is rejected withtimeout_too_high. - Memory: Overpass's own
[maxsize:…]limit applies (512 MB by default). Very large extracts should be split into smaller areas.
The exact values for your key are in /api/me. If you need more, ask the administrator.
Overpass QL primer
Overpass QL is the query language of the Overpass API. The full reference is on the OSM wiki; this section covers what you need for most work.
Query structure
[out:json][timeout:60]; // settings: output format, time limit ( // union: collect results of several statements node["amenity"="hospital"](around:5000,16.4337,81.6966); way["amenity"="hospital"](around:5000,16.4337,81.6966); ); out center tags; // print results
Settings go first, in square brackets, ended by ;. Each statement ends with ;. Use nwr as a shortcut for "node, way and relation".
Filters
| Filter | Syntax |
|---|---|
| Tag equals | ["amenity"="school"] |
| Tag exists / does not exist | ["name"] / [!"name"] |
| Tag not equal | ["access"!="private"] |
| Regular expression | ["amenity"~"school|college|university"] |
| Case-insensitive regex | ["name"~"apollo",i] |
| Bounding box (south, west, north, east) | (17.30,78.40,17.45,78.55) |
| Radius around a point (metres, lat, lon) | (around:1500,17.385,78.4867) |
| Inside a named area | (area.a), see below |
| By ID | node(2261567007); way(123456); |
Areas & boundaries
To search inside a district, city or state, first find its boundary as an area, then filter by it:
[out:json][timeout:90]; area["boundary"="administrative"]["name"="West Godavari"]["admin_level"="5"]->.district; nwr["amenity"="hospital"](area.district); out center tags;
Tips: check the exact name and admin_level of a boundary first, since names can differ in spelling. Area queries are heavier than bounding-box or radius queries.
Output modes
| Statement | Returns |
|---|---|
out; | Elements with tags (nodes with coordinates, ways with node IDs) |
out center; | Adds a centre point to ways and relations, ideal for "list of places" |
out geom; | Full coordinates for ways and relations (for drawing lines and polygons) |
out tags; | Tags only, no geometry (smallest output) |
out ids; | IDs only |
out count; | Just the number of matching elements |
out 50; | At most 50 elements |
(._;>;); out; | Ways plus all their nodes (classic XML/OSM format) |
Formats: [out:json], [out:xml] (default), or CSV with chosen columns: [out:csv(name, ::lat, ::lon, "addr:city"; true; ",")].
Agriculture recipes
Ready-to-run queries for common agricultural questions. Replace the coordinates (latitude, longitude) or bounding box (south, west, north, east) with your own area. Mapping density varies by region, so if a query returns little data, try a nearby area or a broader tag.
Farmland parcels around a village
[out:json][timeout:90]; way["landuse"="farmland"](around:5000,16.4337,81.6966); out geom;
Crop-specific fields (paddy, sugarcane, cotton…)
[out:json][timeout:90]; nwr["landuse"="farmland"]["crop"~"rice|sugarcane|cotton"](16.2,81.4,16.7,82.0); out center tags;
Orchards, plantations and vineyards
[out:json][timeout:90]; nwr["landuse"~"orchard|vineyard|plantation"](around:20000,19.9975,73.7898); out center tags;
Irrigation canals, drains and ditches
[out:json][timeout:120]; way["waterway"~"canal|ditch|drain"](16.2,81.4,16.7,82.0); out geom;
Tanks, ponds and reservoirs (with names) as CSV
[out:csv(::id, name, water, ::lat, ::lon; true; ",")][timeout:90]; nwr["natural"="water"]["water"~"pond|reservoir|tank|lake"](16.2,81.4,16.7,82.0); out center;
Wells and water pumps
[out:json][timeout:60]; node["man_made"~"water_well|water_works|pumping_station"](around:10000,16.4337,81.6966); out;
Aquaculture ponds (fish / prawn farming)
[out:json][timeout:90]; nwr["landuse"="aquaculture"](16.2,81.4,16.7,82.0); out center tags;
Seed, fertiliser and pesticide shops
[out:json][timeout:60]; nwr["shop"~"agrarian|farm|garden_centre"](around:20000,16.3067,80.4365); out center tags;
Market yards, mandis and weekly markets
[out:json][timeout:60]; nwr["amenity"="marketplace"](around:25000,16.4337,81.6966); out center tags;
Warehouses, silos and cold storage
[out:json][timeout:90]; ( nwr["man_made"="silo"](16.2,81.4,16.7,82.0); nwr["building"="warehouse"](16.2,81.4,16.7,82.0); nwr["industrial"~"warehouse|cold_storage"](16.2,81.4,16.7,82.0); ); out center tags;
Veterinary clinics and dairies
[out:json][timeout:60]; ( nwr["amenity"="veterinary"](around:25000,22.5645,72.928); nwr["craft"="dairy"](around:25000,22.5645,72.928); nwr["shop"="dairy"](around:25000,22.5645,72.928); ); out center tags;
Farm tracks and village roads
[out:json][timeout:90]; way["highway"~"track|unclassified|tertiary"](around:5000,16.4337,81.6966); out geom;
All villages in a district (for a village table)
[out:csv(::id, name, "name:te", ::lat, ::lon; true; ",")][timeout:180]; area["boundary"="administrative"]["name"="West Godavari"]["admin_level"="5"]->.d; node["place"~"village|hamlet"](area.d); out;
Village fact sheet: what is within 3 km?
[out:json][timeout:90]; ( nwr["amenity"~"school|clinic|hospital|marketplace|veterinary|bank"](around:3000,16.4337,81.6966); nwr["shop"~"agrarian|farm"](around:3000,16.4337,81.6966); nwr["natural"="water"](around:3000,16.4337,81.6966); ); out center tags;
Tip for GIS and machine learning: use out geom; and convert to GeoJSON (see GeoJSON & GIS) to overlay farmland polygons on satellite imagery, or as training labels for land-use classification.
General recipes
Hospitals and clinics within 5 km (with centre points)
[out:json][timeout:60]; nwr["amenity"~"hospital|clinic"](around:5000,16.4337,81.6966); out center tags;
ATMs and banks in a bounding box
[out:json][timeout:25]; ( node["amenity"="atm"](17.35,78.44,17.42,78.52); nwr["amenity"="bank"](17.35,78.44,17.42,78.52); ); out center;
All schools in a district
[out:json][timeout:120]; area["boundary"="administrative"]["name"="West Godavari"]["admin_level"="5"]->.d; nwr["amenity"="school"](area.d); out center tags;
Road network with geometry
[out:json][timeout:90]; way["highway"~"motorway|trunk|primary|secondary"](16.35,81.60,16.50,81.80); out geom;
Building footprints near a point
[out:json][timeout:60]; way["building"](around:500,16.4337,81.6966); out geom;
Count restaurants in a city
[out:json][timeout:60]; nwr["amenity"="restaurant"](17.30,78.35,17.50,78.60); out count;
Places with a Telugu name (CSV export)
[out:csv(::id, name, "name:te", ::lat, ::lon; true; ",")][timeout:60]; node["place"~"town|village"]["name:te"](16.2,81.4,16.7,82.0); out;
Petrol pumps open 24 hours
[out:json][timeout:60]; nwr["amenity"="fuel"]["opening_hours"="24/7"](17.20,78.20,17.60,78.70); out center tags;
State boundary outline
[out:json][timeout:180]; relation["boundary"="administrative"]["admin_level"="4"]["name"="Andhra Pradesh"]; out geom;
Bus stops along a route (relation members)
[out:json][timeout:60]; relation["route"="bus"](17.30,78.40,17.45,78.55); node(r)["highway"="bus_stop"]; out;
Name search (case-insensitive)
[out:json][timeout:60]; nwr["name"~"swarnandhra",i]; out center tags;
Client code
curl (query in a file)
# save your query to query.overpassql, then: curl -X POST https://api.geoflux.swarnandhra.ac.in/api/interpreter \ -H "X-API-Key: $GEOFLUX_KEY" \ --data-urlencode data@query.overpassql \ -o result.json
Python (requests)
import os
import requests
GEOFLUX = "https://api.geoflux.swarnandhra.ac.in/api/interpreter"
KEY = os.environ["GEOFLUX_KEY"]
def overpass(query: str) -> dict:
r = requests.post(GEOFLUX, headers={"X-API-Key": KEY}, data={"data": query}, timeout=300)
if r.status_code == 429:
raise RuntimeError(f"Limit reached, retry after {r.headers.get('Retry-After')} s")
r.raise_for_status()
return r.json()
data = overpass("""
[out:json][timeout:60];
nwr["amenity"="hospital"](around:5000,16.4337,81.6966);
out center tags;
""")
for el in data["elements"]:
lat = el.get("lat") or el["center"]["lat"]
lon = el.get("lon") or el["center"]["lon"]
print(el["tags"].get("name", "(unnamed)"), lat, lon)
Python (pandas, from CSV output)
import io, os, requests, pandas as pd
q = '[out:csv(name, ::lat, ::lon; true; ",")][timeout:60];node["amenity"="school"](16.3,81.5,16.6,81.9);out;'
r = requests.post("https://api.geoflux.swarnandhra.ac.in/api/interpreter",
headers={"X-API-Key": os.environ["GEOFLUX_KEY"]}, data={"data": q})
df = pd.read_csv(io.StringIO(r.text))
print(df.head())
JavaScript (Node.js 18+ or server-side)
const res = await fetch("https://api.geoflux.swarnandhra.ac.in/api/interpreter", {
method: "POST",
headers: { "X-API-Key": process.env.GEOFLUX_KEY },
body: new URLSearchParams({
data: '[out:json][timeout:25];node["amenity"="pharmacy"](around:2000,17.385,78.4867);out;',
}),
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { elements } = await res.json();
Web apps: CORS is enabled, but a key used in browser JavaScript is visible to anyone who opens your page. For public websites, call GeoFlux from your own backend and keep the key on the server.
R (httr2)
library(httr2)
resp <- request("https://api.geoflux.swarnandhra.ac.in/api/interpreter") |>
req_headers(`X-API-Key` = Sys.getenv("GEOFLUX_KEY")) |>
req_body_form(data = '[out:json];node["amenity"="college"](16.3,81.5,16.6,81.9);out;') |>
req_perform()
elements <- resp_body_json(resp)$elements
Postman / Insomnia
Method POST, URL https://api.geoflux.swarnandhra.ac.in/api/interpreter, header X-API-Key, body type x-www-form-urlencoded with one field data containing your query.
GeoJSON & GIS
Overpass JSON is not GeoJSON, but converting is easy:
# Node.js npm install -g osmtogeojson curl -s -X POST https://api.geoflux.swarnandhra.ac.in/api/interpreter -H "X-API-Key: $GEOFLUX_KEY" \ --data-urlencode 'data=[out:json];way["leisure"="park"](17.35,78.44,17.42,78.52);out geom;' \ | osmtogeojson > parks.geojson
# Python pip install osm2geojson import osm2geojson geojson = osm2geojson.json2geojson(data) # data = Overpass JSON from the example above
The resulting .geojson files open directly in QGIS, ArcGIS, Leaflet, Mapbox, kepler.gl and geopandas (geopandas.read_file("parks.geojson")).
Tools that cannot send custom headers (some GIS plugins) can use the URL form https://api.geoflux.swarnandhra.ac.in/api/interpreter?key=YOUR_KEY, but only on trusted machines.
Errors
Gateway errors are JSON: {"error": {"code": "…", "message": "…"}}. Errors in the query itself come from Overpass, usually as HTTP 400 with an HTML/text explanation of the syntax problem.
| HTTP | Code | What to do |
|---|---|---|
| 400 | missing_query | Send the query as the data parameter or the POST body. |
| 400 | timeout_too_high | Lower [timeout:N] to your key's maximum (see /api/me). |
| 400 | (from Overpass) | Syntax error in your query. Read the message for the line number. |
| 401 | missing_key | Add the X-API-Key header. |
| 401 | invalid_key | Check for typos or extra spaces. The key may have been rotated or deleted. |
| 403 | key_expired | Your validity period has ended. Ask the administrator for an extension. |
| 403 | key_not_yet_valid | The key's start date is in the future. |
| 403 | key_revoked | The key was disabled by the administrator. |
| 403 | ip_not_allowed | The key is limited to certain IP addresses. |
| 403 | https_required | Use https://. |
| 413 | bad_request | Query larger than 1 MB. |
| 429 | rate_limited | Too many requests this minute. Wait Retry-After seconds. |
| 429 | quota_exceeded | Daily quota used up. Resets at 00:00 UTC. |
| 429 | too_many_concurrent | Wait for your running queries to finish. |
| 502 | upstream_unavailable | The Overpass backend is restarting or busy. Retry in a minute. |
| 504 | upstream_timeout | Query took too long. Use a smaller area, a lower out detail, or split it. |
Good practice
- Start small. Test on a small bounding box, then expand.
- Always set
[timeout:N]to what your query really needs. - Prefer
aroundor a bounding box over named areas for speed. - Request only what you need:
out centerorout tagsinstead ofout geomwhen you only need locations. - Cache results in your application; OSM data in GeoFlux changes only when the snapshot is updated.
- Back off on 429/502/504: wait for
Retry-Afterand retry with exponential delay, never in a tight loop. - Split large jobs (e.g. a whole state) into tiles or districts.
Licence & attribution
Data returned by GeoFlux comes from OpenStreetMap and is licensed under the Open Database License (ODbL) 1.0. You may use it for any purpose, including commercial, provided that you:
- Attribute: show "© OpenStreetMap contributors" wherever you display the data (maps, reports, apps, papers), with a link to openstreetmap.org/copyright.
- Share-alike: if you publish a modified database derived from the data, release it under the ODbL too.
Access to GeoFlux itself is governed by your institution's acceptable-use rules: keys are personal, must be used for the stated purpose, and may be revoked for misuse.
FAQ
Can I use overpass-turbo.eu with GeoFlux?
overpass turbo cannot send API keys, so it cannot query GeoFlux directly. Use it to design and test queries against the public server on a small area, then run the final query through GeoFlux.
Why do I get an empty elements array?
Either nothing matches (check tag spelling: keys and values are case-sensitive), the area is outside India, or your bounding box coordinates are in the wrong order. The order is south, west, north, east.
Ways have no coordinates in my result
Use out geom; for full geometry or out center; for a single point per way.
How often is the data updated?
See osm3s.timestamp_osm_base in any response. The administrator refreshes the snapshot periodically.
Can I edit or add data?
No. GeoFlux is read-only. To improve the map, edit OpenStreetMap at openstreetmap.org; changes reach GeoFlux at the next data refresh.
My key expired. Is my data lost?
Keys hold no data. Ask the administrator to extend the validity; the same key keeps working once it is extended.
Need help or a bigger quota? Contact the GeoFlux administrator.
by Swarnandhra