# Weather Forecast API (`sfoln/weather-forecast`) Actor

Weather forecast API for any list of place names or coordinates: current conditions, a daily forecast of up to 10 days and optional hourly steps, with temperature, feels-like, rain, wind, UV and sunrise/sunset in local time. MET Norway data. $1 per 1,000 locations.

- **URL**: https://apify.com/sfoln/weather-forecast.md
- **Developed by:** [SFOLN LLC](https://apify.com/sfoln) (community)
- **Categories:** Developer tools, Automation, Travel
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 location forecasts

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Weather Forecast API** returns **current conditions plus a daily forecast of up to 10 days** (and optional hourly steps) for any list of place names or coordinates in one call. Forecasts come from MET Norway, the Norwegian Meteorological Institute (the forecasts behind yr.no), for any point on Earth. Place names are geocoded automatically, and every record is in the location's own time zone with readable conditions ("Light rain showers"), feels-like temperature, UV index and sunrise/sunset. Built for logistics and field-service planning, travel and event apps, agriculture dashboards and AI agents that need a reliable weather answer.

- **What you get:** current conditions; per day the high and low, precipitation sum, strongest wind, the most severe weather, UV index, sunrise and sunset; optional hourly steps (hourly for about 2.5 days, then every 6 hours).
- **Price:** $1 per 1,000 locations (`weather-forecast`), whatever the number of days or hourly data; unknown places and upstream errors are never charged.
- **Works everywhere:** API, MCP for AI agents, Make, Zapier, n8n, schedules and webhooks.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `locations` | array | – | One per line: place name or `latitude,longitude`. API callers may pass objects `{ latitude, longitude, name? }` or `{ place, countryCode? }`. Commas inside a line belong to the location. |
| `days` | integer | 7 | Calendar days to return, today included (1–16 accepted; the forecast reaches about 10 days, so larger values return all 10). |
| `hourly` | boolean | false | Add an `hourly` array with every forecast step. |
| `units` | string | `metric` | `metric` (°C, km/h, mm) or `imperial` (°F, mph, inch). |
| `timezone` | string | `auto` | `auto`: each location's own time zone. Or one IANA zone for all locations, e.g. `UTC` or `Europe/Berlin`. |
| `maxLocations` | integer | 1000 | Safety cap for this run; locations beyond it are ignored and counted as `inputItemsDropped` in the `OUTPUT` record. |
| `concurrency` | integer | 5 | Parallel locations (1–10). |
| `includeRaw` | boolean | false | Attach the raw MET Norway forecast (GeoJSON). |

```json
{
  "locations": ["Berlin", "40.7128,-74.0060", { "latitude": 35.68, "longitude": 139.69, "name": "Tokyo office" }],
  "days": 3,
  "units": "metric"
}
```

### Output

One dataset record per location (`daily` and `hourly` shortened here):

```json
{
  "input": { "kind": "place", "place": "New York" },
  "location": "New York, United States",
  "resolvedPlace": { "name": "New York", "latitude": 40.71427, "longitude": -74.00597, "country": "United States", "countryCode": "US", "admin1": "New York", "timezone": "America/New_York", "elevation": 10, "population": 8804190 },
  "latitude": 40.7128,
  "longitude": -74.006,
  "elevation": 28,
  "timezone": "America/New_York",
  "timezoneAbbreviation": "EDT",
  "utcOffsetSeconds": -14400,
  "timezoneSource": "geocoder",
  "units": { "temperature": "°C", "windSpeed": "km/h", "precipitation": "mm" },
  "current": { "time": "2026-10-14T19:00", "temperature": 23, "apparentTemperature": 23, "dewPoint": 19.7, "relativeHumidity": 81.1, "precipitation": 0, "weatherCode": 2, "symbolCode": "partlycloudy_night", "weatherText": "Partly cloudy", "cloudCover": 71.1, "windSpeed": 16.6, "windDirection": 260.2, "windGusts": null, "pressure": 1011.1, "uvIndexClearSky": 0, "isDay": false },
  "daily": [
    { "date": "2026-10-16", "tempMax": 23.9, "tempMin": 12.7, "precipitationSum": 6.7, "precipitationProbabilityMax": null, "weatherCode": 81, "symbolCode": "rainshowers_day", "weatherText": "Rain showers", "windMax": 21.6, "windGustMax": null, "uvIndexMax": 4.5, "sunrise": "2026-10-16T07:08", "sunset": "2026-10-16T18:14", "hoursCovered": 24 }
  ],
  "hourly": [
    { "time": "2026-10-14T19:00", "periodHours": 1, "temperature": 23, "apparentTemperature": 23, "dewPoint": 19.7, "relativeHumidity": 81.1, "precipitation": 0, "precipitationProbability": null, "weatherCode": 2, "symbolCode": "partlycloudy_night", "weatherText": "Partly cloudy", "windSpeed": 16.6, "windDirection": 260.2, "windGusts": null, "cloudCover": 71.1, "uvIndexClearSky": 0 }
  ],
  "forecastDays": 3,
  "forecastStart": "2026-10-14T19:00",
  "forecastEnd": "2026-10-23T20:00",
  "forecastUpdatedAt": "2026-10-14T19:17:47Z",
  "attribution": "Weather data from MET Norway (api.met.no), CC BY 4.0",
  "status": "ok",
  "charged": true,
  "chargedEvent": "weather-forecast",
  "source": "metno",
  "fetchedAt": "2026-10-14T23:38:02.000Z"
}
```

| Field | Description |
| --- | --- |
| `location`, `resolvedPlace` | Label and geocoding match (null `resolvedPlace` for coordinate inputs). |
| `latitude`, `longitude`, `elevation` | Forecast point (4 decimals) and the altitude its temperatures refer to (the place's elevation when known, else MET Norway's terrain model; a geocoder elevation no place has, such as its "no data" value 9999, is ignored and shown as `null` in `resolvedPlace`). |
| `timezone`, `timezoneAbbreviation`, `utcOffsetSeconds`, `timezoneSource` | All dates and times are wall-clock times of `timezone`: the place's zone (`geocoder`), for coordinates the zone of the nearest populated place (`nearest_place`), or your `timezone` input (`input`). |
| `units` | Unit labels for temperature, wind speed and precipitation. |
| `current` | The current forecast hour: temperature, feels-like (`apparentTemperature`), dew point, humidity, precipitation in the hour, conditions, cloud cover, wind, gusts, sea-level pressure, clear-sky UV index, `isDay`. |
| `daily[]` | `date`, `tempMax`, `tempMin`, `precipitationSum`, `precipitationProbabilityMax`, `weatherCode` + `symbolCode` + `weatherText` (the most severe weather of the day), `windMax`, `windGustMax`, `uvIndexMax`, `sunrise`, `sunset`, `hoursCovered` (forecast hours inside the day: today starts at the current hour). |
| `hourly[]` | Only with `hourly: true`: one entry per forecast step; `periodHours` (1, later 6) is the period its precipitation and conditions cover. |
| `weatherCode`, `symbolCode`, `weatherText` | `symbolCode` is MET Norway's weather icon name, `weatherText` its description, `weatherCode` the equivalent WMO code (0 clear … 3 overcast, 45 fog, 61–65 rain, 71–75 snow, 80–86 showers, 95 thunder). |
| `forecastStart`, `forecastEnd`, `forecastUpdatedAt` | First and last forecast step (local) and when MET Norway last updated the forecast. |
| `attribution` | Data source and licence of the forecast. |

`status` is `ok` for every delivered forecast, `not_found` when a place name cannot be geocoded (not charged), `skipped_invalid` for out-of-range coordinates (not charged), `error` when an upstream call failed (not charged) and `skipped_budget` when your cost cap was reached.

### Pricing

Store discounts: the FREE and BRONZE tiers use the list prices below. SILVER receives 5% off; GOLD, PLATINUM and DIAMOND receive 10% off billable result events. The platform start fee is unchanged. Check the Actor's Store pricing table for the prices currently in effect.

| Event | Price | When charged |
| --- | --- | --- |
| Location forecast (`weather-forecast`) | **$0.001** per location ($1 / 1,000) | once per location with a delivered forecast, regardless of `days` or `hourly` |

Apart from Apify's automatic Actor-start charge ($0.00005 per GB of run memory, a fraction of a cent per run) there is no start fee or subscription. Use **Maximum cost per run** to cap spend; remaining locations are returned as `skipped_budget` and not charged. Accounts on the Apify free plan can process up to 10 locations per run.

### Use with AI agents (MCP)

Use this Actor from Claude, ChatGPT, Cursor, VS Code or any other MCP client through the [Apify MCP server](https://mcp.apify.com). Add this server URL to your client and sign in with your Apify account when asked:

```text
https://mcp.apify.com?tools=sfoln/weather-forecast
```

To run the MCP server locally instead, start `npx -y @apify/actors-mcp-server --tools sfoln/weather-forecast` with your `APIFY_TOKEN` in the environment.

Example prompt:

> What is the 7-day weather forecast for Berlin and New York? Include daily highs, lows and how much rain to expect.

Runs started by an agent are billed like any other run (see Pricing). Agents can cap what a run may spend with `maxTotalChargeUsd`.

### API usage

Run the Actor and get its dataset items in one call (the call waits up to 5 minutes for the run to finish):

```bash
curl -X POST "https://api.apify.com/v2/acts/sfoln~weather-forecast/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"locations": ["Berlin", "40.7128,-74.0060"]}'
```

For large inputs, start the run asynchronously and download the dataset when it has finished:

```bash
## 1. Start a run: the response holds the run ID (data.id) and its dataset ID (data.defaultDatasetId)
curl -X POST "https://api.apify.com/v2/acts/sfoln~weather-forecast/runs" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"locations": ["Berlin", "40.7128,-74.0060"]}'
## 2. Repeat until data.status is SUCCEEDED (each call waits up to 60 s)
curl "https://api.apify.com/v2/actor-runs/<runId>?waitForFinish=60" -H "Authorization: Bearer <APIFY_TOKEN>"
## 3. Download the results (format=json, csv or xlsx)
curl "https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=json" -H "Authorization: Bearer <APIFY_TOKEN>"
```

Python ([apify-client](https://pypi.org/project/apify-client/)):

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("sfoln/weather-forecast").call(run_input={"locations": ["Berlin", "40.7128,-74.0060"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

Instead of polling, you can attach a webhook to the run (see Integrations). The API tab of this page shows the same calls for JavaScript and the Apify CLI.

### Integrations

- **Make, Zapier and n8n:** run `sfoln/weather-forecast` with the Apify app (in n8n, the Apify node) and pass the dataset items to the next step of your workflow.
- **Google Sheets:** add the items to a sheet with the Google Sheets step of Make, Zapier or n8n, or download them as CSV or Excel from the run's Storage tab or the API (`format=csv` or `format=xlsx`).
- **Webhooks:** get a POST request when a run succeeds or fails: add a webhook in the Actor's Integrations tab, or pass `webhooks` when you start a run through the API.
- **Schedules:** run it hourly, daily or weekly with the same input from Apify Schedules; every run keeps its results in its own dataset.
- **More:** Slack, Google Drive, GitHub, LangChain, LlamaIndex and other [Apify integrations](https://docs.apify.com/platform/integrations).

### Related Actors

- [Historical Weather Data API](https://apify.com/sfoln/historical-weather)
- [Geocoding API – Address to Coordinates](https://apify.com/sfoln/geocode-address)
- [Currency Exchange Rates API](https://apify.com/sfoln/fx-rates)

See [all our Actors](https://apify.com/sfoln) on Apify Store.

### FAQ

#### How much does it cost, and am I charged for failed items?

You pay per event at the prices under Pricing above, plus a run start fee of $0.00005 per GB of memory, with no subscription; platform usage is included. Errors and skipped items (`skipped_…` statuses) are never charged; a lookup that finds nothing is charged only where Pricing says so, and every record's `charged` field shows whether it was billed. Set **Maximum cost per run** to cap what a single run can spend.

#### How fresh is the data?

Each run queries its source while it runs, so you get what the source returns at that moment. Source-specific details, such as how often a provider refreshes its own database, are under Limits & notes.

#### What are the limits?

Per-run caps (for example the maximum number of items) are listed under Input, source limits under Limits & notes, and the free-plan limit under Pricing. For big batches, start the run asynchronously (see API usage) and read the dataset when it has finished.

#### Can I schedule runs or get results by webhook?

Yes. Create a schedule in Apify Console to run it hourly, daily or weekly with the same input, and add a webhook to get a POST request when a run finishes (see Integrations).

#### What does this Actor record about my runs?

This Actor records operational metrics about each run (item counts, duration, charges, error codes and a pseudonymous hash of your Apify user ID) to monitor reliability and costs. It never stores your input or results.

#### How far ahead does the forecast go?

About 10 days: hourly steps for roughly the first 2.5 days, then 6-hour steps. Ask for up to 10 days; larger values return the whole forecast.

#### Which time zone are the dates and times in?

The location's own time zone by default (from the place name, or for coordinates the zone of the nearest populated place). Set timezone to UTC or any IANA zone to use that instead.

#### How do I get help?

Open an issue in the Actor's Issues tab and include the link to the run, so we can reproduce the problem. Feature requests are welcome there too.

### Limits & notes

- **Horizon:** about 9–10 days ahead (MET Norway Locationforecast 2.0): hourly steps for roughly the first 2.5 days, then 6-hour steps. `days` above 10 return the whole forecast. Use the `historical-weather` Actor for past days.
- Today's daily values cover the remaining hours of the day (`hoursCovered`); the last day ends with the forecast.
- Precipitation probability and wind gusts exist only in MET Norway's Nordic high-resolution area; elsewhere they are `null`.
- Forecasts are model output that MET Norway updates several times a day (`forecastUpdatedAt`). Repeated points in one run are served from the forecast's own cache lifetime.
- Times are local wall-clock times without an offset (`timezone` and `utcOffsetSeconds` say which zone). For coordinates the zone is that of the nearest populated place, which can be off right at a time-zone border or in sparsely populated areas (a record whose nearest known place is more than 250 km away carries a warning): set `timezone` to be explicit.
- Place names resolve to the best Open-Meteo geocoding match (cities, towns, postal codes). For ambiguous names add the region or country after a comma (`"Springfield, Illinois"`, `"Paris, Texas"`, `"Paris, FR"`) or pass coordinates. The part after the comma must name the region or country in whole words (or the 2-letter country code); when no match is in that region or country, the top match is used and the record carries a warning.
- Up to 10,000 locations per run, at most 5 forecast requests per second per run (MET Norway's limit is shared by every run of this Actor).
- When MET Norway refuses requests (HTTP 403), the run stops with a clear message instead of failing every location; try again later.

# Actor input Schema

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

One per line: a place name ("Berlin", "Paris, France") or "latitude,longitude" ("40.7128,-74.0060"). Via the API you can also pass objects like {"latitude": 52.52, "longitude": 13.41, "name": "Office"} or {"place": "Springfield", "countryCode": "US"}. Accounts on the Apify free plan can process up to 10 locations per run.

## `days` (type: `integer`):

Calendar days to return, today included. The forecast reaches about 10 days ahead, so values above 10 return the whole forecast (10 days).

## `hourly` (type: `boolean`):

Add an `hourly` array: one entry per forecast step (hourly for about the first 2.5 days, then every 6 hours) with temperature, feels-like, humidity, precipitation, conditions and wind.

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

metric = °C, km/h, mm · imperial = °F, mph, inch.

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

auto (default) = each location's own time zone: days and times are local there. Or one IANA time zone for every location, e.g. UTC or Europe/Berlin.

## `maxLocations` (type: `integer`):

Safety cap on how many locations are processed in this run.

## `concurrency` (type: `integer`):

How many locations are processed in parallel.

## `includeRaw` (type: `boolean`):

Attach the unmodified MET Norway forecast (GeoJSON) to each record (larger output).

## Actor input object example

```json
{
  "locations": [
    "Berlin",
    "40.7128,-74.0060"
  ],
  "days": 7,
  "hourly": false,
  "units": "metric",
  "timezone": "auto",
  "maxLocations": 1000,
  "concurrency": 5,
  "includeRaw": false
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "Berlin",
        "40.7128,-74.0060"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sfoln/weather-forecast").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": [
        "Berlin",
        "40.7128,-74.0060",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sfoln/weather-forecast").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": [
    "Berlin",
    "40.7128,-74.0060"
  ]
}' |
apify call sfoln/weather-forecast --silent --output-dataset

```

## MCP server setup

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

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/MlG5XnUNMGoe9PrbP/builds/hkdDNCSjA6Aq3LSxp/openapi.json
