# Weather Forecast API - Worldwide, Any City or Coordinates (`neverempty/weather-forecast-worldwide`) Actor

For travel apps, logistics, farming and dashboards: hourly weather forecasts for any city name or latitude/longitude on Earth, about 9 days ahead, with temperature in C and F, rain, wind, clouds, humidity and pressure. About 34,000 cities match by name. MET Norway data, CC BY 4.0. No API key.

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

## Pricing

from $1.46 / 1,000 forecast row returneds

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 - Worldwide, Any City or Coordinates

**Hour-by-hour weather forecasts for any city name or any latitude/longitude on Earth, up to about 9 days ahead. No API key, no sign-up with a weather provider.**

Give it `"Tokyo"`, `"Paris, FR"`, `"Austin, TX"` or `"-33.8688,151.2093"` and get one clean row per forecast time: temperature in °C and °F, precipitation, wind (m/s, km/h, mph and compass direction), cloud cover, humidity, sea-level pressure and a weather symbol.

The forecast comes from **MET Norway** (the Norwegian Meteorological Institute), whose public forecast API serves the whole globe and is free to reuse under **CC BY 4.0**. This Actor calls it the way MET Norway's terms ask (identified User-Agent, coordinates rounded to 4 decimals, cached answers reused until they expire, `If-Modified-Since` on refresh), and turns the nested GeoJSON into flat rows you can drop into a spreadsheet, database or dashboard.

### What you get

One row per forecast time, per location:

| Field | Example | Notes |
|---|---|---|
| `query` | `Paris` | What you typed |
| `matchedPlace` | `Paris, FR (most populous of 3 matching places)` | Which place a city name was matched to. `null` for coordinates |
| `countryCode` / `country` | `FR` / `France` | City inputs only |
| `latitude` / `longitude` | `48.8534` / `2.3488` | The point that was forecast (4 decimals) |
| `elevationM` | `42` | Height used for the forecast |
| `timezone` | `Europe/Paris` | City inputs only |
| `timeUtc` | `2026-09-18T14:00:00Z` | Forecast time in UTC |
| `localTime` | `2026-09-18T16:00` | Same time on the local clock (city inputs only) |
| `hoursToNextRow` | `1` | `1` in the hourly part, `6` further out |
| `temperatureC` / `temperatureF` | `21.9` / `71.4` | Air temperature at 2 m |
| `precipitationMmNext1h` | `0` | Only in the hourly part; `null` (not `0`) where MET Norway gives no 1-hour value |
| `precipitationMmNext6h` | `1.2` | |
| `symbolNext1h` / `symbolNext6h` / `symbolNext12h` | `partlycloudy_day` | MET Norway weather symbol codes |
| `windSpeedMs` / `windSpeedKmh` / `windSpeedMph` | `4.5` / `16.2` / `10.1` | 10-minute mean at 10 m |
| `windFromDirectionDeg` / `windFromCompass` | `279.6` / `W` | Direction the wind comes **from** |
| `cloudCoverPercent` | `77.3` | |
| `relativeHumidityPercent` | `45.9` | |
| `pressureHpaSeaLevel` | `1023.3` | |
| `forecastUpdatedAt` | `2026-09-18T13:16:43Z` | When MET Norway last updated this forecast |
| `attribution` / `license` | `Data from MET Norway ...` / CC BY 4.0 link | Keep these if you republish the data |
| `placeAttribution` | `City coordinates from GeoNames ...` | City inputs only |

#### A real row (Sydney, run on 2026-09-18)

```json
{
  "query": "-33.8688,151.2093",
  "matchedPlace": null,
  "latitude": -33.8688,
  "longitude": 151.2093,
  "elevationM": 41,
  "timeUtc": "2026-09-18T14:00:00Z",
  "hoursToNextRow": 1,
  "temperatureC": 16.5,
  "temperatureF": 61.7,
  "precipitationMmNext1h": 0,
  "precipitationMmNext6h": 0,
  "symbolNext1h": "partlycloudy_night",
  "symbolNext6h": "partlycloudy_night",
  "symbolNext12h": "fair_day",
  "windSpeedMs": 4.5,
  "windSpeedKmh": 16.2,
  "windSpeedMph": 10.1,
  "windFromDirectionDeg": 279.6,
  "windFromCompass": "W",
  "cloudCoverPercent": 77.3,
  "relativeHumidityPercent": 45.9,
  "pressureHpaSeaLevel": 1023.3,
  "forecastUpdatedAt": "2026-09-18T13:16:43Z",
  "attribution": "Data from MET Norway (api.met.no), CC BY 4.0 - reformatted and unit-converted by this Actor",
  "license": "https://creativecommons.org/licenses/by/4.0/"
}
```

### How far ahead, and how many rows

MET Norway publishes about 9 days per point: **hourly for about the first 2.5 days, then every 6 hours**. In our test runs on 2026-09-18 that was 91-92 time steps per location. Northern Europe gets a higher-resolution model; the rest of the world uses the ECMWF global model (about 9 km).

Want less? Set **Hours ahead** (`maxHoursAhead`), e.g. `24` returns the current hour plus the next 24 (25 rows per location).

### Input

| Field | What it does |
|---|---|
| `cities` | City names, one per line (`"Paris, FR"`, `"Austin, TX"`, `"Tokyo"`) |
| `locations` | Coordinates: `"lat,lon"` strings or `{ "latitude", "longitude", "label", "altitude" }` objects |
| `maxHoursAhead` | Optional. Only forecast times up to this many hours from now |
| `useCache` | Reuse a still-valid forecast (default on, see Caching below) |
| `maxRetries` | Attempts per location on temporary errors (default 3) |

```json
{
  "cities": ["London, GB", "Tokyo", "Austin, TX"],
  "locations": ["-33.8688,151.2093", { "latitude": 64.1466, "longitude": -21.9426, "label": "Reykjavik harbour", "altitude": 10 }],
  "maxHoursAhead": 48
}
```

- **Cities** are matched against a bundled copy of the GeoNames list of about 34,000 cities with 15,000+ people or national capitals. Accents and case do not matter (`sao paulo` = `São Paulo`), and many English and local names work (`Munich` = `München`, `Kiev` = `Kyiv`). A city whose own name matches always wins over a city that only has it as an alternate name; alternate-name matches say so in `matchedPlace`.
  - Several places share a name? Without a country, the most populous one is used and `matchedPlace` says how many there were. Add a 2-letter country code (`"Paris, US"`) or, for the US, a state code (`"Paris, TX"`).
  - Two-letter codes are read as a country code **and** as a US state code, so a few overlap (`CA` = Canada or California, `IN` = India or Indiana). If both match, the most populous place wins and `matchedPlace` shows which one; add a second code to narrow it (`"Ontario, CA, US"` = Ontario, California) or use coordinates.
  - A name that is not in the list, or a country that does not have that name, is **not** silently replaced by another place: it is skipped and explained (see below).
- **Coordinates** work anywhere, including the ocean. Optional `altitude` (meters) improves temperature in hilly terrain; for cities the GeoNames elevation is sent automatically.
- The same point asked twice (e.g. a city and its own coordinates rounded to 4 decimals) is fetched and billed once.
- Leave everything empty and you get London, Tokyo and New York as an example.

### When something cannot be answered

Inputs that cannot be used are never turned into empty or made-up rows. They are listed, with the reason, in the run log and in the **`RUN_ISSUES`** record of the run's key-value store, and they are not billed. For example:

- `"Xyzzy"`: *No city named "Xyzzy" in the bundled GeoNames list ... Use coordinates for smaller places.*
- `"Paris, DE"`: *"Paris" exists in the bundled list, but not in "DE". Places with that name are in: FR, US-TX, ZA.*
- MET Norway refusing a point or throttling (HTTP 429) after the retries: the HTTP status and message.
- If 5 locations in a row fail with temporary MET Norway errors (5xx, 429, timeouts), the remaining locations are not requested and are listed with that reason instead of waiting for hours.
- An empty or non-text entry in `cities` is listed as *Not a city name* (the London/Tokyo/New York example is only used when both `cities` and `locations` are left empty).

If every input fails, the run returns 0 rows and its status message says why.

### Caching (why a second run can be instant)

MET Norway's terms ask API users not to re-download a forecast before its `Expires` time and to refresh with `If-Modified-Since`. With **Reuse a still-valid forecast** on (default), the Actor keeps the last answer per point in a named key-value store in your own Apify account, `weather-forecast-worldwide-cache`, and:

- before `Expires`: reuses it without calling MET Norway;
- after `Expires`: asks MET Norway with `If-Modified-Since`; `304 Not Modified` means the stored forecast is still the current one.

Either way the rows are the forecast MET Norway is serving at that moment, and they are billed like any other row. Turn it off to always fetch; you can delete the store at any time.

### Pricing

Pay per result: **one row = one forecast time for one location**. Nothing is charged for inputs that could not be used. With no `maxHoursAhead`, one location is typically about 90 rows. If you set a maximum charge for a run and it is reached, the Actor stops fetching, keeps the rows already delivered, and says in the log and status that the result is incomplete.

### Data sources and license

- **Forecasts:** [MET Norway](https://api.met.no/) Locationforecast 2.0, licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) and the Norwegian Licence for Open Government Data (NLOD) 2.0. This Actor flattens the data and adds unit conversions (°F, km/h, mph, compass direction, local time). **If you publish the data, credit "Data from MET Norway"** as the `attribution` column says.
- **City names and coordinates:** [GeoNames](https://www.geonames.org/) `cities15000`, licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
- This Actor is an independent tool. It is not made or endorsed by MET Norway, Yr or NRK.

### Also from NeverEmpty

- [Weather Forecast API - NWS (US only)](https://apify.com/neverempty/us-weather-forecast-api): the National Weather Service's own day/night and hourly forecasts with its text descriptions.

# Actor input Schema

## `cities` (type: `array`):

City names, one per line. Add a 2-letter country code to pick the right one: "Paris, FR", "London, GB", "Portland, US" (for the US you can also use the state: "Portland, OR"). Covers about 34,000 cities with 15,000+ people or national capitals (GeoNames). If several places share a name and you give no country, the most populous one is used and the row says so in "matchedPlace". For smaller places use Coordinates.

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

Any point on Earth, as "latitude,longitude" strings ("35.6895,139.6917") or objects like {"latitude": 35.6895, "longitude": 139.6917, "label": "Office", "altitude": 40}. Coordinates are rounded to 4 decimals (about 11 m), as MET Norway requires. "altitude" in meters is optional and improves the temperature in hilly places.

## `maxHoursAhead` (type: `integer`):

Only return forecast times up to this many hours from now. Leave empty for everything MET Norway publishes (about 9 days: hourly for roughly the first 2.5 days, then every 6 hours). Each row is one forecast time for one location and is billed as one result, so this also caps the cost.

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

MET Norway's terms ask clients not to re-download a forecast before its Expires time and to use If-Modified-Since. On (recommended) keeps the last answer per point in a named key-value store in your account (weather-forecast-worldwide-cache) and reuses it while it is valid. The rows are the same forecast MET Norway is serving at that moment.

## `maxRetries` (type: `integer`):

How many times to try a location when MET Norway returns a temporary error (5xx, 429 or a network error).

## Actor input object example

```json
{
  "cities": [
    "London, GB",
    "Tokyo, JP",
    "Sao Paulo, BR"
  ],
  "locations": [
    "-33.8688,151.2093",
    {
      "latitude": 64.1466,
      "longitude": -21.9426,
      "label": "Reykjavik harbour"
    }
  ],
  "useCache": true,
  "maxRetries": 3
}
```

# Actor output Schema

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

One row per forecast time per location.

# 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 = {
    "cities": [
        "London, GB",
        "Tokyo, JP",
        "Sao Paulo, BR"
    ],
    "locations": [
        "-33.8688,151.2093",
        {
            "latitude": 64.1466,
            "longitude": -21.9426,
            "label": "Reykjavik harbour"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/weather-forecast-worldwide").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 = {
    "cities": [
        "London, GB",
        "Tokyo, JP",
        "Sao Paulo, BR",
    ],
    "locations": [
        "-33.8688,151.2093",
        {
            "latitude": 64.1466,
            "longitude": -21.9426,
            "label": "Reykjavik harbour",
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/weather-forecast-worldwide").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 '{
  "cities": [
    "London, GB",
    "Tokyo, JP",
    "Sao Paulo, BR"
  ],
  "locations": [
    "-33.8688,151.2093",
    {
      "latitude": 64.1466,
      "longitude": -21.9426,
      "label": "Reykjavik harbour"
    }
  ]
}' |
apify call neverempty/weather-forecast-worldwide --silent --output-dataset

```

## MCP server setup

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

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/baBfsFNxFV7CYkbKy/builds/SIMGP2PR8iKJy7OET/openapi.json
