Find Places by Name
Turns what somebody typed — zala, Bacău, Fântâni, Dolj, Romania — into the places it could be, each with its region, its country and its coordinates. It is the search box behind a map: a person names a place instead of dragging the world to it. Opensolr Photos uses it to move a photo to the right place, and it works the same for any application with an address field, a map or a location filter.
Endpoint
GET https://opensolr.com/solr_manager/api/place_search
opensolr.com. It is part of the management API, not the AI API, so do not call it on api.opensolr.com — that host answers 404 with WRONG_API_HOST and tells you the correct URL. POST works exactly like GET; a JSON request body is accepted too, with the same field names.Parameters
| Parameter | Type | Status | Description |
|---|---|---|---|
email | string | Required | Your Opensolr registration email address |
api_key | string | Required | Your Opensolr API key (master key, or a scoped key that grants place_search) |
q | string | Required | The name, or the beginning of a name, of a place. Up to 80 characters |
country | string | Optional | Two-letter country code (RO, US), to search inside one country only |
limit | integer | Optional | How many places to return, 1 to 25. Ten by default |
How It Works
The text is matched against a world-wide gazetteer of populated places and administrative divisions — cities, towns, villages, counties, countries. Names match as they are typed: zala already finds Zalău, because the name fields are indexed as prefixes, and diacritics are optional in either direction. Every language a place is known by is searched too, so Bucharest, București and Bukarest all reach the same city.
The biggest place comes first. Results are ranked by population on a logarithmic scale, so a city of a million outranks a hamlet of the same name without burying it: what a person means is almost always the larger place, and the smaller ones are still on the list.
Commas are separators, not letters. Fântâni, Dolj, Romania searches exactly like Fântâni Dolj Romania, so the label you show a person is itself a query you can send back.
What it does not do
This endpoint knows places, not addresses: no streets, no house numbers, no points of interest. A street address is a different question, and it is answered from the other side: give nearby_places the coordinates you already have and it names the place around them.
Absent facts are absent
On a place entry only place, country_code, lat, lon and kind are guaranteed. region, province, country and population are omitted when the gazetteer does not know them — never an empty string. Test with isset().
kind reduces the gazetteer's feature codes to the three a person picking a place thinks in: city for a place to stand in, region for an administrative division inside a country, country for a country. It is what to use when deciding how far to zoom a map.
Versioned contract
The response shape is Opensolr's, not the gazetteer's, and it carries contract_version. The provider behind the endpoint can be replaced without breaking your integration.
Limits
| Limit | Value | What happens |
|---|---|---|
| Query length | 80 characters | Longer text is cut to 80 |
| Places per call | 1 to 25 | Anything outside is clamped, default 10 |
| Answers held | 24 hours | A name answered once is served from Opensolr for a day; the gazetteer itself is rebuilt monthly |
| Rate limit cost | 1 per request | Counted once against the per-minute, per-hour and monthly API request limits. This endpoint does not draw on the AI allowance |
Response
| Field | Type | Description |
|---|---|---|
status | boolean | true when places were found |
contract_version | integer | The version of this response shape |
q | string | The text as it was searched for |
country_code | string | The country filter that was applied, or null |
count | integer | How many entries are in places |
places | array | The places, best match first |
places[].place | string | The name of the place |
places[].region | string | County or state, when known |
places[].province | string | The division below the region, when known |
places[].country | string | Country name, when known |
places[].country_code | string | ISO-3166-1 alpha-2 country code |
places[].lat / places[].lon | float | Decimal degrees, five decimals |
places[].kind | string | city, region or country |
places[].population | integer | Inhabitants, when the gazetteer knows a figure |
Errors
| HTTP | Message | Meaning |
|---|---|---|
400 | ERROR_NO_QUERY_SUPPLIED | No usable text was sent in q |
404 | ERROR_GEO_NO_DATA | No place is known by that name. An answer, not a failure — but do not keep it: the name may be findable tomorrow |
503 | ERROR_GEO_LOOKUP_UNAVAILABLE | The place database could not be asked. Retry later; nothing from a non-200 answer is cacheable |
403 | ERROR_AUTHENTICATION_FAILED | Email and API key do not match an account |
Code Examples
cURL
curl -s "https://opensolr.com/solr_manager/api/place_search" \ --data-urlencode "email=you@example.com" \ --data-urlencode "api_key=YOUR_API_KEY" \ --data-urlencode "q=zala" \ --data-urlencode "limit=5"
PHP
$params = array( 'email' => 'you@example.com', 'api_key' => 'YOUR_API_KEY', 'q' => 'fantani, dolj, romania', 'limit' => 10, ); $url = 'https://opensolr.com/solr_manager/api/place_search?' . http_build_query($params); $answer = json_decode(file_get_contents($url), true); foreach ($answer['places'] as $place) { $label = $place['place'] . (isset($place['region']) ? ', ' . $place['region'] : '') . (isset($place['country']) ? ', ' . $place['country'] : ''); echo $label . ' -> ' . $place['lat'] . ',' . $place['lon'] . PHP_EOL; }
Python
import requests answer = requests.get( "https://opensolr.com/solr_manager/api/place_search", params={ "email": "you@example.com", "api_key": "YOUR_API_KEY", "q": "springfield illinois", "limit": 5, }, timeout=10, ).json() for place in answer.get("places", []): print(place["place"], place.get("region"), place["lat"], place["lon"], place["kind"])
Example Response
{ "status": true, "contract_version": 1, "q": "zala", "country_code": null, "count": 3, "places": [ { "place": "Zala megye", "region": "Zala County", "country": "Hungary", "country_code": "HU", "lat": 46.66667, "lon": 16.83333, "kind": "region", "population": 270634 }, { "place": "Zalaegerszeg", "region": "Zala County", "country": "Hungary", "country_code": "HU", "lat": 46.83695, "lon": 16.84401, "kind": "city", "population": 61898 }, { "place": "Zal\u0103u", "region": "S\u0103laj County", "province": "Municipiul Zal\u0103u", "country": "Romania", "country_code": "RO", "lat": 47.2, "lon": 23.05, "kind": "city", "population": 52359 } ] }
And when nothing is known by that name:
{ "status": false, "msg": "ERROR_GEO_NO_DATA", "q": "zzzqqq" }
Use Cases
- Put a search box on a map so a person can name the town instead of dragging the world to it — tap a result, fly the map to
lat,lon, zoom bykind - Autocomplete a location field in a form, with the region and the country shown next to the name so two towns that share a name can be told apart
- Turn a place a person typed into coordinates you can store, index and search on — the same coordinates nearby_places reads back as words
- Offer a country, region or city filter built from real names rather than a hand-kept list
- Pair it with geo_lookup and nearby_places: an IP in, coordinates out; coordinates in, a name out; a name in, coordinates out — the three directions of the same question
Related Documentation
Need help with the Opensolr API? We are here to help.
Contact Support