# Weather Forecast API - MET Norway (Yr), Hourly & Daily (`far003/weather-forecast-met-norway`) Actor

Official MET Norway (Yr) weather forecast for any coordinates worldwide: hourly steps, daily min/max, rain and wind, local time. No API key. Your results are cached until the source's own expiry. Rows ready for spreadsheets.

- **URL**: https://apify.com/far003/weather-forecast-met-norway.md
- **Developed by:** [Francesco Antonio Russo](https://apify.com/far003) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.80 / 1,000 place forecasts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 — MET Norway (Yr) hourly and daily forecast for any coordinates

Give it a list of places (latitude and longitude) and get back the official **MET Norway Locationforecast 2.0** forecast for each one: hourly steps, daily minimum and maximum temperature, rain, wind, humidity, cloud cover and a plain-English weather summary. Worldwide, no API key, and every place comes with its **local time** and a ready **daily summary** that tells you honestly when a day is only partly covered.

MET Norway is the national weather service of Norway; this is the same free data that powers the Yr forecasts. The Actor follows MET Norway's terms of service (identifying User-Agent, coordinates cut to 4 decimals, no request before the `Expires` time, 429/203 handling) and puts the required credit in **every record**.

### Who it is for

- **Developers and data teams** who need a clean weather feed for a list of sites without writing and babysitting a client for the MET Norway API.
- **Energy, agriculture, construction, events and logistics teams** that check tomorrow's rain, wind and temperature for many sites every morning and want them in a spreadsheet (`outputMode: "day"`).
- **Anyone building dashboards, alerts or AI agents** that need a dependable forecast for coordinates, with units and time zones stated in the data.

### What you get

For every place you choose one of three layouts. All of them cost the same (one charge per place) and carry the same place fields, the units and the attribution:

| Layout (`outputMode`) | What a row is | Best for |
|---|---|---|
| `location` (default) | one record per place, with the daily summaries in `days` and the time steps in `steps` | APIs, apps, agents |
| `day` | one flat row per place and day: min/max temperature, rain, wind, summary | spreadsheets, daily reports |
| `step` | one flat row per place and time step: temperature, wind, humidity, rain, symbol | charts, hourly analysis |

Anything the source does not give is `null`. Nothing is guessed, and the weather text for a symbol code the Actor does not know is `null` instead of an invention.

#### Real example: one record per place

Run on 19 October 2026, Oslo, `forecastDays: 3` (`days` cut to its first day and `steps` to its first two entries for this page; the full record has all 3 days and 54 steps, as `dayCount` and `stepCount` say):

```json
{
  "id": "59.9139,10.7522",
  "name": "Oslo",
  "latitude": 59.9139,
  "longitude": 10.7522,
  "coordinatesTruncated": false,
  "elevationMeters": 5,
  "elevationSource": "source-model",
  "timeZone": "Europe/Oslo",
  "timeZoneSource": "tz-lookup",
  "dayBasis": "local",
  "status": "ok",
  "error": null,
  "notice": null,
  "forecastUpdatedAt": "2026-10-19T12:30:07Z",
  "expiresAt": "2026-10-19T13:39:31.000Z",
  "fetchedAt": "2026-10-19T13:25:02.609Z",
  "dataSource": "network",
  "units": {
    "temperature": "°C",
    "windSpeed": "km/h",
    "precipitation": "mm",
    "pressure": "hPa",
    "humidity": "%",
    "cloudCover": "%",
    "fogFraction": "%",
    "windDirection": "degrees",
    "uvIndexClearSky": "index"
  },
  "sourceUrl": "https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=59.9139&lon=10.7522",
  "attribution": "Based on data from MET Norway (The Norwegian Meteorological Institute), https://api.met.no/, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes were made: values converted to the chosen units, daily summaries and local times added.",
  "stepCount": 54,
  "dayCount": 3,
  "days": [
    {
      "date": "2026-10-19",
      "weekday": "Mon",
      "partial": true,
      "hoursCovered": 9,
      "precipitationExact": true,
      "temperatureMin": 5.3,
      "temperatureMax": 9.2,
      "precipitationTotal": 0,
      "windSpeedMax": 4,
      "uvIndexClearSkyMax": null,
      "symbol": "fair",
      "summary": "Fair"
    }
  ],
  "steps": [
    {
      "time": "2026-10-19T13:00:00Z",
      "localTime": "2026-10-19T15:00:00+02:00",
      "localDate": "2026-10-19",
      "stepHours": 1,
      "temperature": 8.2,
      "temperatureMin": null,
      "temperatureMax": null,
      "apparentTemperature": null,
      "dewPoint": null,
      "humidity": 87,
      "pressure": 1037,
      "cloudCover": 13.6,
      "cloudCoverLow": null,
      "cloudCoverMedium": null,
      "cloudCoverHigh": null,
      "fogFraction": null,
      "windSpeed": 3.6,
      "windDirection": 332,
      "uvIndexClearSky": null,
      "precipitation": 0,
      "symbol": "fair_day",
      "summary": "Fair"
    },
    {
      "time": "2026-10-19T14:00:00Z",
      "localTime": "2026-10-19T16:00:00+02:00",
      "localDate": "2026-10-19",
      "stepHours": 1,
      "temperature": 9.2,
      "temperatureMin": null,
      "temperatureMax": null,
      "apparentTemperature": null,
      "dewPoint": null,
      "humidity": 83.5,
      "pressure": 1036.6,
      "cloudCover": 9,
      "cloudCoverLow": null,
      "cloudCoverMedium": null,
      "cloudCoverHigh": null,
      "fogFraction": null,
      "windSpeed": 1.4,
      "windDirection": 294,
      "uvIndexClearSky": null,
      "precipitation": 0,
      "symbol": "clearsky_day",
      "summary": "Clear sky"
    }
  ]
}
```

#### Real example: a daily row (`outputMode: "day"`)

Tromsø, run on 19 October 2026. The forecast after the first two and a half days is given by the source in 6-hour blocks fixed to UTC hours, so in a zone that is not a multiple of 6 hours from UTC the rain total of a later day can include a block that crosses midnight: `precipitationExact` is then `false` (here it is `true` for 20 October and `false` from 21 October).

```json
{
  "id": "69.6492,18.9553",
  "name": "Tromso",
  "latitude": 69.6492,
  "longitude": 18.9553,
  "date": "2026-10-20",
  "weekday": "Tue",
  "partial": false,
  "hoursCovered": 24,
  "precipitationExact": true,
  "temperatureMin": 6.5,
  "temperatureMax": 11.2,
  "precipitationTotal": 7.7,
  "windSpeedMax": 41.4,
  "uvIndexClearSkyMax": null,
  "symbol": "cloudy",
  "summary": "Cloudy",
  "coordinatesTruncated": false,
  "elevationMeters": 7,
  "elevationSource": "source-model",
  "timeZone": "Europe/Oslo",
  "timeZoneSource": "tz-lookup",
  "dayBasis": "local",
  "status": "ok",
  "error": null,
  "notice": null,
  "forecastUpdatedAt": "2026-10-19T12:30:06Z",
  "expiresAt": "2026-10-19T13:27:08.000Z",
  "fetchedAt": "2026-10-19T13:24:32.326Z",
  "dataSource": "network",
  "units": {
    "temperature": "°C",
    "windSpeed": "km/h",
    "precipitation": "mm",
    "pressure": "hPa",
    "humidity": "%",
    "cloudCover": "%",
    "fogFraction": "%",
    "windDirection": "degrees",
    "uvIndexClearSky": "index"
  },
  "sourceUrl": "https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=69.6492&lon=18.9553",
  "attribution": "Based on data from MET Norway (The Norwegian Meteorological Institute), https://api.met.no/, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes were made: values converted to the chosen units, daily summaries and local times added."
}
```

#### Real example: a time-step row (`outputMode: "step"`)

Phoenix (no daylight saving, UTC-7), with the extended fields off, so those stay `null`:

```json
{
  "id": "33.4484,-112.0740",
  "name": "Phoenix",
  "latitude": 33.4484,
  "longitude": -112.074,
  "time": "2026-10-19T13:00:00Z",
  "localTime": "2026-10-19T06:00:00-07:00",
  "localDate": "2026-10-19",
  "stepHours": 1,
  "temperature": 19,
  "temperatureMin": null,
  "temperatureMax": null,
  "apparentTemperature": null,
  "dewPoint": null,
  "humidity": 59.2,
  "pressure": 1014.5,
  "cloudCover": 13.3,
  "cloudCoverLow": null,
  "cloudCoverMedium": null,
  "cloudCoverHigh": null,
  "fogFraction": null,
  "windSpeed": 7.6,
  "windDirection": 107.8,
  "uvIndexClearSky": null,
  "precipitation": 0,
  "symbol": "fair_night",
  "summary": "Fair",
  "coordinatesTruncated": false,
  "elevationMeters": 333,
  "elevationSource": "source-model",
  "timeZone": "America/Phoenix",
  "timeZoneSource": "tz-lookup",
  "dayBasis": "local",
  "status": "ok",
  "error": null,
  "notice": null,
  "forecastUpdatedAt": "2026-10-19T11:26:47Z",
  "expiresAt": "2026-10-19T13:51:18.000Z",
  "fetchedAt": "2026-10-19T13:25:01.584Z",
  "dataSource": "network",
  "units": {
    "temperature": "°C",
    "windSpeed": "km/h",
    "precipitation": "mm",
    "pressure": "hPa",
    "humidity": "%",
    "cloudCover": "%",
    "fogFraction": "%",
    "windDirection": "degrees",
    "uvIndexClearSky": "index"
  },
  "sourceUrl": "https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=33.4484&lon=-112.0740",
  "attribution": "Based on data from MET Norway (The Norwegian Meteorological Institute), https://api.met.no/, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes were made: values converted to the chosen units, daily summaries and local times added."
}
```

#### What an error row looks like

A place that cannot be read is still one row, so you can see which one failed. It is free. This is what the Actor writes when the source answers 404 (generated locally from the Actor's own code, not from a real outage):

```json
{
  "id": "12.3456,65.4321",
  "name": "Nowhere",
  "latitude": 12.3456,
  "longitude": 65.4321,
  "coordinatesTruncated": false,
  "elevationMeters": null,
  "elevationSource": null,
  "timeZone": "Asia/Dubai",
  "timeZoneSource": null,
  "dayBasis": "utc",
  "status": "error",
  "error": "HTTP 404: Not Found",
  "notice": null,
  "forecastUpdatedAt": null,
  "expiresAt": null,
  "fetchedAt": null,
  "dataSource": null,
  "units": {
    "temperature": "°C",
    "windSpeed": "km/h",
    "precipitation": "mm",
    "pressure": "hPa",
    "humidity": "%",
    "cloudCover": "%",
    "fogFraction": "%",
    "windDirection": "degrees",
    "uvIndexClearSky": "index"
  },
  "sourceUrl": "https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=12.3456&lon=65.4321",
  "attribution": "Based on data from MET Norway (The Norwegian Meteorological Institute), https://api.met.no/, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes were made: values converted to the chosen units, daily summaries and local times added.",
  "stepCount": null,
  "dayCount": null,
  "days": null,
  "steps": null
}
```

### How to use it

#### Input

1. **`locations`**: the places. Each is an object `{"name": "Oslo", "latitude": 59.9139, "longitude": 10.7522}` (optional `altitude` in metres and `timeZone` such as `Europe/Oslo`) or the text `"latitude, longitude"` or `"Name: latitude, longitude"`. A dot is the decimal separator. Up to 10,000 places per run; repeated places are merged and charged once.
2. **`forecastDays`**: 1 to 10 local calendar days, today included. Default 3. MET Norway forecasts about 9 to 10 days ahead, so asking for 10 can return 9 or 10.
3. **`outputMode`**: `location`, `day` or `step`, as above.
4. **`timeStep`**: `hourly` (every step the source gives: 1 hour apart for roughly the first 2.5 days, then 6 hours apart, each step says its `stepHours`) or `six-hourly` (only 00, 06, 12 and 18 UTC, each with the 6-hour rain, minimum and maximum).
5. **`units`**: `metric` (°C, km/h, mm, hPa), `imperial` (°F, mph, inches, inHg) or `source` (as MET Norway delivers: °C, m/s, mm, hPa). The unit of every value is written in the row's `units`.
6. **`includeDaily`** and **`includeSteps`**: with the `location` layout, leave out `days` or `steps` (they become `null`). Switching `includeSteps` off makes records about 10 times smaller.
7. **`includeExtendedFields`**: adds feels-like temperature, dew point, low/medium/high cloud cover, fog and the clear-sky UV index. MET Norway gives them for part of the horizon (fog and UV for the first days), otherwise they stay `null`.
8. **`useCache`**: on by default. See "Be kind to the source" below.

Minimal input:

```json
{
  "locations": [
    {
      "name": "Oslo",
      "latitude": 59.9139,
      "longitude": 10.7522
    },
    "Milan: 45.4642, 9.19",
    "-33.8688, 151.2093"
  ],
  "forecastDays": 3,
  "outputMode": "day",
  "units": "metric"
}
```

#### Output

A `location` record has the same 24 fields in every run, a `day` row the same 32 fields, a `step` row the same 42 fields; the key order is fixed. The place and source fields, in every layout:

| Field | Type | What it is |
|---|---|---|
| `id` | string | Stable key of the place: the coordinates as sent to the source (4 decimals), plus "@altitude" when you gave an altitude. Use it as the key when you join runs or modes. Repeated in every row of a place. |
| `name` | string / null | The name you gave the place, cleaned of line breaks. Null when you gave none. The Actor never looks names up. |
| `latitude` | number | Latitude used for the forecast, in decimal degrees, cut (not rounded) to 4 decimals as MET Norway requires. |
| `longitude` | number | Longitude used for the forecast, in decimal degrees, cut (not rounded) to 4 decimals as MET Norway requires. |
| `coordinatesTruncated` | boolean | True when you gave more than 4 decimals and they were cut to 4 (about 11 m). The forecast is for the cut point. |
| `elevationMeters` | number / null | Ground elevation the forecast was computed for: your altitude if you gave one, else the height MET Norway's own terrain model uses for that point. Null if the source does not say. |
| `elevationSource` | string / null | "input" when it is the altitude you gave, "source-model" when MET Norway chose it, null when unknown. |
| `timeZone` | string / null | IANA time zone of the place (Europe/Oslo): the one you gave, else looked up offline from the coordinates. Null when none could be found: then days are UTC days and local times are null. |
| `timeZoneSource` | string / null | "input" (you gave it), "tz-lookup" (offline lookup from the coordinates: approximate within a few km of a zone border), or null. |
| `dayBasis` | string | "local" when days follow the place's local calendar day, "utc" when no time zone is known. |
| `status` | string | "ok" = the forecast was read and is in this record; "error" = it could not be read (see `error`). Error records are free. |
| `error` | string / null | Why the forecast could not be read, in plain words. Null when status is "ok". |
| `notice` | string / null | Something the source said that you should know, for example that MET Norway marks the product deprecated (HTTP 203). Null normally. |
| `forecastUpdatedAt` | string / null | When MET Norway last updated the model run behind this forecast (meta.updated_at), ISO 8601 UTC. |
| `expiresAt` | string / null | The source's Expires time: a newer forecast is not available before it. ISO 8601 UTC. |
| `fetchedAt` | string / null | When this Actor last asked MET Norway for this place (it can be earlier than the run when the stored answer was still valid). |
| `dataSource` | string / null | "network" = read from MET Norway in this run; "cache" = a stored answer that had not expired yet (no request was made); "revalidated" = asked with If-Modified-Since and the source said nothing changed. |
| `units` | object | The unit of every measured value in this row, so a row can be read on its own. Keys: temperature, windSpeed, precipitation, pressure, humidity, cloudCover, fogFraction, windDirection, uvIndexClearSky. |
| `sourceUrl` | string / null | The exact MET Norway request this forecast comes from (public, no key). |
| `attribution` | string | The credit CC BY 4.0 requires. Keep it when you publish or redistribute the data. |

Extra fields of the `location` layout:

| Field | Type | What it is |
|---|---|---|
| `stepCount` | number / null | Number of entries in `steps`. Null when `steps` is null (includeSteps off) or the place failed. |
| `dayCount` | number / null | Number of entries in `days`. Null when `days` is null (includeDaily off) or the place failed. |
| `days` | array / null | Daily summaries, one object per day with the fields of the daily rows (date, weekday, partial, hoursCovered, precipitationExact, temperatureMin, temperatureMax, precipitationTotal, windSpeedMax, uvIndexClearSkyMax, symbol, summary). Null when includeDaily is off or the place failed. |
| `steps` | array / null | Forecast steps, one object per time step with the fields of the step rows (time, localTime, localDate, stepHours, temperature, ...). Null when includeSteps is off or the place failed. |

Fields of a `day` row, and of each entry of `days`:

| Field | Type | What it is |
|---|---|---|
| `date` | string / null | The calendar day (YYYY-MM-DD) in the place's time zone, or in UTC when dayBasis is "utc". Null in an error row. |
| `weekday` | string / null | Mon, Tue, Wed, Thu, Fri, Sat or Sun. |
| `partial` | boolean / null | True when the forecast covers less than a full day: the first day starts at the current hour, the last day may be cut by the end of the source's horizon. Extremes and totals then cover only the covered hours. |
| `hoursCovered` | number / null | Hours of this day that have a forecast value for precipitation (24 for a whole day, 23 or 25 on a daylight-saving change). |
| `precipitationExact` | boolean / null | True when every forecast block behind `precipitationTotal` lies inside this day. After about 2.5 days MET Norway only gives 6-hour blocks fixed to UTC hours (00, 06, 12, 18); in a zone that is not a multiple of 6 hours from UTC a block can cross local midnight. It is then counted in the day it starts in, never split, and this is false. |
| `temperatureMin` | number / null | Day rows: lowest of the forecast temperatures at the steps of the day and of the 6-hour minimums that lie inside the day. Step rows: the 6-hour minimum for 6-hour steps, null for 1-hour steps. |
| `temperatureMax` | number / null | Day rows: highest of the forecast temperatures at the steps of the day and of the 6-hour maximums that lie inside the day. Step rows: the 6-hour maximum for 6-hour steps, null for 1-hour steps. |
| `precipitationTotal` | number / null | Sum of the forecast precipitation of the blocks that start in this day (rain, melted snow). Null when the source gave none for the day. |
| `windSpeedMax` | number / null | Highest forecast wind speed (10 m, mean wind, not gusts) at the steps of the day. After the first 2.5 days steps are 6 hours apart, so a short peak can be missed. |
| `uvIndexClearSkyMax` | number / null | Highest clear-sky UV index at the steps of the day. Only with includeExtendedFields; null otherwise or when the source has none (night). |
| `symbol` | string / null | MET Norway weather symbol code for the step, for example "clearsky_day" or "lightrain". Day rows: the most frequent symbol of the day without the \_day/\_night suffix, ties go to the worse weather. |
| `summary` | string / null | English text of the symbol ("Clear sky", "Light rain showers and thunder"). Null for a code this Actor does not know: the code is never guessed. |

Fields of a `step` row, and of each entry of `steps`:

| Field | Type | What it is |
|---|---|---|
| `time` | string / null | Start of the step, ISO 8601 UTC, exactly as the source gives it. Null in an error row. |
| `localTime` | string / null | The same instant in the place's time zone with its UTC offset, for example 2026-10-19T14:00:00+02:00. Null when no time zone is known. |
| `localDate` | string / null | Calendar day of the step in the place's time zone (matches `date` in the daily rows). Null when no time zone is known. |
| `stepHours` | number / null | How many hours the precipitation and symbol of the step cover: 1 for the first 2.5 days or so, then 6. Null for the very last step, which only carries instant values. |
| `temperature` | number / null | Air temperature at 2 m at the start of the step. |
| `temperatureMin` | number / null | Day rows: lowest of the forecast temperatures at the steps of the day and of the 6-hour minimums that lie inside the day. Step rows: the 6-hour minimum for 6-hour steps, null for 1-hour steps. |
| `temperatureMax` | number / null | Day rows: highest of the forecast temperatures at the steps of the day and of the 6-hour maximums that lie inside the day. Step rows: the 6-hour maximum for 6-hour steps, null for 1-hour steps. |
| `apparentTemperature` | number / null | Feels-like temperature, as computed by MET Norway. Only with includeExtendedFields. |
| `dewPoint` | number / null | Dew point temperature. Only with includeExtendedFields. |
| `humidity` | number / null | Relative humidity at 2 m, percent. |
| `pressure` | number / null | Air pressure at sea level. |
| `cloudCover` | number / null | Total cloud cover, percent of the sky. |
| `cloudCoverLow` | number / null | Low-level cloud cover, percent. Only with includeExtendedFields. |
| `cloudCoverMedium` | number / null | Mid-level cloud cover, percent. Only with includeExtendedFields. |
| `cloudCoverHigh` | number / null | High-level cloud cover, percent. Only with includeExtendedFields. |
| `fogFraction` | number / null | Fog area fraction, percent. Only with includeExtendedFields; MET Norway gives it for the first days only. |
| `windSpeed` | number / null | Mean wind speed at 10 m (gusts are not in this product). |
| `windDirection` | number / null | Direction the wind blows FROM, in degrees: 0 = north, 90 = east, 180 = south, 270 = west. |
| `uvIndexClearSky` | number / null | UV index for a cloudless sky (real UV is lower under cloud). Only with includeExtendedFields; null at night and beyond the first days. |
| `precipitation` | number / null | Precipitation (rain, melted snow) over the step, in the unit of `units.precipitation`, for `stepHours` hours. Null for the last step. |
| `symbol` | string / null | MET Norway weather symbol code for the step, for example "clearsky_day" or "lightrain". Day rows: the most frequent symbol of the day without the \_day/\_night suffix, ties go to the worse weather. |
| `summary` | string / null | English text of the symbol ("Clear sky", "Light rain showers and thunder"). Null for a code this Actor does not know: the code is never guessed. |

Also stored: a `SUMMARY` record in the key-value store with the settings used, the totals, the number of requests, cache hits, retries, the places that failed and why, the places not read if the run stopped, and the attribution.

### How the daily numbers are worked out

- A **day** is a local calendar day of the place (midnight to midnight in its time zone), or a UTC day when no time zone is known (`dayBasis`).
- **`temperatureMin` / `temperatureMax`**: lowest and highest of the forecast temperatures at the steps of the day, together with the 6-hour minimum and maximum the source gives for each 6-hour block that lies entirely inside the day.
- **`precipitationTotal`**: the sum of the source's precipitation blocks that *start* in the day (1-hour blocks first, 6-hour blocks later). A block is never split. When a 6-hour block crosses local midnight, `precipitationExact` is `false`.
- **`windSpeedMax`**: the highest forecast mean wind at the day's steps. Gusts are not part of this product, and after the first 2.5 days steps are 6 hours apart, so a short peak can be missed.
- **`symbol` / `summary`**: the most frequent weather symbol of the day, weighted by hours, day and night variants merged; if two are equally frequent the worse weather wins.
- **`partial`, `hoursCovered`**: the first day starts at the current hour and the last day may be cut by the source's horizon, so a day can cover less than 24 hours. `hoursCovered` counts the hours of that day with a precipitation value (23 or 25 on a daylight-saving change). Never compare a partial day's minimum with a full day's without looking at it.
- **Time zone**: from the `timeZone` you give, else looked up *offline* from the coordinates with the CC0 `tz-lookup` polygon table, then the real UTC offset (including daylight saving) from Node's time zone database. Near a zone border (a few km) the lookup can pick the neighbour: give `timeZone` for places where this matters. Open-sea points get a nautical zone such as `Etc/GMT+2`. If no zone is found, days are UTC days, local times are `null` and `notice` says so.
- **Units** are converted from the source's °C, m/s, mm and hPa: °F = °C × 9/5 + 32, km/h = m/s × 3.6, mph = m/s × 2.2369, inches = mm / 25.4, inHg = hPa × 0.02953.

### How much does it cost?

One event, **`forecast`: $0.0008 per place whose forecast is delivered ($0.80 per 1,000 places)**. Platform usage is included. You are charged once per place whatever the layout, the number of days or the rows it produces, and also when the answer came from the stored copy (you pay for the forecast delivered, not for the request).

**Free:** places that fail, invalid or repeated entries in your list, anything not read because the run stopped. The Actor stops by itself when your **maximum cost per run** is reached ("budget exhausted" in the `SUMMARY`) and never goes one place over.

| Use | Forecasts | Cost |
|---|---|---|
| 50 sites, once a day, for a month | 1,500 | $1.20 |
| 200 sites, every 6 hours, for a month | 24,000 | $19.20 |
| 5,000 grid points, once | 5,000 | $4.00 |

Speed: about 3 places per second (one request every 0.3 seconds, on purpose), so 1,000 places take about 5 to 6 minutes on the default 256 MB.

### Be kind to the source (and keep the cost of reruns low)

MET Norway is a free public service. It asks clients not to repeat a request before the `Expires` time of the previous answer, and to use `If-Modified-Since`. With `useCache` on (default), each answer is kept in a key-value store named `met-norway-forecast-cache` in your account (compressed, about 7 KB per place, up to 5,000 places): a place whose stored answer has not expired is served from it with no request (`dataSource: "cache"`); an expired one is asked again with `If-Modified-Since` and a "not modified" answer (`"revalidated"`) just extends it. MET Norway sets `Expires` only some minutes ahead (we saw about 17), so the stored copy mostly helps reruns within minutes: retries, the same list in another layout, overlapping lists. Delete the store whenever you like.

### Limits to know

- **Coordinates only.** Place names are not looked up. Free geocoding services either limit commercial use to paid keys (Open-Meteo's geocoding) or ask for no bulk use and at most 1 request a second (OpenStreetMap's Nominatim), so the Actor does not guess which "Springfield" you meant. Put the name you want back in `name`.
- **Forecast, not observation.** No history, no measured data, no weather warnings, no sunrise or sunset, no probability of precipitation, no gusts.
- **Model point.** The forecast is for the point at the terrain height of MET Norway's model unless you give `altitude`. In mountains, give it.
- **Horizon** about 9 to 10 days; the long range is 6-hourly and less certain. Not for safety-critical decisions.
- **Up to 10,000 places a run**, 4 attempts per place, each request cut at 30 seconds, answers over 8 MB refused. If the source answers 429 (too many requests) three times in a row, the run stops by itself and lists the places not read.

### FAQ

**Is this allowed? Is the data free to use commercially?** MET Norway licenses its data under CC BY 4.0 and the Norwegian Licence for Open Government Data (NLOD) 2.0 (https://api.met.no/doc/License). Credit is required: it is in the `attribution` field of every row. Keep it if you publish or pass on the data. The terms of service (https://api.met.no/doc/TermsOfService) require an identifying User-Agent, coordinates with at most 4 decimals, respect for `Expires`, and a rate under 20 requests a second for an application: this Actor sends `weather-forecast-met-norway/<version> (+https://github.com/FarGitub003)`, cuts coordinates (`coordinatesTruncated`), uses one request at a time with 0.3 s between, and logs a 203 ("product deprecated") as a warning and in `notice`.

**Why is the first day "partial"?** It starts at the current hour, and its numbers cover only the hours left. `hoursCovered` and `partial` tell you.

**Why are some `precipitationExact` false?** See above: the source's later 6-hour blocks are tied to UTC hours.

**Can I give a city name?** No, see "Limits". Use a geocoder you have a licence for, and pass the coordinates and the name.

**Which time zone do you use for my place?** The one in the row (`timeZone`, `timeZoneSource`).

**Do you keep my places?** Only the answers in your own `met-norway-forecast-cache` store, keyed by the coordinates. Nothing is sent anywhere but to api.met.no.

### Use it from code

Replace `YOUR_TOKEN`. The Actor is called `far003/weather-forecast-met-norway`.

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('far003/weather-forecast-met-norway').call({
    locations: [
        { name: 'Oslo', latitude: 59.9139, longitude: 10.7522 },
        'Milan: 45.4642, 9.19',
    ],
    outputMode: 'day',
    forecastDays: 5,
    units: 'metric',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const day of items) console.log(day.name, day.date, day.temperatureMin, day.temperatureMax, day.precipitationTotal, day.summary);
```

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("far003/weather-forecast-met-norway").call(run_input={
    "locations": [
        {"name": "Oslo", "latitude": 59.9139, "longitude": 10.7522},
        "Milan: 45.4642, 9.19",
    ],
    "outputMode": "day",
    "forecastDays": 5,
    "units": "metric",
})
for day in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(day["name"], day["date"], day["temperatureMin"], day["temperatureMax"], day["precipitationTotal"], day["summary"])
```

**Schedule.** In Apify, add a Schedule for the Actor (for example every morning) and a webhook or integration (Slack, e-mail, Make, Zapier, Google Sheets) on *Run succeeded*. In `day` layout the dataset opens as a table, ready for a spreadsheet export.

### Attribution

Based on data from MET Norway (The Norwegian Meteorological Institute), https://api.met.no/, licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes were made: values converted to the chosen units, daily summaries and local times added.

The forecast data is from the Norwegian Meteorological Institute (MET Norway), https://api.met.no/ — Locationforecast 2.0. The weather symbol codes are MET Norway's; this Actor ships no icons. This Actor is not affiliated with, or endorsed by, MET Norway or Yr (NRK and MET Norway). Forecasts are provided as they are, without warranty.

# Actor input Schema

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

The places to forecast, by coordinates. Each entry is either an object {"name": "Oslo", "latitude": 59.9139, "longitude": 10.7522} (optional "altitude" in metres and optional "timeZone" such as "Europe/Oslo") or the text "latitude, longitude" / "Name: latitude, longitude". Use a dot as decimal separator. Coordinates are cut to 4 decimals (about 11 m), as the source requires. The Actor does not look up city names: it never guesses which "Springfield" you meant. Duplicates are merged and charged once; up to 10,000 places per run.

## `forecastDays` (type: `integer`):

How many local calendar days to return, counting today (the day of the current hour). MET Norway forecasts about 9 to 10 days ahead; if the source ends sooner you get fewer days. Today is usually a partial day: its rows say so (`partial`, `hoursCovered`).

## `outputMode` (type: `string`):

location = one record per place with the daily summaries (`days`) and the time steps (`steps`) inside it. day = one flat row per place and day (min/max temperature, rain, wind), ready for a spreadsheet. step = one flat row per place and time step (hourly, then 6-hourly). Every layout costs the same: one charge per place.

## `timeStep` (type: `string`):

hourly = every step the source gives: 1 hour apart for roughly the first 2.5 days, then 6 hours apart (each step says its `stepHours`). six-hourly = only the steps at 00, 06, 12 and 18 UTC, each with its 6-hour precipitation, minimum and maximum. Used by the `steps` and the step rows.

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

metric = °C, km/h, mm, hPa. imperial = °F, mph, inches, inHg. source = exactly as MET Norway delivers: °C, m/s, mm, hPa. Every record carries its `units`.

## `includeDaily` (type: `boolean`):

Only for the "one record per place" layout: add `days`. Turn off to get only the time steps.

## `includeSteps` (type: `boolean`):

Only for the "one record per place" layout: add `steps`. Turn off to get only the daily summaries (about 10 times smaller).

## `includeExtendedFields` (type: `boolean`):

Add apparent (feels-like) temperature, dew point, low/medium/high cloud cover, fog and clear-sky UV index. They exist in MET Norway's detailed product only, for part of the horizon (fog and UV for the first days); otherwise they stay null.

## `useCache` (type: `boolean`):

MET Norway asks clients not to repeat a request before the `Expires` time of the last answer. With this on, each answer is kept (compressed, about 7 KB per place) in a key-value store named met-norway-forecast-cache in your account, and a place whose stored answer has not expired is served from it without any request, which is the polite and faster way. Turn off to always ask the source; delete the store at any time to clear it.

## Actor input object example

```json
{
  "locations": [
    {
      "name": "Mount Everest base camp",
      "latitude": 28.0026,
      "longitude": 86.8528,
      "altitude": 5364,
      "timeZone": "Asia/Kathmandu"
    },
    "Lisbon: 38.7223, -9.1393",
    "35.6762, 139.6503"
  ],
  "forecastDays": 3,
  "outputMode": "location",
  "timeStep": "hourly",
  "units": "metric",
  "includeDaily": true,
  "includeSteps": true,
  "includeExtendedFields": false,
  "useCache": true
}
```

# Actor output Schema

## `forecasts` (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": [
        {
            "name": "Oslo",
            "latitude": 59.9139,
            "longitude": 10.7522
        },
        {
            "name": "Milan",
            "latitude": 45.4642,
            "longitude": 9.19
        },
        {
            "name": "Sydney",
            "latitude": -33.8688,
            "longitude": 151.2093
        }
    ],
    "forecastDays": 3,
    "outputMode": "location",
    "timeStep": "hourly",
    "units": "metric"
};

// Run the Actor and wait for it to finish
const run = await client.actor("far003/weather-forecast-met-norway").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": [
        {
            "name": "Oslo",
            "latitude": 59.9139,
            "longitude": 10.7522,
        },
        {
            "name": "Milan",
            "latitude": 45.4642,
            "longitude": 9.19,
        },
        {
            "name": "Sydney",
            "latitude": -33.8688,
            "longitude": 151.2093,
        },
    ],
    "forecastDays": 3,
    "outputMode": "location",
    "timeStep": "hourly",
    "units": "metric",
}

# Run the Actor and wait for it to finish
run = client.actor("far003/weather-forecast-met-norway").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": [
    {
      "name": "Oslo",
      "latitude": 59.9139,
      "longitude": 10.7522
    },
    {
      "name": "Milan",
      "latitude": 45.4642,
      "longitude": 9.19
    },
    {
      "name": "Sydney",
      "latitude": -33.8688,
      "longitude": 151.2093
    }
  ],
  "forecastDays": 3,
  "outputMode": "location",
  "timeStep": "hourly",
  "units": "metric"
}' |
apify call far003/weather-forecast-met-norway --silent --output-dataset

```

## MCP server setup

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

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/VdbSh5CAuRtsOsTeJ/builds/j35Q73niY9eyCyKll/openapi.json
