---
name: orr-rail-statistics-data-portal-ingestion
description: "How to get ORR rail statistics data portal data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Load an ORR periodic freight table into Parquet

Source entry: https://signal-lab-jet.vercel.app/datasets/orr-rail-statistics-data-portal
Provider: https://dataportal.orr.gov.uk/
Checked against the provider's documentation: 2026-11-01

## Access
- No account or key. The table rows are embedded in the public HTML page.
- The page also offers client-side CSV, JSON and XLSX downloads.

## Request
```bash
curl 'https://dataportal.orr.gov.uk/statistics/usage/freight-rail-usage-and-performance/table-1314-freight-moved-by-commodity-periodic-1/'
```

## Format
HTML table with one row per rail period and 13 commodity columns measured in million net tonne kilometres.

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""ORR periodic freight-by-commodity table -> pandas -> Parquet. No key."""
from html.parser import HTMLParser
import requests
import pandas as pd

URL = "https://dataportal.orr.gov.uk/statistics/usage/freight-rail-usage-and-performance/table-1314-freight-moved-by-commodity-periodic-1/"

class TableParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_table = False
        self.in_cell = False
        self.row = []
        self.rows = []
        self.text = []
    def handle_starttag(self, tag, attrs):
        attrs = dict(attrs)
        if tag == "table" and attrs.get("id") == "reportTable":
            self.in_table = True
        elif self.in_table and tag == "tr":
            self.row = []
        elif self.in_table and tag in {"th", "td"}:
            self.in_cell = True
            self.text = []
    def handle_data(self, data):
        if self.in_cell:
            self.text.append(data)
    def handle_endtag(self, tag):
        if self.in_table and tag in {"th", "td"}:
            self.row.append(" ".join("".join(self.text).split()))
            self.in_cell = False
        elif self.in_table and tag == "tr" and self.row:
            self.rows.append(self.row)
        elif self.in_table and tag == "table":
            self.in_table = False

r = requests.get(URL, timeout=60)
r.raise_for_status()
parser = TableParser()
parser.feed(r.text)
df = pd.DataFrame(parser.rows[1:], columns=parser.rows[0])
df.to_parquet("orr_freight_moved_by_commodity.parquet", index=False)
print(len(df), "rows", df["Time period"].iloc[0], "to", df["Time period"].iloc[-1],
      len(df.columns) - 1, "commodity columns")
```
Run by us on 2026-11-01 (python 3.13.5 | pandas 3.1.0 | pyarrow 26.0.0 | requests 2.34.2). Result: 97 rows Apr 2019 to Mar 2020 (Period 01) to Apr 2026 to Mar 2027 (Period 06) 13 commodity columns

## Limits
- Rate limit: Not stated.
- The example covers one periodic freight table, not the portal's full collection.
- ORR says periodic freight tables can take up to 15 working days after period end to update.

## Quirks
- The CSV, JSON and XLSX buttons generate downloads in the browser; the example parses the same embedded HTML table.
- Rail periods are four-week reporting periods and are labeled within a financial year, not calendar months.
- Commodity columns include their unit in the header; retain the header text or map units separately.

## Terms and attribution
- ORR Crown-copyright material may be reused under OGL v3 free of charge.
- Logos and identified third-party material are excluded from that permission.
- Terms page: https://www.orr.gov.uk/terms-and-conditions

## Sources
- https://dataportal.orr.gov.uk/statistics/usage/freight-rail-usage-and-performance/: "Quarterly and periodic (4-weekly) statistics on the volume of freight transported by rail and the punctuality of those services."
- https://dataportal.orr.gov.uk/statistics/usage/freight-rail-usage-and-performance/: "it can take up to 15 working days after period end for the table to be updated."
- https://dataportal.orr.gov.uk/statistics/usage/freight-rail-usage-and-performance/table-1314-freight-moved-by-commodity-periodic-1/: "Download CSV"
- https://www.orr.gov.uk/terms-and-conditions: "All content is available under the Open Government Licence v3.0, except where otherwise stated"

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab-jet.vercel.app/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
