# Weather Data — Multi-Location Forecasts (Open-Meteo) (`leorochasantos/weather-data`) Actor

Current conditions, hourly and daily forecasts, and air quality for one or many cities or GPS coordinates in a single run, from Open-Meteo (free, no API key). Bulk multi-location queries with built-in geocoding; one clean JSON row per location per period slice.

- **URL**: https://apify.com/leorochasantos/weather-data.md
- **Developed by:** [Leonardo Santos](https://apify.com/leorochasantos) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.33 / 1,000 weather data rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Weather Data — Multi-Location Forecasts (Open-Meteo)

Current conditions, hourly and daily forecasts, and air quality for one city or
a hundred — in a single run. Give it place names (`Berlin`, `Sao Paulo`) or GPS
coordinates (`52.52, 13.41`); it geocodes them, fetches every requested period
slice from **Open-Meteo** (a free public API — no API key, no upstream cost),
and returns one clean JSON row per location per slice, with explicit units and
null-safe optional variables.

### Why this actor?

- **Bulk multi-location in one run** — the wedge: geocoding + forecast +
  air quality for up to 100 locations in a single call, one bill.
- **Free upstream, no key** — you pay only for the convenience of a typed,
  unified, agent-ready dataset.
- **Null-safe rows** — unavailable variables are explicit `null`, never dropped
  rows or crashes.
- **Flat, typed output** — every row carries location identity, source, period,
  timestamp, and units, so downstream pipelines (dashboards, LLM/MCP agents)
  can merge locations without re-resolving anything.
- **Predictable billing** — one charge per delivered row, charged only after
  the row lands in your dataset; errors are free.

### Input

```json
{
  "locations": [
    { "query": "Berlin" },
    { "query": "Paris" },
    { "lat": 40.7128, "lon": -74.006 }
  ],
  "current": true,
  "hourly": ["temperature_2m", "precipitation", "wind_speed_10m"],
  "daily": ["temperature_2m_max", "precipitation_sum"],
  "air_quality": ["us_aqi"],
  "forecast_days": 1,
  "units": "metric",
  "max_locations": 100
}
```

`locations` is required. Every other field has a sensible default: current
conditions on, 1 forecast day, metric units, `auto` timezone, up to 100
locations (a hard, locally enforced cap).

### Output

One row per location per requested period slice:

```json
{
  "location": { "query": "Berlin", "lat": 52.52, "lon": 13.41, "resolved_name": "Berlin, Germany" },
  "source": "open-meteo",
  "period": "current",
  "timestamp": "2026-08-07T12:15:00.000Z",
  "temperature_2m": 24.1,
  "relative_humidity_2m": 58,
  "wind_speed_10m": 11.2,
  "units": { "temperature_2m": "°C", "wind_speed_10m": "km/h" }
}
```

Hourly and daily rows carry `period: "hourly"` / `"daily"` and one timestamp per
hour or day; air-quality rows carry `period: "air_quality"` with variables like
`us_aqi`, `pm2_5`, `pm10`. Dataset views split the periods for you.

### Pricing

### Pricing

Pay per event, and **the platform usage is on us** — the price you see is the price you pay, with no compute bill on top.

| Event | Price | What one charge buys |
|---|---|---|
| Weather data row | **$0.0005** | Charged once per delivered weather row — one location per requested period slice (current, hourly, daily, or air quality). Rows are charged only after they are pushed to the dataset; unresolvable locations, empty results, and upstream failures are free error items and never charged. |
| Actor Start | **$0.002** | One run, whatever it returns. |

Higher Apify subscription tiers pay less on every event (Silver −20%, Gold −35%).

### Use cases

- **Multi-city current conditions** — dashboards and ops boards with one run
  per refresh instead of N curls.
- **Hourly forecast feeds** — energy, logistics, or agriculture pipelines that
  need hour-by-hour temperature/precipitation/wind.
- **Air-quality monitoring** — US/EU AQI plus particulate and gas concentrations
  for a list of cities.
- **LLM/MCP tooling** — clean, typed JSON with units on every row; no scraping,
  no parsing of a free API yourself.

### FAQ

**Does this actor need an API key?** No. Open-Meteo is a free public API —
there is no upstream cost, ever. (A future OpenWeatherMap secondary source
would use a user-supplied free-tier key.)

**How many locations can I query?** Up to `max_locations` (default 100, hard
cap 100). The cap is enforced locally before any request — the upstream would
accept more, we never fetch or bill more.

**What is a "row" for billing?** One location × one period slice: a current
block is one row, an hourly slice is one row per hour, a daily slice is one row
per day, an air-quality block is one row. A 10-city current-conditions run is
10 rows.

**What happens when a city can't be resolved?** It becomes a free error item
with the message in the `error` field — the rest of your locations still
return. Empty results and upstream failures are free too; nothing is charged
that isn't delivered.

***

*This Actor is an independent tool and is not affiliated with Open-Meteo.
Weather data is provided by the free Open-Meteo API (`api.open-meteo.com`,
`geocoding-api.open-meteo.com`, `air-quality-api.open-meteo.com`).*

# Actor input Schema

## `locations` (type: `array`):

One location per object: <code>{"query": "Berlin"}</code> (resolved via Open-Meteo geocoding) or <code>{"lat": 52.52, "lon": 13.41}</code> (exact coordinates, no geocoding needed). Up to <code>max\_locations</code> entries are processed; duplicates are dropped. One weather row is delivered per location per requested period slice (current, hourly, daily, air quality).

## `current` (type: `boolean`):

Fetch the current-conditions block per location (temperature, humidity, apparent temperature, precipitation, weather code, cloud cover, pressure, wind). One row per location.

## `hourly` (type: `array`):

Hourly forecast variables, one row per hour per location. Supported: temperature\_2m, relative\_humidity\_2m, dew\_point\_2m, apparent\_temperature, precipitation\_probability, precipitation, rain, showers, snowfall, snow\_depth, weather\_code, cloud\_cover, is\_day, visibility, wind\_speed\_10m, wind\_direction\_10m, wind\_gusts\_10m, uv\_index, sunshine\_duration, and more (see SPEC.md for the full list).

## `daily` (type: `array`):

Daily forecast variables, one row per day per location. Supported: weather\_code, temperature\_2m\_max, temperature\_2m\_min, apparent\_temperature\_max, apparent\_temperature\_min, sunrise, sunset, precipitation\_sum, rain\_sum, snowfall\_sum, precipitation\_probability\_max, wind\_speed\_10m\_max, wind\_gusts\_10m\_max, wind\_direction\_10m\_dominant, and more (see SPEC.md for the full list).

## `air_quality` (type: `array`):

Current air-quality variables, one row per location (values are explicit null when a location has no coverage). Supported: us\_aqi, eu\_aqi, pm10, pm2\_5, carbon\_monoxide, nitrogen\_dioxide, sulphur\_dioxide, ozone, and pollen counts (see SPEC.md for the full list).

## `forecast_days` (type: `integer`):

How many days of hourly/daily forecast to fetch (0–16). 0 means no forecast window — useful only when you want the current block or air quality alone.

## `timezone` (type: `string`):

IANA timezone name (e.g. Europe/Berlin) or "auto" to resolve each location's timezone automatically. Timestamps are normalized to UTC in the output.

## `units` (type: `string`):

Metric (°C, km/h, mm), imperial (°F, mph, inch), or scientific (°C, m/s, mm).

## `max_locations` (type: `integer`):

Hard cap on processed locations — the billing boundary, enforced locally before any request (the upstream accepts more; we never fetch or bill more). One charge event per delivered row.

## `simulate_upstream_failure` (type: `boolean`):

Debug/test hook: forces an upstream-style 5xx failure so the free error path can be verified. Never enable in production.

## `proxyConfiguration` (type: `object`):

Proxy to use for outgoing requests. Open-Meteo is a free public API — the default datacenter proxy works reliably.

## Actor input object example

```json
{
  "locations": [
    {
      "query": "Berlin"
    },
    {
      "query": "Paris"
    },
    {
      "lat": 40.7128,
      "lon": -74.006
    }
  ],
  "current": true,
  "hourly": [
    "temperature_2m",
    "precipitation",
    "wind_speed_10m"
  ],
  "daily": [
    "temperature_2m_max",
    "temperature_2m_min",
    "precipitation_sum"
  ],
  "air_quality": [
    "us_aqi",
    "pm2_5"
  ],
  "forecast_days": 1,
  "timezone": "auto",
  "units": "metric",
  "max_locations": 100,
  "simulate_upstream_failure": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        {
            "query": "Berlin"
        },
        {
            "query": "Paris"
        },
        {
            "lat": 40.7128,
            "lon": -74.006
        }
    ],
    "hourly": [
        "temperature_2m",
        "precipitation",
        "wind_speed_10m"
    ],
    "daily": [
        "temperature_2m_max",
        "temperature_2m_min",
        "precipitation_sum"
    ],
    "air_quality": [
        "us_aqi",
        "pm2_5"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("leorochasantos/weather-data").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": [
        { "query": "Berlin" },
        { "query": "Paris" },
        {
            "lat": 40.7128,
            "lon": -74.006,
        },
    ],
    "hourly": [
        "temperature_2m",
        "precipitation",
        "wind_speed_10m",
    ],
    "daily": [
        "temperature_2m_max",
        "temperature_2m_min",
        "precipitation_sum",
    ],
    "air_quality": [
        "us_aqi",
        "pm2_5",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("leorochasantos/weather-data").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    {
      "query": "Berlin"
    },
    {
      "query": "Paris"
    },
    {
      "lat": 40.7128,
      "lon": -74.006
    }
  ],
  "hourly": [
    "temperature_2m",
    "precipitation",
    "wind_speed_10m"
  ],
  "daily": [
    "temperature_2m_max",
    "temperature_2m_min",
    "precipitation_sum"
  ],
  "air_quality": [
    "us_aqi",
    "pm2_5"
  ]
}' |
apify call leorochasantos/weather-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leorochasantos/weather-data"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/NdkLMPT2w6p2gB8YJ/builds/u1KaYUyzz6at2N4Dm/openapi.json
