Geocoding#
GeoPandas supports geocoding (i.e., converting place names to location on Earth) through geopy, an optional dependency of GeoPandas. The following example shows how to get the locations of boroughs in New York City, and plots those locations along with the detailed borough boundary file included within GeoPandas.
In [1]: import geodatasets
In [2]: boros = geopandas.read_file(geodatasets.get_path("nybb"))
In [3]: boros.BoroName
Out[3]:
0 Staten Island
1 Queens
2 Brooklyn
3 Manhattan
4 Bronx
Name: BoroName, dtype: str
In [4]: boro_locations = geopandas.geocode(boros.BoroName)
---------------------------------------------------------------------------
TimeoutError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:540, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
539 try:
--> 540 response = conn.getresponse()
541 except (BaseSSLError, OSError) as e:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connection.py:638, in HTTPConnection.getresponse(self)
637 # Get the response from http.client.HTTPConnection
--> 638 httplib_response = super().getresponse()
640 try:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/http/client.py:1478, in HTTPConnection.getresponse(self)
1477 try:
-> 1478 response.begin()
1479 except ConnectionError:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/http/client.py:343, in HTTPResponse.begin(self)
342 for _ in range(_MAXINTERIMRESPONSES):
--> 343 version, status, reason = self._read_status()
344 if status != CONTINUE:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/http/client.py:304, in HTTPResponse._read_status(self)
303 def _read_status(self):
--> 304 line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
305 if len(line) > _MAXLINE:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/socket.py:723, in SocketIO.readinto(self, b)
722 try:
--> 723 return self._sock.recv_into(b)
724 except timeout:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/ssl.py:1304, in SSLSocket.recv_into(self, buffer, nbytes, flags)
1301 raise ValueError(
1302 "non-zero flags not allowed in calls to recv_into() on %s" %
1303 self.__class__)
-> 1304 return self.read(nbytes, buffer)
1305 else:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/ssl.py:1138, in SSLSocket.read(self, len, buffer)
1137 if buffer is not None:
-> 1138 return self._sslobj.read(len, buffer)
1139 else:
TimeoutError: The read operation timed out
The above exception was the direct cause of the following exception:
ReadTimeoutError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:793, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
792 # Make the request on the HTTPConnection object
--> 793 response = self._make_request(
794 conn,
795 method,
796 url,
797 timeout=timeout_obj,
798 body=body,
799 headers=headers,
800 chunked=chunked,
801 retries=retries,
802 response_conn=response_conn,
803 preload_content=preload_content,
804 decode_content=decode_content,
805 **response_kw,
806 )
808 # Everything went great!
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:542, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
541 except (BaseSSLError, OSError) as e:
--> 542 self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
543 raise
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:373, in HTTPConnectionPool._raise_timeout(self, err, url, timeout_value)
372 if isinstance(err, SocketTimeout):
--> 373 raise ReadTimeoutError(
374 self, url, f"Read timed out. (read timeout={timeout_value})"
375 ) from err
377 # See the above comment about EAGAIN in Python 3.
ReadTimeoutError: HTTPSConnectionPool(host='photon.komoot.io', port=443): Read timed out. (read timeout=1)
The above exception was the direct cause of the following exception:
MaxRetryError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/requests/adapters.py:696, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
695 try:
--> 696 resp = conn.urlopen(
697 method=request.method,
698 url=url,
699 body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str]
700 headers=request.headers, # type: ignore[arg-type] # urllib3#3072
701 redirect=False,
702 assert_same_host=False,
703 preload_content=False,
704 decode_content=False,
705 retries=self.max_retries,
706 timeout=resolved_timeout,
707 chunked=chunked,
708 )
710 except (ProtocolError, OSError) as err:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:886, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
874 log.warning(
875 "Retrying (%r) after connection broken by '%r': %s",
876 retries,
(...) 884 extra={"__urllib3-retry-warning": {"host": self.host}},
885 )
--> 886 return self.urlopen(
887 method,
888 url,
889 body,
890 headers,
891 retries,
892 redirect,
893 assert_same_host,
894 timeout=timeout,
895 pool_timeout=pool_timeout,
896 release_conn=release_conn,
897 chunked=chunked,
898 body_pos=body_pos,
899 preload_content=preload_content,
900 decode_content=decode_content,
901 **response_kw,
902 )
904 # Handle redirect?
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:886, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
874 log.warning(
875 "Retrying (%r) after connection broken by '%r': %s",
876 retries,
(...) 884 extra={"__urllib3-retry-warning": {"host": self.host}},
885 )
--> 886 return self.urlopen(
887 method,
888 url,
889 body,
890 headers,
891 retries,
892 redirect,
893 assert_same_host,
894 timeout=timeout,
895 pool_timeout=pool_timeout,
896 release_conn=release_conn,
897 chunked=chunked,
898 body_pos=body_pos,
899 preload_content=preload_content,
900 decode_content=decode_content,
901 **response_kw,
902 )
904 # Handle redirect?
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/connectionpool.py:847, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
845 new_e = ProtocolError("Connection aborted.", new_e)
--> 847 retries = retries.increment(
848 method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
849 )
850 retries.sleep()
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/urllib3/util/retry.py:555, in Retry.increment(self, method, url, response, error, _pool, _stacktrace)
554 reason = error or ResponseError(cause)
--> 555 raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
557 log.debug("Incremented Retry for (url='%s'): %r", url, new_retry)
MaxRetryError: HTTPSConnectionPool(host='photon.komoot.io', port=443): Max retries exceeded with url: /api?q=Staten+Island&limit=1 (Caused by ReadTimeoutError("HTTPSConnectionPool(host='photon.komoot.io', port=443): Read timed out. (read timeout=1)"))
During handling of the above exception, another exception occurred:
ConnectionError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/geopy/adapters.py:482, in RequestsAdapter._request(self, url, timeout, headers)
481 try:
--> 482 resp = self.session.get(url, timeout=timeout, headers=headers)
483 except Exception as error:
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/requests/sessions.py:671, in Session.get(self, url, params, **kwargs)
670 kwargs.setdefault("allow_redirects", True)
--> 671 return self.request("GET", url, params=params, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/requests/sessions.py:651, in Session.request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
650 send_kwargs.update(settings)
--> 651 resp = self.send(prep, **send_kwargs)
653 return resp
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/requests/sessions.py:784, in Session.send(self, request, **kwargs)
783 # Send the request
--> 784 r = adapter.send(request, **kwargs)
786 # Total elapsed time of the request (approximately)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/requests/adapters.py:729, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
727 raise SSLError(e, request=request)
--> 729 raise ConnectionError(e, request=request)
731 except ClosedPoolError as e:
ConnectionError: HTTPSConnectionPool(host='photon.komoot.io', port=443): Max retries exceeded with url: /api?q=Staten+Island&limit=1 (Caused by ReadTimeoutError("HTTPSConnectionPool(host='photon.komoot.io', port=443): Read timed out. (read timeout=1)"))
During handling of the above exception, another exception occurred:
GeocoderUnavailable Traceback (most recent call last)
Cell In[4], line 1
----> 1 boro_locations = geopandas.geocode(boros.BoroName)
File ~/checkouts/readthedocs.org/user_builds/geopandas/checkouts/stable/geopandas/tools/geocoding.py:66, in geocode(strings, provider, **kwargs)
63 provider = "photon"
64 throttle_time = _get_throttle_time(provider)
---> 66 return _query(strings, True, provider, throttle_time, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/geopandas/checkouts/stable/geopandas/tools/geocoding.py:139, in _query(data, forward, provider, throttle_time, **kwargs)
137 try:
138 if forward:
--> 139 results[i] = coder.geocode(s)
140 else:
141 results[i] = coder.reverse((s.y, s.x), exactly_one=True)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/geopy/geocoders/photon.py:166, in Photon.geocode(self, query, exactly_one, timeout, location_bias, language, limit, osm_tag, bbox)
164 logger.debug("%s.geocode: %s", self.__class__.__name__, url)
165 callback = partial(self._parse_json, exactly_one=exactly_one)
--> 166 return self._call_geocoder(url, callback, timeout=timeout)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/geopy/geocoders/base.py:367, in Geocoder._call_geocoder(self, url, callback, timeout, is_json, headers)
365 try:
366 if is_json:
--> 367 result = self.adapter.get_json(url, timeout=timeout, headers=req_headers)
368 else:
369 result = self.adapter.get_text(url, timeout=timeout, headers=req_headers)
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/geopy/adapters.py:472, in RequestsAdapter.get_json(self, url, timeout, headers)
471 def get_json(self, url, *, timeout, headers):
--> 472 resp = self._request(url, timeout=timeout, headers=headers)
473 try:
474 return resp.json()
File ~/checkouts/readthedocs.org/user_builds/geopandas/conda/stable/lib/python3.13/site-packages/geopy/adapters.py:494, in RequestsAdapter._request(self, url, timeout, headers)
492 raise GeocoderServiceError(message)
493 else:
--> 494 raise GeocoderUnavailable(message)
495 elif isinstance(error, requests.Timeout):
496 raise GeocoderTimedOut("Service timed out")
GeocoderUnavailable: HTTPSConnectionPool(host='photon.komoot.io', port=443): Max retries exceeded with url: /api?q=Staten+Island&limit=1 (Caused by ReadTimeoutError("HTTPSConnectionPool(host='photon.komoot.io', port=443): Read timed out. (read timeout=1)"))
In [5]: boro_locations
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[5], line 1
----> 1 boro_locations
NameError: name 'boro_locations' is not defined
In [6]: import matplotlib.pyplot as plt
In [7]: fig, ax = plt.subplots()
In [8]: boros.to_crs("EPSG:4326").plot(ax=ax, color="white", edgecolor="black");
In [9]: boro_locations.plot(ax=ax, color="red");
By default, the geocode() function uses the
Photon geocoding API.
But a different geocoding service can be specified with the
provider keyword.
The argument to provider can either be a string referencing geocoding
services, such as 'google', 'bing', 'yahoo', and
'openmapquest', or an instance of a Geocoder from geopy. See
geopy.geocoders.SERVICE_TO_GEOCODER for the full list.
For many providers, parameters such as API keys need to be passed as
**kwargs in the geocode() call.
For example, to use the OpenStreetMap Nominatim geocoder, you need to specify a user agent:
geopandas.geocode(boros.BoroName, provider='nominatim', user_agent="my-application")
Attention
Please consult the Terms of Service for the chosen provider. The example
above uses 'photon' (the default), which expects fair usage
- extensive usage will be throttled.
(Photon’s Terms of Use).