Air Quality API - US AQI, Pollutants & Cleanest Hours Forecast
Pricing
$20.00 / 1,000 query answereds
Air Quality API - US AQI, Pollutants & Cleanest Hours Forecast
Air quality for any coordinates worldwide: current US AQI, PM2.5, PM10, ozone, NO2, SO2, CO and UV index, an EPA AirNow-based outdoor exercise verdict, and the cleanest and dirtiest windows up to 7 days ahead. Modelled Copernicus CAMS data via Open-Meteo. JSON/CSV rows, pay per query.
Pricing
$20.00 / 1,000 query answereds
Rating
0.0
(0)
Developer
Dave Fergins
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Air quality data for any coordinates worldwide as plain JSON or CSV rows: the current US AQI with the pollutant breakdown (PM2.5, PM10, ozone, nitrogen dioxide, sulphur dioxide, carbon monoxide and UV index), the EPA category and activity guidance, a GO / CAUTION / AVOID verdict on exercising outdoors right now, and the cleanest and dirtiest contiguous windows of the length you choose within the next 7 days. The data is modelled (Copernicus CAMS via Open-Meteo), not a reading from a sensor at your exact location, and the guidance is general public-health information, not medical advice.
The Actor is a thin client: it sends each query you give it to the air quality service, charges one event per query the service answers, and writes the answer to the dataset as one summary row, plus one row per forecast hour when you ask for the hourly series. A run takes seconds and uses 256 MB. You need no API key or account with any data provider; the Actor carries its own credential.
Air quality now: US AQI, pollutants and an outdoor exercise verdict
One query is a point (lat, lon) anywhere in the world. The summary row carries the current reading: time (local, with the location's timezone), us_aqi, pm2_5, pm10, ozone, nitrogen_dioxide, sulphur_dioxide, carbon_monoxide (all in micrograms per cubic metre) and uv_index; the EPA band of the current AQI (Good, Moderate, Unhealthy for Sensitive Groups, and so on) with the matching advice; exercise_verdict (GO, CAUTION or AVOID); and dominant_pollutant, the one closest to its own limit now. A summary field holds the whole answer as one paragraph, with your place label in it if you gave one.
The cleanest window ahead: when to go outside
hours says how far ahead to search (default 24, at most 168, which is 7 days) and duration how many hours you want to be outside (default 1). The service finds the cleanest contiguous block of that length and the dirtiest, and the summary row carries both flattened: best_window_start, best_window_end, best_window_mean_us_aqi, best_window_peak_us_aqi, best_window_band, and the same five for worst_window. improving is true when the best window is cleaner than now. Set hourly to true to add one hourly row per forecast hour with the same pollutant columns; it is most of the payload, so it is off by default.
Several points in one run
The top-level fields are the first query and the defaults for every other. Add points as a list of "lat,lon" strings for more locations with the same settings, or queries as a list of objects using the same field names for anything else, for instance a different duration or place per point. A queries object with its own point does not inherit the top-level one; one that only changes a setting runs at the top-level point. The place label belongs to its point: extra points and queries carry their own label or none, and a place in a queries object needs its lat and lon beside it. A run may hold at most 25 queries, and each query the service answers is one billable event.
Example input
{"lat": 47.6588,"lon": -117.426,"hours": 24,"duration": 2,"hourly": false,"place": "Spokane","points": ["45.5152,-122.6784"],"queries": [{ "lat": 34.0522, "lon": -118.2437, "place": "Los Angeles", "duration": 3 }]}
That run is three queries: Spokane for a two-hour session within the next 24 hours, Portland with the same settings, and Los Angeles for a three-hour session. Field names are the service's own, so a queries object is exactly the query it sends.
Output: example rows, CSV views and the OUTPUT record
Every row starts with the same eight columns: scout, row_type (summary or hourly), query_index (1-based position in the run), query (the normalised query as sent), as_of (the current reading's local time), receipt, source and disclaimer. Then the row's own fields. A summary row looks like this:
{"scout": "air","row_type": "summary","query_index": 1,"query": { "duration": 2, "hours": 24, "lat": 47.6588, "lon": -117.426, "place": "Spokane" },"as_of": "2026-10-08T13:00:00-06:00","receipt": "","source": "Open-Meteo Air Quality API (CC-BY-4.0), based on Copernicus Atmosphere Monitoring Service (CAMS) models","disclaimer": "Air quality is modelled (Copernicus CAMS via Open-Meteo) ...","time": "2026-10-08T13:00:00-06:00","timezone": "America/Los_Angeles","us_aqi": 42,"band": "Good","advice": "Air quality is good. No restrictions on outdoor activity.","exercise_verdict": "GO","dominant_pollutant": "ozone","pm2_5": 9.8,"pm10": 14.1,"ozone": 61,"nitrogen_dioxide": 7.2,"sulphur_dioxide": 1.1,"carbon_monoxide": 182,"uv_index": 3.4,"improving": true,"best_window_start": "2026-10-08T20:00:00-06:00","best_window_end": "2026-10-08T22:00:00-06:00","best_window_mean_us_aqi": 28,"best_window_peak_us_aqi": 31,"best_window_band": "Good","worst_window_start": "2026-10-08T15:00:00-06:00","worst_window_end": "2026-10-08T17:00:00-06:00","worst_window_mean_us_aqi": 55,"worst_window_peak_us_aqi": 58,"worst_window_band": "Moderate","summary": "Spokane - US AQI 42 (Good). GO: Air quality is good. ..."}
The dataset has two table views: summary (one line per query) and hourly (one line per forecast hour). Filter on row_type when you export both as one CSV. The run's OUTPUT key-value record holds the service's response for every query verbatim, keyed q1, q2, ..., each with the query it answered, plus an errors map for any query that failed.
Pricing: pay per query answered
One query-answered event per query the service answered, whether or not you asked for the hourly series: one point is one event, ten points is ten events. Rows are never billed individually, so hourly changes the size of the dataset, not the price. A query the service refuses (coordinates it cannot model, the service warming up) is not charged, and the run still succeeds with the queries that worked; only a run where every query failed ends as failed. Price: $0.02 per query answered, on every Apify plan. Example: a daily schedule of three points is about 90 queries a month, $1.80. An hourly schedule for one point is about 720 queries a month, $14.40.
Use cases: air quality monitoring, training plans and dashboards
- Air quality monitoring: schedule the run for the points you care about and keep the summary rows as a time series, with
as_ofon every row. - Training and event planning: the cleanest
duration-hour window in the next day or week, per location, ready for a calendar or a notification. - Health and school notices: the EPA band, advice and GO / CAUTION / AVOID verdict per site, in a table.
- Spreadsheets and dashboards: export the
summaryview as CSV or attach Apify's Google Sheets integration so every scheduled run appends its rows. - AI agents and automations: like any public Actor it can be called through the Apify API, a webhook or Apify's MCP server, with the same input and the same dataset.
Data source and attribution
The data is the Open-Meteo Air Quality API (CC-BY-4.0), based on Copernicus Atmosphere Monitoring Service (CAMS) models: modelled values for any coordinates worldwide, up to 7 days ahead. The AQI is the US EPA scale and the activity guidance follows the US EPA AirNow categories. Every row carries the attribution in source and the service's disclaimer verbatim:
Air quality is modelled (Copernicus CAMS via Open-Meteo), not a reading from a sensor at your exact location; local conditions near fires, traffic or industry can differ sharply. Activity guidance follows US EPA AirNow categories and is general public-health information, not medical advice — if you have a heart or lung condition, follow your clinician's advice.
FAQ
Does it work outside the US? Yes, anywhere in the world: the model is global. The AQI scale and the activity categories are the US EPA's, applied everywhere.
Is this a sensor reading? No. Values are modelled by Copernicus CAMS, served through Open-Meteo, for the grid cell around your point. Conditions near fires, traffic or industry can differ sharply from the model.
What is the cleanest window? The contiguous block of duration hours, within the next hours hours, with the lowest mean US AQI; worst_window is the opposite. Both carry the mean, the peak and the EPA band.
Can I get the full hourly forecast? Yes: set hourly to true and each forecast hour becomes a row with us_aqi, pm2_5, ozone and the other pollutants where modelled. The price does not change.
Can I check several locations in one run? Yes: points for more "lat,lon" locations with the same settings, or queries for a list of full query objects. At most 25 queries per run, one event each.
What are the pollutant units? Micrograms per cubic metre for PM2.5, PM10, ozone, nitrogen dioxide, sulphur dioxide and carbon monoxide; uv_index is the UV index.
Do I need an API key? No. The Actor carries its own credential for the air quality service; you only give it the queries.
Why did one query fail while the others worked? The service answers each query on its own; a query it cannot answer is recorded in the status message and the OUTPUT record's errors map, skipped without charge, and the rest continue. A query the service never answers (unreachable, or a gateway error) is retried once; after two such queries in a row the remaining ones are skipped rather than waited for.
What happens with an empty input? The run succeeds with one unbilled status row (status: needs_input) that names the missing fields, gives a hint and repeats the example input. Nothing is sent to the service and nothing is charged. Any field that is present must still be valid.