Demonstration of API using OpenWeatherMap.org#

This demonstration is heavily inspired by NeuralNine’s video.
You need a free account from here.
The VS Code extension JSON viewer is recommended for viewing downloaded JSON content.

  • Set your maximum API calls to 1000 per day to make sure you are under the limit for billing.

  • To run the examples, download your API key, save it in the right folder (see below) in a file called api_key_OpenWeather, containing only the key (no spaces or “enters”).

# Imports
import datetime as dt
import requests
import json

Current weather#

Common definitions to use for all requests#

BASE_URL = "http://api.openweathermap.org/data/2.5/weather?"
API_KEY = open('../../../No_sync/api_key_OpenWeather','r').read()
CITY = "Ski"

url = BASE_URL + "q=" + CITY + "&appid=" + API_KEY

Request current weather in chosen city#

response = requests.get(url).json()
print(response)
{'coord': {'lon': 10.8358, 'lat': 59.7195}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'base': 'stations', 'main': {'temp': 290.25, 'feels_like': 290.52, 'temp_min': 290.25, 'temp_max': 290.55, 'pressure': 1014, 'humidity': 96, 'sea_level': 1014, 'grnd_level': 998}, 'visibility': 10000, 'wind': {'speed': 2.15, 'deg': 175, 'gust': 5.91}, 'rain': {'1h': 0.12}, 'clouds': {'all': 100}, 'dt': 1757076228, 'sys': {'type': 2, 'id': 2006772, 'country': 'NO', 'sunrise': 1757046115, 'sunset': 1757095752}, 'timezone': 7200, 'id': 3139081, 'name': 'Ski', 'cod': 200}
# Write JSON to file for viewing
with open('downloads/weather.json', 'w') as f:
    json.dump(response, f, indent=4)

Conversion functions#

Changing scales can make results more interpretable

# Kelvin to Celsius
def kelvin_to_celsius(temp):
    return temp - 273.15

# Meters per second to knots
def mps_to_knots(speed):
    return speed * 1.943844

Forecasted weather#

Common definitions to use for all requests#

BASE_URL = "https://api.openweathermap.org/data/2.5/forecast?"
CITY = "Mo i Rana"

urlF = BASE_URL + "q=" + CITY + "&appid=" + API_KEY

Request forecasted weather in chosen city#

responseF = requests.get(urlF).json()
#print(json.dumps(responseF, indent=4))
print(responseF)
{'cod': '200', 'message': 0, 'cnt': 40, 'list': [{'dt': 1757084400, 'main': {'temp': 291.62, 'feels_like': 291.51, 'temp_min': 291.62, 'temp_max': 293.76, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 964, 'humidity': 76, 'temp_kf': -2.14}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 60}, 'wind': {'speed': 1.43, 'deg': 337, 'gust': 1.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-05 15:00:00'}, {'dt': 1757095200, 'main': {'temp': 288.85, 'feels_like': 288.64, 'temp_min': 288, 'temp_max': 288.85, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 965, 'humidity': 83, 'temp_kf': 0.85}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 80}, 'wind': {'speed': 0.74, 'deg': 18, 'gust': 0.38}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-05 18:00:00'}, {'dt': 1757106000, 'main': {'temp': 287.83, 'feels_like': 287.55, 'temp_min': 287.83, 'temp_max': 287.83, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 966, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.23, 'deg': 115, 'gust': 1.23}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-05 21:00:00'}, {'dt': 1757116800, 'main': {'temp': 287.16, 'feels_like': 286.94, 'temp_min': 287.16, 'temp_max': 287.16, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 89, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 0.32, 'deg': 351, 'gust': 0}, 'visibility': 10000, 'pop': 0.37, 'rain': {'3h': 0.47}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-06 00:00:00'}, {'dt': 1757127600, 'main': {'temp': 287.45, 'feels_like': 287.39, 'temp_min': 287.45, 'temp_max': 287.45, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 968, 'humidity': 94, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.04, 'deg': 81, 'gust': 0.91}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 1.18}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-06 03:00:00'}, {'dt': 1757138400, 'main': {'temp': 288.89, 'feels_like': 288.82, 'temp_min': 288.89, 'temp_max': 288.89, 'pressure': 1019, 'sea_level': 1019, 'grnd_level': 969, 'humidity': 88, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.09, 'deg': 285, 'gust': 0.99}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 0.16}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-06 06:00:00'}, {'dt': 1757149200, 'main': {'temp': 290.62, 'feels_like': 290.51, 'temp_min': 290.62, 'temp_max': 290.62, 'pressure': 1022, 'sea_level': 1022, 'grnd_level': 971, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 90}, 'wind': {'speed': 2.69, 'deg': 259, 'gust': 2.63}, 'visibility': 10000, 'pop': 0.35, 'rain': {'3h': 0.24}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-06 09:00:00'}, {'dt': 1757160000, 'main': {'temp': 291.66, 'feels_like': 291.45, 'temp_min': 291.66, 'temp_max': 291.66, 'pressure': 1023, 'sea_level': 1023, 'grnd_level': 973, 'humidity': 72, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 81}, 'wind': {'speed': 2.8, 'deg': 272, 'gust': 2.51}, 'visibility': 10000, 'pop': 0.61, 'rain': {'3h': 0.43}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-06 12:00:00'}, {'dt': 1757170800, 'main': {'temp': 291.88, 'feels_like': 291.56, 'temp_min': 291.88, 'temp_max': 291.88, 'pressure': 1024, 'sea_level': 1024, 'grnd_level': 974, 'humidity': 67, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 96}, 'wind': {'speed': 1.55, 'deg': 267, 'gust': 1.49}, 'visibility': 10000, 'pop': 0.06, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-06 15:00:00'}, {'dt': 1757181600, 'main': {'temp': 290.09, 'feels_like': 289.82, 'temp_min': 290.09, 'temp_max': 290.09, 'pressure': 1025, 'sea_level': 1025, 'grnd_level': 975, 'humidity': 76, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 97}, 'wind': {'speed': 0.84, 'deg': 264, 'gust': 1.03}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-06 18:00:00'}, {'dt': 1757192400, 'main': {'temp': 287.73, 'feels_like': 287.44, 'temp_min': 287.73, 'temp_max': 287.73, 'pressure': 1025, 'sea_level': 1025, 'grnd_level': 975, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.27, 'deg': 73, 'gust': 2.33}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-06 21:00:00'}, {'dt': 1757203200, 'main': {'temp': 286.92, 'feels_like': 286.55, 'temp_min': 286.92, 'temp_max': 286.92, 'pressure': 1025, 'sea_level': 1025, 'grnd_level': 975, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 96}, 'wind': {'speed': 2.57, 'deg': 63, 'gust': 2.32}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-07 00:00:00'}, {'dt': 1757214000, 'main': {'temp': 287.57, 'feels_like': 287.31, 'temp_min': 287.57, 'temp_max': 287.57, 'pressure': 1025, 'sea_level': 1025, 'grnd_level': 974, 'humidity': 86, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.08, 'deg': 75, 'gust': 3.27}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.17}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-07 03:00:00'}, {'dt': 1757224800, 'main': {'temp': 287.67, 'feels_like': 287.63, 'temp_min': 287.67, 'temp_max': 287.67, 'pressure': 1024, 'sea_level': 1024, 'grnd_level': 974, 'humidity': 94, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.2, 'deg': 68, 'gust': 4.73}, 'visibility': 6186, 'pop': 1, 'rain': {'3h': 2.19}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-07 06:00:00'}, {'dt': 1757235600, 'main': {'temp': 288.32, 'feels_like': 288.29, 'temp_min': 288.32, 'temp_max': 288.32, 'pressure': 1024, 'sea_level': 1024, 'grnd_level': 973, 'humidity': 92, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.89, 'deg': 86, 'gust': 4.09}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 1.98}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-07 09:00:00'}, {'dt': 1757246400, 'main': {'temp': 288.5, 'feels_like': 288.52, 'temp_min': 288.5, 'temp_max': 288.5, 'pressure': 1023, 'sea_level': 1023, 'grnd_level': 973, 'humidity': 93, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.83, 'deg': 101, 'gust': 2.02}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 1.69}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-07 12:00:00'}, {'dt': 1757257200, 'main': {'temp': 291.65, 'feels_like': 291.57, 'temp_min': 291.65, 'temp_max': 291.65, 'pressure': 1022, 'sea_level': 1022, 'grnd_level': 972, 'humidity': 77, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 94}, 'wind': {'speed': 2.02, 'deg': 46, 'gust': 3.18}, 'visibility': 10000, 'pop': 0.21, 'rain': {'3h': 0.15}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-07 15:00:00'}, {'dt': 1757268000, 'main': {'temp': 288.76, 'feels_like': 288.67, 'temp_min': 288.76, 'temp_max': 288.76, 'pressure': 1022, 'sea_level': 1022, 'grnd_level': 972, 'humidity': 88, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 95}, 'wind': {'speed': 2.2, 'deg': 76, 'gust': 1.97}, 'visibility': 10000, 'pop': 0.89, 'rain': {'3h': 0.7}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-07 18:00:00'}, {'dt': 1757278800, 'main': {'temp': 286.6, 'feels_like': 286.3, 'temp_min': 286.6, 'temp_max': 286.6, 'pressure': 1022, 'sea_level': 1022, 'grnd_level': 972, 'humidity': 88, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 14}, 'wind': {'speed': 1.73, 'deg': 109, 'gust': 1.79}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-07 21:00:00'}, {'dt': 1757289600, 'main': {'temp': 286.05, 'feels_like': 285.69, 'temp_min': 286.05, 'temp_max': 286.05, 'pressure': 1022, 'sea_level': 1022, 'grnd_level': 972, 'humidity': 88, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 15}, 'wind': {'speed': 1.85, 'deg': 91, 'gust': 1.81}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-08 00:00:00'}, {'dt': 1757300400, 'main': {'temp': 285.79, 'feels_like': 285.36, 'temp_min': 285.79, 'temp_max': 285.79, 'pressure': 1021, 'sea_level': 1021, 'grnd_level': 971, 'humidity': 86, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 19}, 'wind': {'speed': 1.66, 'deg': 91, 'gust': 1.64}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-08 03:00:00'}, {'dt': 1757311200, 'main': {'temp': 288.52, 'feels_like': 288.25, 'temp_min': 288.52, 'temp_max': 288.52, 'pressure': 1020, 'sea_level': 1020, 'grnd_level': 970, 'humidity': 82, 'temp_kf': 0}, 'weather': [{'id': 802, 'main': 'Clouds', 'description': 'scattered clouds', 'icon': '03d'}], 'clouds': {'all': 31}, 'wind': {'speed': 1.18, 'deg': 82, 'gust': 1.01}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-08 06:00:00'}, {'dt': 1757322000, 'main': {'temp': 291.94, 'feels_like': 291.7, 'temp_min': 291.94, 'temp_max': 291.94, 'pressure': 1019, 'sea_level': 1019, 'grnd_level': 969, 'humidity': 70, 'temp_kf': 0}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 5}, 'wind': {'speed': 1.58, 'deg': 61, 'gust': 2}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-08 09:00:00'}, {'dt': 1757332800, 'main': {'temp': 294.67, 'feels_like': 294.34, 'temp_min': 294.67, 'temp_max': 294.67, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 968, 'humidity': 56, 'temp_kf': 0}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 2}, 'wind': {'speed': 1.34, 'deg': 88, 'gust': 2.08}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-08 12:00:00'}, {'dt': 1757343600, 'main': {'temp': 295.42, 'feels_like': 294.98, 'temp_min': 295.42, 'temp_max': 295.42, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 967, 'humidity': 49, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 11}, 'wind': {'speed': 1.23, 'deg': 136, 'gust': 1.89}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-08 15:00:00'}, {'dt': 1757354400, 'main': {'temp': 289.75, 'feels_like': 289.4, 'temp_min': 289.75, 'temp_max': 289.75, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 74, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 13}, 'wind': {'speed': 2, 'deg': 132, 'gust': 1.89}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-08 18:00:00'}, {'dt': 1757365200, 'main': {'temp': 287.82, 'feels_like': 287.54, 'temp_min': 287.82, 'temp_max': 287.82, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 11}, 'wind': {'speed': 1.88, 'deg': 121, 'gust': 1.82}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-08 21:00:00'}, {'dt': 1757376000, 'main': {'temp': 286.61, 'feels_like': 286.2, 'temp_min': 286.61, 'temp_max': 286.61, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 13}, 'wind': {'speed': 1.44, 'deg': 88, 'gust': 1.35}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-09 00:00:00'}, {'dt': 1757386800, 'main': {'temp': 285.92, 'feels_like': 285.47, 'temp_min': 285.92, 'temp_max': 285.92, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 85, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04n'}], 'clouds': {'all': 55}, 'wind': {'speed': 1.27, 'deg': 90, 'gust': 1.25}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-09 03:00:00'}, {'dt': 1757397600, 'main': {'temp': 288.4, 'feels_like': 288.12, 'temp_min': 288.4, 'temp_max': 288.4, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 82, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 69}, 'wind': {'speed': 0.87, 'deg': 78, 'gust': 0.63}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-09 06:00:00'}, {'dt': 1757408400, 'main': {'temp': 291.6, 'feels_like': 291.33, 'temp_min': 291.6, 'temp_max': 291.6, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 70, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 0.3, 'deg': 279, 'gust': 0.76}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-09 09:00:00'}, {'dt': 1757419200, 'main': {'temp': 293.3, 'feels_like': 293.07, 'temp_min': 293.3, 'temp_max': 293.3, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 967, 'humidity': 65, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.29, 'deg': 300, 'gust': 1.46}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-09 12:00:00'}, {'dt': 1757430000, 'main': {'temp': 294.15, 'feels_like': 293.85, 'temp_min': 294.15, 'temp_max': 294.15, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 967, 'humidity': 59, 'temp_kf': 0}, 'weather': [{'id': 802, 'main': 'Clouds', 'description': 'scattered clouds', 'icon': '03d'}], 'clouds': {'all': 37}, 'wind': {'speed': 0.5, 'deg': 8, 'gust': 1.37}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-09 15:00:00'}, {'dt': 1757440800, 'main': {'temp': 289.57, 'feels_like': 289.23, 'temp_min': 289.57, 'temp_max': 289.57, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 966, 'humidity': 75, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 23}, 'wind': {'speed': 1.91, 'deg': 115, 'gust': 1.86}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-09 18:00:00'}, {'dt': 1757451600, 'main': {'temp': 287.79, 'feels_like': 287.37, 'temp_min': 287.79, 'temp_max': 287.79, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 966, 'humidity': 79, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 11}, 'wind': {'speed': 2.19, 'deg': 116, 'gust': 2.24}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-09 21:00:00'}, {'dt': 1757462400, 'main': {'temp': 287.22, 'feels_like': 286.77, 'temp_min': 287.22, 'temp_max': 287.22, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 965, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 802, 'main': 'Clouds', 'description': 'scattered clouds', 'icon': '03n'}], 'clouds': {'all': 35}, 'wind': {'speed': 2.05, 'deg': 106, 'gust': 2.05}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-10 00:00:00'}, {'dt': 1757473200, 'main': {'temp': 287.2, 'feels_like': 286.75, 'temp_min': 287.2, 'temp_max': 287.2, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 964, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.27, 'deg': 89, 'gust': 2.15}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-10 03:00:00'}, {'dt': 1757484000, 'main': {'temp': 288.7, 'feels_like': 288.32, 'temp_min': 288.7, 'temp_max': 288.7, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 964, 'humidity': 77, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 99}, 'wind': {'speed': 2.49, 'deg': 99, 'gust': 2.78}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-10 06:00:00'}, {'dt': 1757494800, 'main': {'temp': 292.81, 'feels_like': 292.4, 'temp_min': 292.81, 'temp_max': 292.81, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 963, 'humidity': 60, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 92}, 'wind': {'speed': 2.31, 'deg': 105, 'gust': 2.94}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-10 09:00:00'}, {'dt': 1757505600, 'main': {'temp': 292.51, 'feels_like': 292.17, 'temp_min': 292.51, 'temp_max': 292.51, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 962, 'humidity': 64, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 90}, 'wind': {'speed': 2.66, 'deg': 115, 'gust': 3.27}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-10 12:00:00'}], 'city': {'id': 3145614, 'name': 'Mo i Rana', 'coord': {'lat': 66.3128, 'lon': 14.1428}, 'country': 'NO', 'population': 17853, 'timezone': 7200, 'sunrise': 1757044255, 'sunset': 1757096025}}

# Write JSON to file for viewing
with open('downloads/forecast.json', 'w') as f:
    json.dump(responseF, f, indent=4)

When and what?#

Check contents and time stamps

# Content of responseF
responseF.keys()
dict_keys(['cod', 'message', 'cnt', 'list', 'city'])
# Number of forecasts
print(len(responseF["list"]))
40
# Print forecast times
for forecast in responseF["list"]:
    print(forecast["dt_txt"])
2025-09-05 15:00:00
2025-09-05 18:00:00
2025-09-05 21:00:00
2025-09-06 00:00:00
2025-09-06 03:00:00
2025-09-06 06:00:00
2025-09-06 09:00:00
2025-09-06 12:00:00
2025-09-06 15:00:00
2025-09-06 18:00:00
2025-09-06 21:00:00
2025-09-07 00:00:00
2025-09-07 03:00:00
2025-09-07 06:00:00
2025-09-07 09:00:00
2025-09-07 12:00:00
2025-09-07 15:00:00
2025-09-07 18:00:00
2025-09-07 21:00:00
2025-09-08 00:00:00
2025-09-08 03:00:00
2025-09-08 06:00:00
2025-09-08 09:00:00
2025-09-08 12:00:00
2025-09-08 15:00:00
2025-09-08 18:00:00
2025-09-08 21:00:00
2025-09-09 00:00:00
2025-09-09 03:00:00
2025-09-09 06:00:00
2025-09-09 09:00:00
2025-09-09 12:00:00
2025-09-09 15:00:00
2025-09-09 18:00:00
2025-09-09 21:00:00
2025-09-10 00:00:00
2025-09-10 03:00:00
2025-09-10 06:00:00
2025-09-10 09:00:00
2025-09-10 12:00:00

Make plots of omnipresent measurements and events#

We will later look at missing data, data only sporadically appearing and so on.

# Air pressure per period
pressures = []
timestamps = []
for forecast in responseF["list"]:
    pressures.append(forecast["main"]["pressure"])
    timestamps.append(dt.datetime.fromtimestamp(forecast["dt"]))
import matplotlib.pyplot as plt
plt.bar(timestamps, pressures)
plt.xticks(rotation=45)
plt.ylim(980, 1050)
plt.grid()
plt.ylabel("Air pressure (hPa)")
plt.title(f"Forecasted air pressure in {CITY}")
plt.show()
../../_images/4a66bf3f5e566be2ee1e06a6c1a94ca519c7f8ca9e1b54645eb207c1b49223eb.png

Exercise#

  • Make a new forecast request for your own hometown. Call your response something else than responseF.

  • If available, plot the humidity like we did with air pressure.

Precipitation#

  • … comes in two main flavours: rain and snow.

  • We need to check which is present and set to zero if it is abscent.

rain = []
snow = []
for forecast in responseF["list"]:
    try: # Check if rain is present in forecast
        rain.append(forecast["rain"]["3h"])
    except KeyError:
        rain.append(0)
    try: # Check if snow is present in forecast
        snow.append(forecast["snow"]["3h"])
    except KeyError:
        snow.append(0)
# Stacked bar chart with rain and snow
plt.bar(timestamps, rain, label="Rain")
plt.bar(timestamps, snow, label="Snow")
plt.xticks(rotation=45)
plt.grid()
plt.ylabel("Precipitation (mm)")
plt.title(f"Forecasted precipitation in {CITY}")
plt.legend()
plt.show()
../../_images/836252f861d796e1c4da24360c1269311790e742ede9e558aa4dcc7ee7ea0211.png