API - Find Places by Name (place_search)

Geolocation
Geolocation API

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
This one lives on 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

ParameterTypeStatusDescription
emailstringRequiredYour Opensolr registration email address
api_keystringRequiredYour Opensolr API key (master key, or a scoped key that grants place_search)
qstringRequiredThe name, or the beginning of a name, of a place. Up to 80 characters
countrystringOptionalTwo-letter country code (RO, US), to search inside one country only
limitintegerOptionalHow 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

LimitValueWhat happens
Query length80 charactersLonger text is cut to 80
Places per call1 to 25Anything outside is clamped, default 10
Answers held24 hoursA name answered once is served from Opensolr for a day; the gazetteer itself is rebuilt monthly
Rate limit cost1 per requestCounted once against the per-minute, per-hour and monthly API request limits. This endpoint does not draw on the AI allowance
Typing is not searching. Wait until the typing stops before you call — about a third of a second — and ask only from the second character. One request per pause instead of one per letter keeps a search box inside a small rate limit, and holding the answers on your own side keeps it there for good.

Response

FieldTypeDescription
statusbooleantrue when places were found
contract_versionintegerThe version of this response shape
qstringThe text as it was searched for
country_codestringThe country filter that was applied, or null
countintegerHow many entries are in places
placesarrayThe places, best match first
places[].placestringThe name of the place
places[].regionstringCounty or state, when known
places[].provincestringThe division below the region, when known
places[].countrystringCountry name, when known
places[].country_codestringISO-3166-1 alpha-2 country code
places[].lat / places[].lonfloatDecimal degrees, five decimals
places[].kindstringcity, region or country
places[].populationintegerInhabitants, when the gazetteer knows a figure

Errors

HTTPMessageMeaning
400ERROR_NO_QUERY_SUPPLIEDNo usable text was sent in q
404ERROR_GEO_NO_DATANo place is known by that name. An answer, not a failure — but do not keep it: the name may be findable tomorrow
503ERROR_GEO_LOOKUP_UNAVAILABLEThe place database could not be asked. Retry later; nothing from a non-200 answer is cacheable
403ERROR_AUTHENTICATION_FAILEDEmail 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 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;
}

Py 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 by kind
  • 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