# Rail network of Europe

*Every railway, tram, metro and funicular line in Europe, as segments.*

Europe's rail network from Overture Maps' transportation theme: one row per line segment with its class (standard gauge, narrow gauge, tram, subway, light rail, funicular, monorail), its name where the line has one, flags such as passenger, freight, disused, bridge or tunnel, its length in metres, a bounding box and a native geometry column (Iceberg v3, rows in Hilbert order). About 960,000 segments.

## At a glance

| | |
|---|---|
| Table | `pubdata.transport.rail_segments` |
| Category | Transport · Transport, Rail, Spatial, Europe |
| Rows | 962,699 |
| Size | 2 data file(s) |
| Iceberg format | v3 |
| Last refreshed | 2026-10-10T12:50:15Z |
| Source version | overture 2026-09-23.1 |
| Refresh cadence | monthly (replace) |
| Coverage | a box around Europe (25°W to 45°E, 34°N to 72°N); the latest Overture release |

## Origin

- **Source:** [Overture Maps Foundation, transportation theme (rail segments; OpenStreetMap-derived)](https://docs.overturemaps.org/guides/transportation/)
- **Licence:** ODbL 1.0 (OpenStreetMap-derived); this table, a derived database, is published under ODbL 1.0 too
- **Attribution:** © OpenStreetMap contributors (ODbL 1.0), via the Overture Maps Foundation transportation theme.
- **Note:** Overture releases monthly; the release name is the source version. Measured on 2026-09-23.1, about 0.2 GB.
- **Recipe:** `pubdata/recipes/rail_network.py` in the LakehouseBox repository; registry entry `pubdata/registry/rail_network.yaml`.

## Schema

| column | type | description |
|---|---|---|
| `segment_id` | string | Overture GERS id of the segment |
| `class` | string | standard_gauge, narrow_gauge, tram, subway, light_rail, funicular, monorail or unknown |
| `subclass` | string | Overture's finer class when set |
| `name` | string | the line's name when it has one |
| `flags` | string | comma-separated rail flags when set: is_passenger, is_freight, is_disused, is_abandoned, is_bridge, is_tunnel, … |
| `length_m` | double | spheroidal length in metres |
| `bbox_xmin` | double | bounding box west (longitude) |
| `bbox_ymin` | double | bounding box south (latitude) |
| `bbox_xmax` | double | bounding box east |
| `bbox_ymax` | double | bounding box north |
| `geometry` | geometry | the line (WGS84, longitude/latitude) |
| `overture_release` | string | the release this row came from |

**Join keys:** `segment_id`.

## For agents

A segment is a piece of track between junctions, not a whole line: sum `length_m` for lengths and group by `name`
only where names are set. `flags` carries OpenStreetMap's tags; exclude `is_disused` and `is_abandoned` for the
working network. The box includes the edges of North Africa and Anatolia; join `places.admin_areas` for countries.
`geometry` is an Iceberg v3 geometry column (DuckDB 1.5.6 or newer; PyIceberg 0.12 cannot load v3 geometry tables
yet): filter with `geometry && <shape> AND ST_Intersects(geometry, <shape>)`, which skips files and row groups.
Attribution to OpenStreetMap contributors (ODbL) is required wherever the data is shown.

## Example SQL (DuckDB)

```sql
-- kilometres of line by class
SELECT class, round(sum(length_m) / 1000) AS km
FROM pubdata.transport.rail_segments GROUP BY 1 ORDER BY 2 DESC;
-- tram network per region, with the regions of places.admin_areas (`&&` on the bounding boxes first, exact second)
INSTALL spatial; LOAD spatial;
SELECT a.region_code, a.name, round(sum(r.length_m) / 1000, 1) AS tram_km
FROM pubdata.transport.rail_segments AS r JOIN pubdata.places.admin_areas AS a
  ON a.subtype = 'region' AND a.class = 'land'
 AND a.geometry && r.geometry AND ST_Intersects(a.geometry, r.geometry)
WHERE r.class = 'tram'
GROUP BY 1, 2 ORDER BY tram_km DESC LIMIT 20;
```

## How to read it

Without an account, over HTTPS (the bucket is public):

```sql
INSTALL iceberg; LOAD iceberg; INSTALL httpfs; LOAD httpfs;
-- anonymous: the bucket is public, requests go unsigned, through the public-data cache
CREATE OR REPLACE SECRET pubdata (TYPE S3, ENDPOINT 'lakehousebox-public-data.b-cdn.net', URL_STYLE 'path', REGION 'us-east-1');
CREATE OR REPLACE VIEW rail_segments AS SELECT * FROM iceberg_scan('s3://commons--pubdata/transport/rail_segments');
SELECT * FROM rail_segments LIMIT 10;
```

With a LakehouseBox account:

```bash
# with a LakehouseBox account (any organisation): the public catalog by name, read-only
lhbox duckdb --catalog commons/pubdata     # opens DuckDB attached as `commons_pubdata`
SELECT * FROM commons_pubdata.transport.rail_segments LIMIT 10;
```

Public URL of the table's storage: `https://s3.lakehousebox.com/commons--pubdata/transport/rail_segments/`. This card: `https://lakehousebox.com/pubdata/cards/rail_network.md`; the page: https://lakehousebox.com/public-data/rail_network. Every dataset as a table: `commons_pubdata.meta.datasets`; as Markdown: https://lakehousebox.com/public-data.md.
