- Tourism is strongly affected by weather of a certain place
- It strongly impacts the safety and operation of transportation of all forms.
- We even decide our outfits based on the weather conditions
- No doubt, it plays a major role in the farming business.
Typing `London` feels like the obvious starting point, but I couldn’t resist digging into how that name becomes the coordinates a forecast service needs. That translation gives a small Python script a way to fetch weather without starting with a graphical app.
A city lookup leads to a JSON response your command-line program can use. The response makes more sense once you see which daily values sit beside each date.
What a Python weather forecast returns
Python can fetch weather forecasts from an application programming interface (API) and print the returned values. Open-Meteo’s geocoding API turns a city name into coordinates, then the forecast API uses those coordinates to return daily data.
An API response arrives as JavaScript Object Notation (JSON), with one array for each requested daily value. I tested the location step with London and saw the coordinates the forecast request needs.
| Input or field | What it does |
|---|---|
| City name | Geocoding returns latitude and longitude for the place. |
| Daily values | Maximum and minimum temperature plus precipitation chance. |
| Forecast days | The program requests three daily results. |
| Timezone | Automatic timezone selection keeps dates local to the place. |
The Forecast API docs use Celsius by default. Automatic timezone selection places each forecast date on the location’s local calendar, which keeps a city forecast aligned with its local day.
The forecast endpoint needs coordinates, while the geocoding endpoint accepts a place name. The Open-Meteo Geocoding API documentation allows a country or region after the city when names collide.
What you need before the forecast
Python 3 and an internet connection are enough because the example uses the standard library. It needs no package installation or API key for non-commercial use of Open-Meteo’s free endpoints.
Open-Meteo’s free API is for non-commercial use, and its data require attribution under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). The program prints the data source with its forecast, and commercial projects need a paid plan under the service terms.
- Python 3 and its standard library.
- Network access to the Open-Meteo geocoding and forecast endpoints.
- A city with its country or region when the name is ambiguous.
The code uses Python’s built-in URL tools to make its requests. If you prefer a separate network client, AskPython’s Requests guide covers query parameters and timeouts.
Build a city forecast with Python
The program resolves a place name first because the forecast service needs coordinates. It then requests the selected daily fields and prints one line per date.
1. Resolve the city name
The forecast service needs latitude and longitude, so the geocoder turns a place name into those coordinates.
The code asks the geocoder for one match, then sends that location’s coordinates to the forecast endpoint. If a city name is common, append a country or region because this example uses the first returned match.
2. Request daily forecast fields
The next request asks for daily high and low temperatures, plus the highest precipitation probability for each day. Setting the timezone to automatic makes the returned dates follow the location’s timezone.
The response stores dates and each requested value in separate arrays. The print loop pairs values by position, so a daily high does not get matched with another date’s low.
3. Print the forecast
The script accepts a city on the command line or asks for one when you run it without an argument. A missing location stops before the forecast request, while a network or response error prints a failure message.
import json
import sys
from urllib.error import URLError
from urllib.parse import urlencode
from urllib.request import urlopen
GEOCODING_URL = "https://geocoding-api.open-meteo.com/v1/search"
FORECAST_URL = "https://api.open-meteo.com/v1/forecast"
def get_json(url, params):
query = urlencode(params)
with urlopen(f"{url}?{query}", timeout=15) as response:
return json.load(response)
def show_forecast(city):
try:
matches = get_json(
GEOCODING_URL,
{"name": city, "count": 1, "language": "en", "format": "json"},
).get("results", [])
if not matches:
raise SystemExit(f"No location found for {city!r}. Add a country or region.")
location = matches[0]
forecast = get_json(
FORECAST_URL,
{
"latitude": location["latitude"],
"longitude": location["longitude"],
"daily": "temperature_2m_max,temperature_2m_min,precipitation_probability_max",
"forecast_days": 3,
"timezone": "auto",
},
)["daily"]
except (URLError, TimeoutError, json.JSONDecodeError) as error:
raise SystemExit(f"Weather request failed: {error}") from error
country = location.get("country", "")
print(f"Daily forecast for {location['name']}, {country}:")
for day, high, low, rain in zip(
forecast["time"],
forecast["temperature_2m_max"],
forecast["temperature_2m_min"],
forecast["precipitation_probability_max"],
):
rain_label = f"{rain}%" if rain is not None else "unavailable"
print(f"{day}: high {high}°C, low {low}°C, rain chance {rain_label}")
print("Source: Open-Meteo")
if __name__ == "__main__":
city = " ".join(sys.argv[1:]) or input("City and country: ").strip()
if not city:
raise SystemExit("Enter a city and country.")
show_forecast(city)
With no city argument, the script prompts for one. I tested the standard-input path with London and saw the same daily rows.
The program uses urlencode so spaces in a city name stay inside the query parameters, and urlopen applies a 15-second timeout to blocking network operations. I saw three dates in the London response, so zip pairs each date with its high, low and rain chance by position.
The command-line city is quoted because it contains spaces. The source line credits Open-Meteo, and the linked licence explains how to attribute its data.
python3 weather_forecast.py "London, United Kingdom"
The London run returned three dates with a daily high, low and precipitation chance. These values come from the forecast response, so a later request can return different figures as the forecast changes.
Handle a missing city or failed request
A place lookup can return no result, while a network request can fail before forecast data arrives.
| What you see | What to do |
|---|---|
| No location found | Add a country or region so the geocoder can choose the intended place. |
| Weather request failed | Check the connection, then retry. Read the message for a network or server error. |
I tested a place with no geocoding result, and the script stopped before requesting the forecast. That keeps an empty search result from turning into a confusing missing-data error later.
I tested a connection refusal by pointing the geocoding request at a closed local port. The same handler printed the underlying error and stopped the program.
The 15-second timeout gives a stalled connection operation a failure path. The handler reports the original error instead of leaving the user without a result.
The handler also catches an unsuccessful server response and invalid JSON, so either failure exits before the program prints a forecast.
Try a name that will not resolve to see the first case.
python3 weather_forecast.py "NinadsImpossibleCity999"

Choose the location before trusting the numbers
The geocoder’s first match determines which coordinates feed every forecast value, so add a country or region when a city name can refer to more than one place. Then run the same program for a city you care about.
python3 weather_forecast.py "Bristol, United Kingdom"
Weather forecast questions
The daily values come from Open-Meteo’s forecast service. This script formats that provider data instead of training a weather model.
Why does the program make two API requests?
The geocoding request turns the city name into latitude and longitude. The forecast request uses those coordinates to fetch daily weather values.
Does this program need an API key?
The Open-Meteo free API does not require a key for non-commercial use. Its weather data require attribution under CC BY 4.0, and commercial use needs a paid plan.
Does this program predict the weather itself?
No. It requests a forecast from Open-Meteo and prints the returned values. It does not train a weather prediction model.

