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': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'base': 'stations', 'main': {'temp': 288.59, 'feels_like': 288.49, 'temp_min': 288.59, 'temp_max': 289.44, 'pressure': 1010, 'humidity': 88, 'sea_level': 1010, 'grnd_level': 995}, 'visibility': 10000, 'wind': {'speed': 4.07, 'deg': 101, 'gust': 12.35}, 'clouds': {'all': 98}, 'dt': 1757534104, 'sys': {'type': 2, 'id': 2006772, 'country': 'NO', 'sunrise': 1757478808, 'sunset': 1757526850}, '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': 1757538000, 'main': {'temp': 288.89, 'feels_like': 288.56, 'temp_min': 286.91, 'temp_max': 288.89, 'pressure': 1020, 'sea_level': 1020, 'grnd_level': 970, 'humidity': 78, 'temp_kf': 1.98}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 20}, 'wind': {'speed': 3.61, 'deg': 99, 'gust': 3.55}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-10 21:00:00'}, {'dt': 1757548800, 'main': {'temp': 287.86, 'feels_like': 287.45, 'temp_min': 285.79, 'temp_max': 287.86, 'pressure': 1020, 'sea_level': 1020, 'grnd_level': 969, 'humidity': 79, 'temp_kf': 2.07}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 16}, 'wind': {'speed': 4.02, 'deg': 86, 'gust': 4.08}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-11 00:00:00'}, {'dt': 1757559600, 'main': {'temp': 286.64, 'feels_like': 286.21, 'temp_min': 285.52, 'temp_max': 286.64, 'pressure': 1019, 'sea_level': 1019, 'grnd_level': 968, 'humidity': 83, 'temp_kf': 1.12}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 8}, 'wind': {'speed': 4.33, 'deg': 78, 'gust': 4.91}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-11 03:00:00'}, {'dt': 1757570400, 'main': {'temp': 288.41, 'feels_like': 287.92, 'temp_min': 288.41, 'temp_max': 288.41, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 966, 'humidity': 74, 'temp_kf': 0}, 'weather': [{'id': 802, 'main': 'Clouds', 'description': 'scattered clouds', 'icon': '03d'}], 'clouds': {'all': 40}, 'wind': {'speed': 4.22, 'deg': 80, 'gust': 5.24}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-11 06:00:00'}, {'dt': 1757581200, 'main': {'temp': 293.41, 'feels_like': 293.14, 'temp_min': 293.41, 'temp_max': 293.41, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 965, 'humidity': 63, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 79}, 'wind': {'speed': 5.36, 'deg': 97, 'gust': 12.12}, 'visibility': 10000, 'pop': 0.28, 'rain': {'3h': 0.18}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-11 09:00:00'}, {'dt': 1757592000, 'main': {'temp': 292.83, 'feels_like': 292.71, 'temp_min': 292.83, 'temp_max': 292.83, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 963, 'humidity': 71, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 90}, 'wind': {'speed': 4.46, 'deg': 87, 'gust': 9.93}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.1}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-11 12:00:00'}, {'dt': 1757602800, 'main': {'temp': 290.8, 'feels_like': 290.71, 'temp_min': 290.8, 'temp_max': 290.8, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 962, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.43, 'deg': 69, 'gust': 4.51}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-11 15:00:00'}, {'dt': 1757613600, 'main': {'temp': 290.26, 'feels_like': 290.27, 'temp_min': 290.26, 'temp_max': 290.26, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 961, 'humidity': 86, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.41, 'deg': 52, 'gust': 3.6}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-11 18:00:00'}, {'dt': 1757624400, 'main': {'temp': 290.01, 'feels_like': 289.97, 'temp_min': 290.01, 'temp_max': 290.01, 'pressure': 1008, 'sea_level': 1008, 'grnd_level': 959, 'humidity': 85, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.75, 'deg': 71, 'gust': 3.61}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-11 21:00:00'}, {'dt': 1757635200, 'main': {'temp': 291.29, 'feels_like': 291.09, 'temp_min': 291.29, 'temp_max': 291.29, 'pressure': 1006, 'sea_level': 1006, 'grnd_level': 957, 'humidity': 74, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 8.2, 'deg': 103, 'gust': 15.7}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.25}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-12 00:00:00'}, {'dt': 1757646000, 'main': {'temp': 289.97, 'feels_like': 289.64, 'temp_min': 289.97, 'temp_max': 289.97, 'pressure': 1004, 'sea_level': 1004, 'grnd_level': 955, 'humidity': 74, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 5.33, 'deg': 98, 'gust': 11.03}, 'visibility': 10000, 'pop': 0.35, 'rain': {'3h': 0.22}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-12 03:00:00'}, {'dt': 1757656800, 'main': {'temp': 288.57, 'feels_like': 288.26, 'temp_min': 288.57, 'temp_max': 288.57, 'pressure': 1006, 'sea_level': 1006, 'grnd_level': 956, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.81, 'deg': 83, 'gust': 4.9}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.1}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-12 06:00:00'}, {'dt': 1757667600, 'main': {'temp': 288.72, 'feels_like': 288.5, 'temp_min': 288.72, 'temp_max': 288.72, 'pressure': 1008, 'sea_level': 1008, 'grnd_level': 958, 'humidity': 83, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.96, 'deg': 77, 'gust': 4.29}, 'visibility': 10000, 'pop': 0.36, 'rain': {'3h': 0.21}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-12 09:00:00'}, {'dt': 1757678400, 'main': {'temp': 289.83, 'feels_like': 289.59, 'temp_min': 289.83, 'temp_max': 289.83, 'pressure': 1009, 'sea_level': 1009, 'grnd_level': 959, 'humidity': 78, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 92}, 'wind': {'speed': 4.02, 'deg': 76, 'gust': 4.96}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-12 12:00:00'}, {'dt': 1757689200, 'main': {'temp': 290.77, 'feels_like': 290.52, 'temp_min': 290.77, 'temp_max': 290.77, 'pressure': 1009, 'sea_level': 1009, 'grnd_level': 960, 'humidity': 74, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 60}, 'wind': {'speed': 3.25, 'deg': 84, 'gust': 3.92}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.13}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-12 15:00:00'}, {'dt': 1757700000, 'main': {'temp': 288.34, 'feels_like': 288.11, 'temp_min': 288.34, 'temp_max': 288.34, 'pressure': 1010, 'sea_level': 1010, 'grnd_level': 961, 'humidity': 84, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 72}, 'wind': {'speed': 2.97, 'deg': 97, 'gust': 2.59}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 0.66}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-12 18:00:00'}, {'dt': 1757710800, 'main': {'temp': 286.15, 'feels_like': 285.72, 'temp_min': 286.15, 'temp_max': 286.15, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 961, 'humidity': 85, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 12}, 'wind': {'speed': 3.09, 'deg': 124, 'gust': 2.86}, 'visibility': 10000, 'pop': 0.31, 'rain': {'3h': 0.24}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-12 21:00:00'}, {'dt': 1757721600, 'main': {'temp': 285.35, 'feels_like': 284.85, 'temp_min': 285.35, 'temp_max': 285.35, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 962, 'humidity': 85, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02n'}], 'clouds': {'all': 12}, 'wind': {'speed': 3.19, 'deg': 117, 'gust': 3.15}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-13 00:00:00'}, {'dt': 1757732400, 'main': {'temp': 286.4, 'feels_like': 286, 'temp_min': 286.4, 'temp_max': 286.4, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 962, 'humidity': 85, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04n'}], 'clouds': {'all': 53}, 'wind': {'speed': 2.96, 'deg': 86, 'gust': 2.68}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-13 03:00:00'}, {'dt': 1757743200, 'main': {'temp': 286.9, 'feels_like': 286.5, 'temp_min': 286.9, 'temp_max': 286.9, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 962, 'humidity': 83, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 77}, 'wind': {'speed': 2.58, 'deg': 105, 'gust': 2.54}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.1}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-13 06:00:00'}, {'dt': 1757754000, 'main': {'temp': 290.24, 'feels_like': 289.47, 'temp_min': 290.24, 'temp_max': 290.24, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 963, 'humidity': 56, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 47}, 'wind': {'speed': 2.35, 'deg': 150, 'gust': 4.71}, 'visibility': 10000, 'pop': 0.64, 'rain': {'3h': 0.35}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-13 09:00:00'}, {'dt': 1757764800, 'main': {'temp': 290.35, 'feels_like': 289.54, 'temp_min': 290.35, 'temp_max': 290.35, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 964, 'humidity': 54, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 33}, 'wind': {'speed': 5.15, 'deg': 164, 'gust': 5.48}, 'visibility': 10000, 'pop': 0.81, 'rain': {'3h': 0.48}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-13 12:00:00'}, {'dt': 1757775600, 'main': {'temp': 289.11, 'feels_like': 288.28, 'temp_min': 289.11, 'temp_max': 289.11, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 965, 'humidity': 58, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10d'}], 'clouds': {'all': 43}, 'wind': {'speed': 2.48, 'deg': 185, 'gust': 3.5}, 'visibility': 10000, 'pop': 0.25, 'rain': {'3h': 0.15}, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-13 15:00:00'}, {'dt': 1757786400, 'main': {'temp': 287.15, 'feels_like': 286.41, 'temp_min': 287.15, 'temp_max': 287.15, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 965, 'humidity': 69, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 71}, 'wind': {'speed': 0.75, 'deg': 152, 'gust': 0.58}, 'visibility': 10000, 'pop': 0.2, 'rain': {'3h': 0.13}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-13 18:00:00'}, {'dt': 1757797200, 'main': {'temp': 286.61, 'feels_like': 285.89, 'temp_min': 286.61, 'temp_max': 286.61, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 965, 'humidity': 72, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 0.81, 'deg': 124, 'gust': 0.79}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-13 21:00:00'}, {'dt': 1757808000, 'main': {'temp': 283.72, 'feels_like': 282.95, 'temp_min': 283.72, 'temp_max': 283.72, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 966, 'humidity': 81, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04n'}], 'clouds': {'all': 83}, 'wind': {'speed': 1.09, 'deg': 117, 'gust': 1.06}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-14 00:00:00'}, {'dt': 1757818800, 'main': {'temp': 282.58, 'feels_like': 281.59, 'temp_min': 282.58, 'temp_max': 282.58, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 966, 'humidity': 83, 'temp_kf': 0}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 8}, 'wind': {'speed': 2.11, 'deg': 108, 'gust': 2.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-14 03:00:00'}, {'dt': 1757829600, 'main': {'temp': 283.9, 'feels_like': 283.12, 'temp_min': 283.9, 'temp_max': 283.9, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 966, 'humidity': 80, 'temp_kf': 0}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 16}, 'wind': {'speed': 2.25, 'deg': 100, 'gust': 2.53}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-14 06:00:00'}, {'dt': 1757840400, 'main': {'temp': 287.78, 'feels_like': 287, 'temp_min': 287.78, 'temp_max': 287.78, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 965, 'humidity': 65, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.95, 'deg': 78, 'gust': 3.16}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-14 09:00:00'}, {'dt': 1757851200, 'main': {'temp': 289.63, 'feels_like': 288.9, 'temp_min': 289.63, 'temp_max': 289.63, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 964, 'humidity': 60, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.8, 'deg': 89, 'gust': 3.32}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-14 12:00:00'}, {'dt': 1757862000, 'main': {'temp': 290.29, 'feels_like': 289.57, 'temp_min': 290.29, 'temp_max': 290.29, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 963, 'humidity': 58, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 88}, 'wind': {'speed': 3.5, 'deg': 81, 'gust': 4.76}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-14 15:00:00'}, {'dt': 1757872800, 'main': {'temp': 287.84, 'feels_like': 287.14, 'temp_min': 287.84, 'temp_max': 287.84, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 961, 'humidity': 68, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 92}, 'wind': {'speed': 3.35, 'deg': 72, 'gust': 3.65}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-14 18:00:00'}, {'dt': 1757883600, 'main': {'temp': 287.07, 'feels_like': 286.48, 'temp_min': 287.07, 'temp_max': 287.07, 'pressure': 1008, 'sea_level': 1008, 'grnd_level': 958, 'humidity': 75, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.98, 'deg': 77, 'gust': 3.36}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-14 21:00:00'}, {'dt': 1757894400, 'main': {'temp': 286.17, 'feels_like': 285.77, 'temp_min': 286.17, 'temp_max': 286.17, 'pressure': 1005, 'sea_level': 1005, 'grnd_level': 955, 'humidity': 86, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.48, 'deg': 72, 'gust': 2.64}, 'visibility': 10000, 'pop': 0.22, 'rain': {'3h': 0.27}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-15 00:00:00'}, {'dt': 1757905200, 'main': {'temp': 285.51, 'feels_like': 285.1, 'temp_min': 285.51, 'temp_max': 285.51, 'pressure': 1003, 'sea_level': 1003, 'grnd_level': 953, 'humidity': 88, 'temp_kf': 0}, 'weather': [{'id': 500, 'main': 'Rain', 'description': 'light rain', 'icon': '10n'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.45, 'deg': 68, 'gust': 2.64}, 'visibility': 10000, 'pop': 1, 'rain': {'3h': 0.62}, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-15 03:00:00'}, {'dt': 1757916000, 'main': {'temp': 284.84, 'feels_like': 284.21, 'temp_min': 284.84, 'temp_max': 284.84, 'pressure': 1001, 'sea_level': 1001, 'grnd_level': 951, 'humidity': 82, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.1, 'deg': 87, 'gust': 4.21}, 'visibility': 10000, 'pop': 0.76, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-15 06:00:00'}, {'dt': 1757926800, 'main': {'temp': 287.26, 'feels_like': 286.48, 'temp_min': 287.26, 'temp_max': 287.26, 'pressure': 1000, 'sea_level': 1000, 'grnd_level': 951, 'humidity': 67, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 74}, 'wind': {'speed': 2.15, 'deg': 104, 'gust': 2.67}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-15 09:00:00'}, {'dt': 1757937600, 'main': {'temp': 289.25, 'feels_like': 288.43, 'temp_min': 289.25, 'temp_max': 289.25, 'pressure': 999, 'sea_level': 999, 'grnd_level': 949, 'humidity': 58, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 67}, 'wind': {'speed': 2.97, 'deg': 119, 'gust': 3.29}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-15 12:00:00'}, {'dt': 1757948400, 'main': {'temp': 288.36, 'feels_like': 287.53, 'temp_min': 288.36, 'temp_max': 288.36, 'pressure': 998, 'sea_level': 998, 'grnd_level': 948, 'humidity': 61, 'temp_kf': 0}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 77}, 'wind': {'speed': 3.29, 'deg': 106, 'gust': 4.52}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2025-09-15 15:00:00'}, {'dt': 1757959200, 'main': {'temp': 286.71, 'feels_like': 285.98, 'temp_min': 286.71, 'temp_max': 286.71, 'pressure': 997, 'sea_level': 997, 'grnd_level': 947, 'humidity': 71, 'temp_kf': 0}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 89}, 'wind': {'speed': 3.05, 'deg': 88, 'gust': 3.73}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2025-09-15 18:00:00'}], 'city': {'id': 3145614, 'name': 'Mo i Rana', 'coord': {'lat': 66.3128, 'lon': 14.1428}, 'country': 'NO', 'population': 17853, 'timezone': 7200, 'sunrise': 1757477229, 'sunset': 1757526841}}
# 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-10 21:00:00
2025-09-11 00:00:00
2025-09-11 03:00:00
2025-09-11 06:00:00
2025-09-11 09:00:00
2025-09-11 12:00:00
2025-09-11 15:00:00
2025-09-11 18:00:00
2025-09-11 21:00:00
2025-09-12 00:00:00
2025-09-12 03:00:00
2025-09-12 06:00:00
2025-09-12 09:00:00
2025-09-12 12:00:00
2025-09-12 15:00:00
2025-09-12 18:00:00
2025-09-12 21:00:00
2025-09-13 00:00:00
2025-09-13 03:00:00
2025-09-13 06:00:00
2025-09-13 09:00:00
2025-09-13 12:00:00
2025-09-13 15:00:00
2025-09-13 18:00:00
2025-09-13 21:00:00
2025-09-14 00:00:00
2025-09-14 03:00:00
2025-09-14 06:00:00
2025-09-14 09:00:00
2025-09-14 12:00:00
2025-09-14 15:00:00
2025-09-14 18:00:00
2025-09-14 21:00:00
2025-09-15 00:00:00
2025-09-15 03:00:00
2025-09-15 06:00:00
2025-09-15 09:00:00
2025-09-15 12:00:00
2025-09-15 15:00:00
2025-09-15 18: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/1d4c0940331a618444ad3c65c0f999fbfde8ebddcdf3c15e315b0a8846e487ea.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/dcdc82714bfa1509e0d1c10ad8c7d86c50ee7de164cc45655c569c2dd223a74d.png