# geopy: a Python client for geocoding services and geodesic distance

> geopy wraps several third-party geocoders behind one Python interface and ships geodesic and great-circle distance helpers. It is a client library, not a geocoder: every lookup depends on a service you configure and its terms.

**geopy/geopy** — Geocoding library for Python.

- Repository: https://github.com/geopy/geopy
- Website: https://geopy.readthedocs.io/
- Stars: 4,867 · Forks: 669
- Language: Python
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/geopy-geopy

## What geopy solves, and who it is actually for

Turning an address into coordinates, or coordinates into an address, means talking to a geocoding web service. Each service has its own request format, its own response schema and its own error behaviour. geopy puts a common wrapper around them. The README describes it as "a Python client for several popular geocoding web services", with geocoder classes for OpenStreetMap Nominatim, the Google Geocoding API (V3) and others listed in the Geocoders doc section.

The audience is Python developers who already know which provider they want to call and do not want to hand-roll HTTP and JSON parsing per provider. It is also for people who need one number: the distance between two points on the globe. That part does not touch the network at all. The distance module computes geodesic distance on an ellipsoid or great-circle distance on a sphere, and the README notes that the geodesic form is the default behind geopy.distance.distance.

What geopy is not: a geocoder. It ships no address database. Every geocode or reverse call is a request to a third party, subject to that party's quota, key requirements and attribution rules. Teams that read "geocoding library" as "offline lookup" will be disappointed on the first run.

## How a geocode call flows through the geocoder classes

The architecture is a thin client layer. You instantiate a geocoder class from geopy.geocoders, pass configuration such as a user agent or an API key, and call geocode() or reverse(). The class builds the provider-specific HTTP request, parses the response, and returns a Location object.

That Location object is where the design pays off. It exposes .address, .latitude, .longitude and .raw. The README's Nominatim example returns an address string starting with "Flatiron Building, 175, 5th Avenue", a (latitude, longitude) tuple, and a raw dictionary containing keys such as 'place_id' and 'type'. Because .raw is the untouched provider payload, you can read fields geopy does not normalise without dropping to requests yourself.

The distance side is separate and purely computational. You construct a distance with two (lat, lon) tuples and read a unit attribute. The README shows geodesic(newport_ri, cleveland_oh).miles returning 538.390445368, and the great-circle version returning 536.997990696 for the same pair. The gap between those two numbers is the point: the ellipsoid model and the sphere model disagree, and geopy lets you choose which one your application reports.

## Install geopy and run a first reverse geocode

The README gives one installation route: pip. The project also publishes wheels and source archives on PyPI, which is the fallback when pip is not available in your environment.

```bash
pip install geopy
```

After installation, the smallest useful program is a reverse lookup, because it needs no free-text address parsing. The README uses a user agent string that you are expected to replace with your own application name.

```python
from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="specify_your_app_name_here")
location = geolocator.reverse("52.509669, 13.376294")
print(location.address)
print((location.latitude, location.longitude))
```

The README states that this prints an address beginning "Potsdamer Platz, Mitte, Berlin, 10117, Deutschland, European Union" and a coordinate pair close to the input. If you instead want to go from text to coordinates, swap in geolocator.geocode("175 5th Avenue NYC") and read location.raw for the provider's full payload.

For distance work, no geocoder instance is needed and no request leaves the process.

```python
from geopy.distance import geodesic

newport_ri = (41.49008, -71.312796)
cleveland_oh = (41.499498, -81.695391)
print(geodesic(newport_ri, cleveland_oh).miles)
```

The README gives 538.390445368 as the value for that pair. If you need the spherical model instead, import great_circle from the same module.

## The Nominatim user agent is not optional in practice

The README's examples all pass user_agent="specify_your_app_name_here". That placeholder is a signal, not decoration. Nominatim is a shared public service, and identifying your application is how its operators attribute traffic. Sending a generic or default agent is the most common way a geopy-based script gets blocked, and the failure appears as an HTTP error from the provider rather than anything geopy raises on its own.

The same caution applies across providers. geopy is a client, so quota, key handling and usage policy live with the service, not the library. The README does not document retry behaviour, backoff or caching. If your workload is a few thousand addresses, you are responsible for pacing the calls and for storing results so you do not repeat them. A geocode you have already paid for in latency is worth caching in your own database.

There is a second boundary worth stating plainly: the project's own test suite acknowledges the cost of network calls. The Makefile defines test-local, which runs pytest with --skip-tests-requiring-internet and comments that these tests are fast and avoid spending geocoder quota on runs that would fail anyway. That is a reasonable posture for a client library, and it also tells you the maintainers do not promise a hermetic test story for the network paths.

## geopy versus calling a provider's HTTP API directly

The honest alternative is not another Python package. It is requests plus your own parsing, or a provider SDK such as the one Google publishes for its own APIs.

The difference is where the provider-specific code lives. With geopy, switching from Nominatim to the Google Geocoding API (V3) means changing the class you import and the credentials you pass, while your code keeps reading location.address and location.latitude. With direct HTTP calls, that switch means rewriting the request builder and the response parser, and every provider's error shape leaks into your application.

The trade runs the other way too. A direct call gives you the provider's full request surface immediately, including parameters geopy may not expose or may expose under a different name. The README points to the Geocoders doc section for the full list of supported services, which is the right place to check whether the provider you need is covered before you commit. If your chosen provider is not in geopy.geocoders, geopy adds a dependency without removing any work.

## Maintenance, release cadence and the MIT licence

The repository is not archived, and the last push was on 2026-07-12. The most recent release, 2.5.0, is dated 2026-07-12 as well. The two releases before it, 2.4.1 and 2.4.0, are dated 2023-11-23 and 2023-08-27. That gap is the practical fact to plan around: the 2.4 line sat for roughly two and a half years before 2.5.0 arrived.

For adopters this means two things. First, pin the version in your requirements and read the release notes when you move, because a multi-year gap can carry behavioural changes that a minor version number does not advertise. Second, do not expect the library to chase every provider's API changes on a short cycle. When a provider changes its response format, the fix arrives on the project's schedule, not yours.

The licence is MIT, and the README states the copyright as "geopy contributors 2006-2026 (see AUTHORS) under the MIT License". MIT is permissive and imposes no copyleft on your application. It does not, however, cover the geocoding services themselves. Nominatim, the Google Geocoding API and the rest each carry their own terms, and those terms, not geopy's licence, govern what you may store and redistribute. Review them separately; this is not legal advice.

The project tests against CPython 3.8 through 3.15 and PyPy3, which the README notes explicitly. The 1.x line supported Python 2.7 and 3.4, so if you are maintaining a Python 2 codebase, the current release is not for you.

## Conclusion

Adopt geopy when you want one Python interface over Nominatim, the Google Geocoding API (V3) and the other services in geopy.geocoders, and when you accept that each lookup is a network call governed by that provider's usage policy. Do not adopt it if you need an offline gazetteer or a self-hosted geocoder with no third-party dependency. Before writing code, confirm the provider's rate limits and attribution requirements, and pin the version: 2.5.0 was released on 2026-07-12, while 2.4.1 dates from 2023-11-23.

## FAQ

### Is geopy free?

The library itself is MIT licensed and the README states the copyright as geopy contributors 2006-2026 under the MIT License. The geocoding services it calls are separate and may require an API key or impose usage limits.

### What is the geopy module in Python?

It is a Python client for several popular geocoding web services, with geocoder classes for OpenStreetMap Nominatim, the Google Geocoding API (V3) and others. It also includes distance helpers for geodesic and great-circle calculations.

### How does geopy calculate the distance between two points?

The distance module computes either geodesic distance on an ellipsoid or great-circle distance on a sphere, taking pairs of (lat, lon) tuples. The README notes the geodesic form is the default behind geopy.distance.distance, and shows the two models returning different mile values for the same pair of points.

### How do I install geopy?

The README gives pip install geopy as the installation command, and notes that you can alternatively download a wheel or source archive from PyPI. Installation does not configure any geocoder; you supply a user agent or API key when you instantiate a geocoder class.

### What does the "modulenotfounderror no module named 'geopy'" error mean?

It means the geopy package is not importable in the Python environment running your code, so the install step was skipped or applied to a different interpreter. The README's installation section gives pip install geopy as the fix.

### What is geopy used for?

Two things: locating the coordinates of addresses, cities, countries and landmarks through third-party geocoders, and measuring the distance between two points. The README describes both the geocoding classes in geopy.geocoders and the geodesic and great-circle distance functions.

## Sources

- [geopy/geopy on GitHub](https://github.com/geopy/geopy)
- [License: MIT](https://github.com/geopy/geopy/blob/master/LICENSE)
- [Project website](https://geopy.readthedocs.io/)
- [README](https://github.com/geopy/geopy/blob/master/README.md)
- [Releases](https://github.com/geopy/geopy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/geopy-geopy
