City Search
GET/api/locationsPro
Search cities by name. Returns matching cities with timezone, coordinates, and population — use this to build city autocomplete in your own frontend or chatbot.
No calculation units consumed
This endpoint only searches the city database — it does not run Swiss Ephemeris or consume a calculation unit from your quota.
Why use this?
All chart endpoints require a valid birthLocation. If you're building your own UI, you need a way to let users pick a real city. This endpoint gives you that — it's the same offline city database the THD frontend uses, with 167,000+ cities across 246 countries.
Typical flow:
- User types into a city input field
- You call
/api/locations?query=<input>on each keystroke (debounced) - Display the returned list as a dropdown
- On selection, pass the chosen
valueasbirthLocationin your chart request
Request
Method: GET
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | — | Partial city name, min 3 characters |
limit | number | No | 8 | Max results returned (max 20) |
Response
Returns a JSON array sorted by population descending (most prominent city wins ties).
Response200
[
{
"name": "Manila",
"province": "National Capital Region",
"country": "Philippines",
"timezone": "Asia/Manila",
"coordinates": { "lat": 14.6042, "lng": 120.9822 },
"population": 1600000,
"value": "Manila, National Capital Region, Philippines"
},
{
"name": "Manila",
"province": "Arkansas",
"country": "United States",
"timezone": "America/Chicago",
"coordinates": { "lat": 35.8801, "lng": -90.167 },
"population": 3736,
"value": "Manila, Arkansas, United States"
}
]| Field | Description |
|---|---|
name | City name |
province | State or province (null if not applicable) |
country | Full country name |
timezone | IANA timezone identifier |
coordinates | { lat, lng } — pass these as latitude/longitude in chart requests to bypass city lookup |
population | Population used for ranking (higher = ranked first) |
value | Display string for your UI — safe to use as birthLocation in chart calls |
Error — query too short:
{ "success": false, "error": "query param is required and must be at least 3 characters." }
Dataset
- Source: GeoNames
cities1000(CC-BY 4.0) - Coverage: 167,617 cities, population ≥ 1,000, 246 countries
- US cities: 17,321 — covers towns down to ~1,000 population
- Search: prefix-first then contains, diacritics-insensitive (
"Zurich"matches"Zürich") - Tiebreaker: population descending —
"London"returns UK (8.9M) before Canada (422K) - Comma hint:
"London, Canada"filters by province/country
Population floor
Towns with fewer than 1,000 residents are not in the dataset. For very remote birthplaces, collect coordinates directly from the user and pass latitude + longitude to the chart endpoint — this bypasses the city lookup entirely.
Integration example
// Debounced autocomplete
let debounce;
cityInput.addEventListener('input', (e) => {
clearTimeout(debounce);
if (e.target.value.length < 3) return;
debounce = setTimeout(async () => {
const res = await fetch(
`/api/locations?query=${encodeURIComponent(e.target.value)}&limit=8`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const cities = await res.json();
// Render dropdown
dropdown.innerHTML = cities.map(city =>
`<option value="${city.value}" data-lat="${city.coordinates.lat}" data-lng="${city.coordinates.lng}">
${city.value}
</option>`
).join('');
}, 250);
});
