Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/NASAARSET/PM2.5_AQ_Online_2026/llms.txt

Use this file to discover all available pages before exploring further.

OpenAQ is an open-source platform that aggregates real-time and historical air quality measurements from government reference networks, research instruments, and low-cost sensor deployments worldwide. The ARSET 2026 case study uses the OpenAQ API v3 to retrieve hourly PM₂.₅ observations from reference-grade stations inside a user-defined bounding box and time window. The F_get_OpenAQ_from_API function wraps the full three-step v3 workflow — parameter lookup, location discovery, and per-sensor measurement retrieval — into a single call that returns a tidy pandas.DataFrame indexed by (lat, lon, time), identical in structure to the output of F_get_SINCA_from_web.

OpenAQ Documentation

Full API reference and platform overview

Get an API Key

Register for a free OpenAQ API key

Authentication

All v3 endpoints require an API key supplied in the X-API-Key request header. Obtain a key at the link above and pass it at notebook startup:
import getpass
s_key_openAQ = getpass.getpass('Enter OpenAQ API key:')
Never hard-code your API key in a shared notebook or commit it to version control. Use getpass.getpass for interactive entry or store the key in an environment variable / Google Colab Secret.

Supported parameters

F_get_OpenAQ_from_API accepts any subset of these pollution species via the l_variables argument:
Display nameOpenAQ nameDefault unitNotes
PM2.5pm25µg/m³Default query variable
PM10pm10µg/m³
O3o3ppbAuto-converted to ppb
NO2no2ppbAuto-converted to ppb
SO2so2ppbAuto-converted to ppb
COcoppbAuto-converted to ppb
BCbcµg/m³
Unit conversion to ppb (gases) or µg/m³ (particles) is applied automatically inside the function using pre-defined multipliers.

API endpoints used

The function calls three sequential v3 endpoints:
GET https://api.openaq.org/v3/parameters
GET https://api.openaq.org/v3/locations?limit=1000&page={n_page}
    &bbox={n_lon_min},{n_lat_min},{n_lon_max},{n_lat_max}
    &parameters_id={s_parameter_ids}&mobile=false&monitor=true
GET https://api.openaq.org/v3/sensors/{n_sensor_id}/measurements
    ?limit=1000&page={n_page}
    &datetime_from={s_datetime_from}&datetime_to={s_datetime_to}
Pagination is handled transparently — the function increments n_page until all results are retrieved for both locations and measurements.

Usage

Reference monitors only (default)

f_data_monitors_OpenAQ = F_get_OpenAQ_from_API(
    n_lon_min=-73.75,
    n_lat_min=-38.0,
    n_lon_max=-69.75,
    n_lat_max=-32.0,
    t_start=np.datetime64('2022-12-01 00:00:00'),
    t_end=np.datetime64('2023-03-31 23:59:59'),
    l_variables=['PM2.5'],
    b_reference=True,
    b_lowcost=False,
    s_key=s_key_openAQ,
)

Low-cost sensors only

f_data_lcs = F_get_OpenAQ_from_API(
    n_lon_min=n_lon_min,
    n_lat_min=n_lat_min,
    n_lon_max=n_lon_max,
    n_lat_max=n_lat_max,
    t_start=t_start,
    t_end=t_end,
    l_variables=['PM2.5'],
    b_reference=False,
    b_lowcost=True,
    s_key=s_key_openAQ,
)

Multiple species

f_data_multi = F_get_OpenAQ_from_API(
    n_lon_min=n_lon_min,
    n_lat_min=n_lat_min,
    n_lon_max=n_lon_max,
    n_lat_max=n_lat_max,
    t_start=t_start,
    t_end=t_end,
    l_variables=['PM2.5', 'O3', 'NO2'],
    b_reference=True,
    b_lowcost=False,
    s_key=s_key_openAQ,
)

Return format

The function returns a pandas.DataFrame with a three-level MultiIndex (lat, lon, time) and one column per requested species (e.g. PM2.5). Values are in the normalised units shown in the table above. The time index is UTC-aware (pd.Timestamp with tz=UTC). Returns None if no data are found.
                                    PM2.5
lat         lon        time
-33.464142  -70.660797 2023-02-14 18:30:00+00:00   24.1
                        2023-02-14 19:30:00+00:00   27.3
                        ...
Timestamps in the returned DataFrame represent the midpoint of each measurement period, computed as datetimeFrom + (datetimeTo - datetimeFrom) / 2. This ensures consistent time alignment when merging with MERRA-2 CNN or SINCA hourly data.

OpenAQ vs SINCA for the Chile 2023 case study

For the February 2023 Chilean megafire episode, OpenAQ data are noticeably smoother than the SINCA hourly records and miss the highest fire-smoke peaks. This occurs for two reasons:
  1. Temporal resolution: OpenAQ ingests Chilean PM₂.₅ data as 24-hour rolling averages (rather than 1-hour averages), which attenuates sharp concentration spikes.
  2. Validation lag: OpenAQ primarily carries validated records. Data flagged as preliminary or not-validated by SINCA during extreme episodes are largely absent until the validation workflow is complete — precisely when the satellite signal is strongest.
The plot below (reproduced from the notebook) illustrates the difference at the Parque O’Higgins reference station in Santiago:
import matplotlib.pyplot as plt

n_monitor_lat, n_monitor_lon = -33.464142, -70.660797

f_data_monitors_OpenAQ_at_site = f_data_monitors_OpenAQ.loc[(n_monitor_lat, n_monitor_lon)]
f_data_monitors_SINCA_at_site  = f_data_monitors_SINCA.loc[(n_monitor_lat, n_monitor_lon)]

o_fig = plt.figure(figsize=(15, 5))
o_ax  = o_fig.add_subplot(111)
o_ax.plot(f_data_monitors_OpenAQ_at_site.index, f_data_monitors_OpenAQ_at_site['PM2.5'], color='blue',   label='Data from OpenAQ')
o_ax.plot(f_data_monitors_SINCA_at_site.index,  f_data_monitors_SINCA_at_site['PM2.5'],  color='orange', label='Data from SINCA')
o_ax.set_ylabel('PM$_{2.5}$ [µg/m$^{3}$]')
o_ax.set_title("Parque O'Higgins — OpenAQ vs SINCA")
o_ax.legend()
For recent or extreme air quality events where validated data may not yet be available in OpenAQ, consider querying the source network directly. For Chile, use F_get_SINCA_from_web, which exposes validated, preliminary, and not-validated data tiers and returns data in the identical (lat, lon, time) format. See the SINCA data source page for details.

Full function reference

See F_get_OpenAQ_from_API for the complete parameter list, internal pagination logic, unit-conversion tables, and notes on combining multiple species into one DataFrame.

Build docs developers (and LLMs) love