This release is a pre-release and may not be stable for production use.
osm2geojson
Convert OpenStreetMap and Overpass API data (JSON or XML) to GeoJSON or Shapely geometries.
Output closely matches osmtogeojson (the JavaScript converter used by overpass-turbo), verified by a compatibility suite.
Highlights:
- Assembles full geometries from raw OSM elements: multipolygon and boundary relations, routes, ways and POI nodes
- Accepts Overpass JSON, Overpass XML and plain OSM XML, including
out centerandout bbresponses - Produces a GeoJSON
FeatureCollectionor a list of Shapely shapes with properties — ready for GIS pipelines or rendering - Ships a command-line tool (
osm2geojson) - Lightweight: the only dependencies are
shapelyandrequests
Installation
pip install osm2geojson
Requires Python 3.8+.
Try the 1.0 release candidate. Version 1.0 changes the produced GeoJSON (matching osmtogeojson) and cleans up the API. Regular installs are unaffected until the final release; to test it now:
pip install --pre --upgrade osm2geojsonSee the CHANGELOG and MIGRATION_NOTES.md for what changed - and please report any unexpected output differences.
Quick start
import osm2geojson
# Fetch data from the Overpass API and convert it
xml = osm2geojson.overpass_call('rel(448930); out geom;')
geojson = osm2geojson.xml2geojson(xml)
# Or convert a local OSM/Overpass file
with open('data.osm', encoding='utf-8') as f:
geojson = osm2geojson.xml2geojson(f.read())
Command-line interface
osm2geojson map.osm map.geojson -i 2 # convert a file, pretty-printed
osm2geojson data.json - # Overpass JSON to stdout
Run osm2geojson --help for all options (input format autodetect/override,
indentation, custom area/polygon definitions, verbosity).
API reference
Conversion functions
| Function | Input | Output |
|---|---|---|
json2geojson(data, **options) |
Overpass JSON (dict or str) | GeoJSON FeatureCollection |
xml2geojson(xml_str, **options) |
OSM/Overpass XML | GeoJSON FeatureCollection |
json2shapes(data, **options) |
Overpass JSON (dict or str) | list of Shape objects |
xml2shapes(xml_str, **options) |
OSM/Overpass XML | list of Shape objects |
All conversion functions accept these optional keyword-only parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
filter_used_refs |
bool | True |
Drop elements that are only used as parts of other features (False returns everything) |
log_level |
str | None |
Set the library logger level for this call ('DEBUG', 'INFO', ...); None leaves your logging configuration untouched |
area_keys |
dict | None |
Custom area key definitions (defaults from areaKeys.json) |
polygon_features |
list | None |
Custom polygon feature whitelist/blacklist (defaults from polygon-features.json) |
raise_on_failure |
bool | False |
Raise ConversionError on geometry conversion failure instead of skipping the element |
Conversion functions never modify the data passed to them.
Shape objects
json2shapes/xml2shapes return dictionaries pairing a Shapely geometry with
the OSM properties:
{
'shape': Point | LineString | Polygon | ..., # Shapely geometry
'properties': {
'type': 'node' | 'way' | 'relation',
'tags': { ... },
'id': 123,
...
}
}
Use shape_to_feature(shape_obj, properties) to turn a Shape object back into
a GeoJSON Feature.
overpass_call(query, **options)
Execute an Overpass QL query and return the raw response text:
result = osm2geojson.overpass_call('[out:json];node(50.746,7.154,50.748,7.157);out;')
Optional keyword-only parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
endpoint |
str | overpass-api.de | Overpass API endpoint URL |
timeout |
float | 180 |
Timeout in seconds for each HTTP request |
retries |
int | 5 |
Retries on rate limiting (429), transient server errors (5xx), timeouts and connection errors; other errors fail immediately (0 disables retrying) |
retry_delay |
float | 5 |
Seconds to sleep between attempts |
Examples
Query the Overpass API and convert to GeoJSON
import osm2geojson
query = """
[out:json];
(
node["amenity"="restaurant"](50.746,7.154,50.748,7.157);
way["amenity"="restaurant"](50.746,7.154,50.748,7.157);
);
out body geom;
"""
result = osm2geojson.overpass_call(query)
geojson = osm2geojson.json2geojson(result)
Work with Shapely geometries
import json
import osm2geojson
with open('overpass.json', encoding='utf-8') as f:
data = json.load(f)
shapes = osm2geojson.json2shapes(data)
for shape_obj in shapes:
geometry = shape_obj['shape'] # Shapely object
osm_tags = shape_obj['properties']['tags']
print(f"Type: {geometry.geom_type}, Tags: {osm_tags}")
Upgrading to 1.0
Version 1.0 changed the produced GeoJSON (to match osmtogeojson) and made converter options keyword-only. See the CHANGELOG for what changed and MIGRATION_NOTES.md for upgrade help.
Development
git clone https://github.com/rapkin/osm2geojson.git
cd osm2geojson
make setup # one-command setup (installs deps + pre-commit hooks)
make all # format, lint and test (do this before committing!)
Submodules (osm-polygon-features, id-area-keys) are optional - they are
only needed to regenerate the bundled JSON data (update-osm-polygon-features.sh).
Fetch them with git submodule update --init when needed.
- CONTRIBUTING.md - development setup, workflow and guidelines
- AI_AGENT_GUIDE.md - codebase guide for AI coding assistants
- RELEASE_GUIDE.md - release process for maintainers
License
Credits
Developed by rapkin
Uses data from:
- osm-polygon-features - polygon feature definitions
- id-area-keys - area key definitions (extracted from the iD editor's tagging schema)
Metadata
Release files for osm2geojson 1.0.0rc2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| osm2geojson-1.0.0rc2.tar.gz | 25.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| osm2geojson-1.0.0rc2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.0 kB
Release files / osm2geojson-1.0.0rc2.tar.gz
| Download URL | osm2geojson-1.0.0rc2.tar.gz |
|---|---|
| Size | 25.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4af269bb25ed0470ea229d8a17fb980a61b6be64e0ed83210db6db8d8676081b
|
|
BLAKE2b-256 checksum How to use checksums |
bc9e7a017cc217dcf0526f7e19ffa13692665c3fd81d8df4cd81a9f8f8fe72d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / osm2geojson-1.0.0rc2-py3-none-any.whl
| Download URL | osm2geojson-1.0.0rc2-py3-none-any.whl |
|---|---|
| Size | 22.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
be100165d99a405aefa9057ff237e978e5e6608088eb9ee4c6c7a9818cb6a301
|
|
BLAKE2b-256 checksum How to use checksums |
3ff507e27066cce8ebe6bf7f770a2656e6d39031e48fba926056c2d04b97d99f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency log