Skip to content

112 quackosm

image image image

Downloading and visualizing OpenStreetMap data with QuackOSM

QuackOSM is a high-performance library for reading OpenStreetMap data using DuckDB. It offers significant speed improvements over traditional methods and can handle large datasets efficiently.

Uncomment the following line to install leafmap and quackosm if needed.

1
# %pip install -U leafmap quackosm
1
2
import leafmap
import leafmap.osm as osm

Download OSM data by place name

The quackosm_gdf_from_place function downloads OSM data for a given place name. QuackOSM automatically finds and downloads the required PBF files.

1
2
3
4
# Download all OSM features for Monaco
gdf = osm.quackosm_gdf_from_place("Monaco")
print(f"Downloaded {len(gdf)} features")
gdf.head()

Visualize the data on an interactive map:

1
2
3
m = leafmap.Map()
m.add_gdf(gdf, layer_name="Monaco OSM")
m

Filter by OSM tags

You can filter OSM features by specifying tags. For example, download only buildings:

1
2
3
4
# Download only buildings in Monaco
buildings = osm.quackosm_gdf_from_place("Monaco", tags={"building": True})
print(f"Downloaded {len(buildings)} buildings")
buildings.head()
1
2
3
m = leafmap.Map()
m.add_gdf(buildings, layer_name="Buildings", style={"color": "red", "fillOpacity": 0.3})
m

Download roads and highways:

1
2
3
4
# Download roads in Monaco
roads = osm.quackosm_gdf_from_place("Monaco", tags={"highway": True})
print(f"Downloaded {len(roads)} road features")
roads.head()
1
2
3
m = leafmap.Map()
m.add_gdf(roads, layer_name="Roads", style={"color": "blue", "weight": 2})
m

Filter for specific tag values:

1
2
3
4
5
6
# Download restaurants and cafes
dining = osm.quackosm_gdf_from_place(
    "Monaco", tags={"amenity": ["restaurant", "cafe", "bar"]}
)
print(f"Downloaded {len(dining)} dining establishments")
dining.head()
1
2
3
m = leafmap.Map()
m.add_gdf(dining, layer_name="Dining", style={"color": "green", "fillColor": "green"})
m

Download OSM data by bounding box

Use quackosm_gdf_from_bbox to download data for a specific bounding box:

1
2
3
4
5
6
7
# Bounding box for Vatican City area (west, south, east, north)
bbox = (12.445, 41.900, 12.460, 41.910)

# Download all features in the bounding box
gdf_bbox = osm.quackosm_gdf_from_bbox(bbox)
print(f"Downloaded {len(gdf_bbox)} features")
gdf_bbox.head()
1
2
3
m = leafmap.Map(center=[41.905, 12.4525], zoom=16)
m.add_gdf(gdf_bbox, layer_name="Vatican Area OSM")
m

Download only buildings in the bounding box:

1
2
buildings_bbox = osm.quackosm_gdf_from_bbox(bbox, tags={"building": True})
print(f"Downloaded {len(buildings_bbox)} buildings")
1
2
3
4
5
6
7
m = leafmap.Map(center=[41.905, 12.4525], zoom=16)
m.add_gdf(
    buildings_bbox,
    layer_name="Buildings",
    style={"color": "orange", "fillOpacity": 0.5},
)
m

Download OSM data by geometry

Use quackosm_gdf_from_geometry to download data for a custom geometry:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from shapely.geometry import Polygon

# Create a custom polygon
coords = [(7.41, 43.73), (7.43, 43.73), (7.43, 43.75), (7.41, 43.75), (7.41, 43.73)]
polygon = Polygon(coords)

# Download natural features
natural = osm.quackosm_gdf_from_geometry(polygon, tags={"natural": True})
print(f"Downloaded {len(natural)} natural features")
natural.head()
1
2
3
4
5
m = leafmap.Map(center=[43.74, 7.42], zoom=14)
m.add_gdf(
    natural, layer_name="Natural Features", style={"color": "green", "fillOpacity": 0.4}
)
m

Using WKT or GeoJSON geometry

You can also use WKT strings or GeoJSON dictionaries as geometry input:

1
2
3
4
# Using WKT string
wkt = "POLYGON ((7.41 43.73, 7.43 43.73, 7.43 43.75, 7.41 43.75, 7.41 43.73))"
leisure = osm.quackosm_gdf_from_geometry(wkt, tags={"leisure": True})
print(f"Downloaded {len(leisure)} leisure features")
1
2
3
m = leafmap.Map(center=[43.74, 7.42], zoom=14)
m.add_gdf(leisure, layer_name="Leisure", style={"color": "purple", "fillOpacity": 0.4})
m

Multiple layers on a single map

Let's combine multiple OSM layers on a single map:

1
2
3
4
5
6
# Download different feature types for Monaco
buildings = osm.quackosm_gdf_from_place("Monaco", tags={"building": True})
roads = osm.quackosm_gdf_from_place("Monaco", tags={"highway": True})
water = osm.quackosm_gdf_from_place("Monaco", tags={"natural": "water"})

print(f"Buildings: {len(buildings)}, Roads: {len(roads)}, Water: {len(water)}")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
m = leafmap.Map()

# Add layers with different styles
if len(buildings) > 0:
    m.add_gdf(
        buildings,
        layer_name="Buildings",
        style={"color": "red", "fillOpacity": 0.3, "weight": 1},
    )
if len(roads) > 0:
    m.add_gdf(roads, layer_name="Roads", style={"color": "gray", "weight": 2})
if len(water) > 0:
    m.add_gdf(water, layer_name="Water", style={"color": "blue", "fillOpacity": 0.5})

m.zoom_to_gdf(buildings)
m

Export to GeoParquet

QuackOSM can efficiently export data to GeoParquet format, which is optimized for cloud storage and analytical workflows:

1
2
3
4
5
6
7
# Export Monaco buildings to GeoParquet
# output_path = osm.quackosm_to_parquet(
#     "Monaco",
#     "monaco_buildings.parquet",
#     tags={"building": True}
# )
# print(f"Saved to: {output_path}")

Common OSM tags

Here are some commonly used OSM tags for filtering:

Category Tag Examples
Buildings {"building": True}, {"building": "residential"}
Roads {"highway": True}, {"highway": ["primary", "secondary"]}
Water {"natural": "water"}, {"waterway": True}
Land use {"landuse": True}, {"landuse": ["residential", "commercial"]}
Amenities {"amenity": True}, {"amenity": ["restaurant", "hospital"]}
Shops {"shop": True}, {"shop": ["supermarket", "convenience"]}
Tourism {"tourism": True}, {"tourism": ["hotel", "attraction"]}
Natural {"natural": True}, {"natural": ["tree", "wood"]}
Leisure {"leisure": True}, {"leisure": ["park", "playground"]}

For a complete list of OSM tags, visit: https://wiki.openstreetmap.org/wiki/Map_features

Performance comparison

QuackOSM typically offers 2-10x faster performance compared to osmnx for large datasets, thanks to: - DuckDB-based parallel processing - Efficient caching of downloaded PBF files - Optimized geometry operations

For very large areas, consider using the verbosity_mode="verbose" parameter to see progress information.