CLI and Python API to fetch air quality index (AQI) data from the Montreal open data portal
Project description
AQI monitoring for the city of Montréal (Québec, Canada)
A Python library and CLI tool to fetch, process, and expose air quality index (AQI) data from the City of Montréal open data platform.
The project is designed to be:
- scriptable (JSON output by default)
- embeddable as a Python library
- suitable for automation (Home Assistant, cron jobs, data pipelines)
Features
- Fetches the latest air quality data from Montréal’s open data portal
- Lists currently active air quality monitoring stations
- Computes the AQI based on RSQA methodology
- Estimates pollutant concentrations from reported AQI contributions¹
- Exposes structured station and pollutant data via Python models
- Outputs machine-readable JSON from the CLI
- Structured logging with optional debug mode
- Test suite covering core logic, JSON contract, and CLI behavior
¹ Estimated concentrations are derived from rounded AQI values and should be treated as approximations.
Requirements
- Python 3.11 or newer
requests
Installation
From PyPI (recommended)
pip install montreal-aqi-api
From source
git clone https://github.com/normcyr/montreal-aqi-api.git
cd montreal-aqi-api
python3 -m venv venv
source venv/bin/activate
pip install .
CLI Usage
The CLI always outputs JSON on stdout. Logs and diagnostics are written to stderr.
Fetch AQI for a specific station
montreal-aqi --station <station_id>
List available monitoring stations
montreal-aqi --list
Enable debug logging
montreal-aqi --station <station_id> --debug
Print the JSON in a pretty format
montreal-aqi --station <station_id> --pretty
or
montreal-aqi --list --pretty
No arguments
If no arguments are provided, the CLI returns a JSON error payload. Interactive prompts are intentionally avoided to keep behavior predictable in automated environments.
Integrations
This library is designed to be consumed by automated systems and integrations.
Home Assistant
Used by the custom Home Assistant integration:
Other Use Cases
- Cron jobs
- Data ingestion pipelines
- Monitoring dashboards
- Research / environmental analysis
JSON Contract — Version 1 (Frozen)
As of v0.4.0, the JSON output contract is explicitly versioned and frozen. The output format is formally specified in: docs/json_contract_v1.md.
The JSON output is governed by the official JSON Schema v1 and all payloads include:
{
"version": 1,
"type": "..."
}
Error Payload
{
"version": 1,
"type": "error",
"error": {
"code": "NO_DATA",
"message": "No data available for this station"
}
}
Stations List Payload
{
"version": 1,
"type": "stations",
"stations": [
{
"station_id": "3",
"name": "Saint-Jean-Baptiste",
"borough": "Rivière-des-Prairies"
}
]
}
Station AQI Payload
{
"version": 1,
"type": "station",
"station_id": "80",
"date": "2025-08-08",
"hour": 10,
"aqi": 49,
"dominant_pollutant": "PM2.5",
"pollutants": {
"PM2.5": {
"name": "PM2.5",
"aqi": 49,
"concentration": 34.3
},
"O3": {
"name": "O3",
"aqi": 22,
"concentration": 70.4
}
}
}
Python Usage
from montreal_aqi_api.service import get_station_aqi
station = get_station_aqi("80")
if station:
print(station.to_dict())
Domain objects (Station, Pollutant) expose explicit serialization helpers
to ease downstream usage.
AQI Methodology
AQI values follow the methodology defined by the Réseau de surveillance de la qualité de l’air (RSQA).
Reference Values
| Pollutant | Full Name | Reference |
|---|---|---|
| SO₂ | Sulfur Dioxide | 500 µg/m³ |
| CO | Carbon Monoxide | 35 mg/m³ |
| O₃ | Ozone | 160 µg/m³ |
| NO₂ | Nitrogen Dioxide | 400 µg/m³ |
| PM2.5 | Particulate Matter | 35 µg/m³ |
Project Status
- JSON contract v1 frozen and validated by tests
- Suitable for automation and integration
- API stability guaranteed within v1
Contributing
Contributions are welcome.
Please ensure that:
- tests pass (
pytest) - the JSON contract remains backward compatible
- any change affecting output is covered by tests
Open an issue before proposing breaking changes.
Data Source
Data is retrieved from the Ville de Montréal Open Data Portal.
License
This project is licensed under the MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file montreal_aqi_api-0.4.1.tar.gz.
File metadata
- Download URL: montreal_aqi_api-0.4.1.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da07aa1160ad736c545328185e6826cca7c5106cab4f096fbd6c613951e2d505
|
|
| MD5 |
64e5ab3d3fc6a08d4c59cc2b5f25fe32
|
|
| BLAKE2b-256 |
520f9d0c548a52adc247fe72d7f2c6ee86fcb6918fd72e35110ae8fc83906a1e
|
File details
Details for the file montreal_aqi_api-0.4.1-py3-none-any.whl.
File metadata
- Download URL: montreal_aqi_api-0.4.1-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1544bfa669f38f60fc26eb4605e1fcd39af1e025cf60d27132fa64bb990bd16
|
|
| MD5 |
167931421fb6990623632d3f82e34a31
|
|
| BLAKE2b-256 |
76681cbc532a0d10486f627248dfa434726acea2ee846061d7ee854caf13ff98
|