Skip to content

Python Windy API package for interacting with the Windy API.

License

Notifications You must be signed in to change notification settings

stedonnelly/windy-api

Windy API

Actions Status PyPI version PyPI platforms PyPi downloads

Python Windy API package for interacting with the Windy API. Currently only supports access to the point forecast API.

Features

  • Point Forecast API: Get detailed weather forecasts for any geographic location using latitude/longitude coordinates
  • Multiple Weather Models: Support for 7+ weather forecast models including GFS, ICON EU, GFS Wave, NAM regional models, and CAMS air quality
  • Comprehensive Parameters: Access 20+ weather parameters including temperature, wind, precipitation, humidity, clouds, pressure, CAPE, and more
  • Automatic Validation: Built-in parameter validation ensures only compatible parameters are requested for each model
  • Async Support: Full async/await support for concurrent API requests with get_point_forecast_async()
  • Type Safety: Strongly typed with Pydantic models for reliable data validation and IDE autocomplete
  • Intuitive Data Access: Clean accessor pattern for accessing forecast data - use response.temp["surface"]
  • Clean Representations: Response objects display in a clean, readable format showing only high-level parameters
  • Error Handling: Clear error messages and exceptions for robust application development

Installation

python -m pip install windy_api

From source:

git clone https://github.com/stedonnelly/windy-api
cd windy-api
python -m pip install .

Usage

Quick Start

from windy_api import WindyAPI

# Initialize the client with your API key
api = WindyAPI(api_key="your_api_key_here")

# Get point forecast for San Francisco
response = api.get_point_forecast(
    latitude=37.7749,
    longitude=-122.4194,
    model="gfs",
    parameters=["temp", "wind"]
)

# View the response structure
print(response)
# WindyForecastResponse(
#   timestamps=37 entries,
#   parameters=[temp, wind]
# )

# Access forecast data using clean accessor pattern
print(f"Timestamps: {response.ts}")
print(f"Temperature data: {response.temp['surface']}")
print(f"Temperature unit: {response.temp.units}")
print(f"Available levels: {response.temp.levels()}")

# Access wind components
print(f"Wind U component: {response.wind.u['surface']}")
print(f"Wind V component: {response.wind.v['surface']}")
print(f"Wind unit: {response.wind.u.units}")

Available Weather Models

The following weather forecast models are supported:

  • gfs - Global Forecast System (default)
  • iconeu - ICON EU regional model
  • gfs_wave - GFS Wave model
  • namconus - NAM CONUS regional model
  • namhawaii - NAM Hawaii regional model
  • namalaska - NAM Alaska regional model
  • cams - CAMS air quality model

Available Parameters

Common weather parameters you can request:

  • temp - Temperature
  • wind - Wind speed and direction (returns wind_u and wind_v components)
  • windGust - Wind gusts
  • dewpoint - Dew point temperature
  • precip - Precipitation
  • convPrecip - Convective precipitation
  • snowPrecip - Snow precipitation
  • cape - Convective Available Potential Energy
  • pressure - Atmospheric pressure
  • rh - Relative humidity
  • lclouds, mclouds, hclouds - Low/medium/high clouds
  • gh - Geopotential height
  • ptype - Precipitation type

Model Parameter Checking

Upon submitting a request to the Windy API the request is validated. If a parameter is requested for a model that does not support it, the incompatible parameters will automatically be removed from the request on validation.

Accessing Response Data

The response object provides a clean, intuitive accessor pattern for retrieving forecast data:

Parameter Accessors

For parameters with multiple levels (e.g., temperature at different altitudes):

# Access data at specific levels
temp_surface = response.temp["surface"]  # Temperature at surface
temp_850h = response.temp["850h"]        # Temperature at 850 hPa

# Get the unit (same across all levels)
print(response.temp.units)  # "K" (Kelvin)

# List all available levels
print(response.temp.levels())  # ["surface", "1000h", "950h", ...]

# Iterate over all levels
for level, data in response.temp.items():
    print(f"{level}: {data}")

Surface-Only Parameters

For parameters that only have surface data:

# Access values and units directly
precip_values = response.precip.values
precip_unit = response.precip.units

pressure_values = response.pressure.values
pressure_unit = response.pressure.units

Complex Parameters (Wind, Waves)

Some parameters have multiple components:

# Wind has u (east-west) and v (north-south) components
wind_u = response.wind.u["surface"]
wind_v = response.wind.v["surface"]
print(response.wind.u.units)  # "m*s-1"

# Waves have height, period, and direction
wave_height = response.waves.height.values
wave_period = response.waves.period.values
wave_direction = response.waves.direction.values
print(response.waves.height.units)  # "m"

Detailed Examples

Multiple Parameters

# Request multiple weather parameters
response = api.get_point_forecast(
    latitude=40.7128,
    longitude=-74.0060,
    model="gfs",
    parameters=["temp", "dewpoint", "pressure", "rh", "precip"]
)

# View available parameters
print(f"Available parameters: {response.available_parameters()}")

# Access each parameter using the clean accessor pattern
for i, timestamp in enumerate(response.ts):
    print(f"Time: {timestamp}")
    print(f"  Temperature: {response.temp['surface'][i]} {response.temp.units}")
    print(f"  Dewpoint: {response.dewpoint['surface'][i]} {response.dewpoint.units}")
    print(f"  Pressure: {response.pressure.values[i]} {response.pressure.units}")
    print(f"  Relative Humidity: {response.rh['surface'][i]} {response.rh.units}")
    print(f"  Precipitation: {response.precip.values[i]} {response.precip.units}")

Working with Wind Data

# Wind returns u and v components
response = api.get_point_forecast(
    latitude=51.5074,
    longitude=-0.1278,
    model="gfs",
    parameters=["wind", "windGust"]
)

# Access wind components using the accessor pattern
wind_u_data = response.wind.u["surface"]  # East-west component
wind_v_data = response.wind.v["surface"]  # North-south component
wind_gust_data = response.windGust.values  # Wind gusts

# Get units
print(f"Wind unit: {response.wind.u.units}")
print(f"Gust unit: {response.windGust.units}")

# Check available levels for wind
print(f"Available wind levels: {response.wind.u.levels()}")

Async Usage

import asyncio
from windy_api import WindyAPI

async def get_forecasts():
    api = WindyAPI(api_key="your_api_key_here")

    # Fetch multiple locations concurrently
    responses = await asyncio.gather(
        api.get_point_forecast_async(37.7749, -122.4194, "gfs", ["temp"]),
        api.get_point_forecast_async(40.7128, -74.0060, "gfs", ["temp"]),
        api.get_point_forecast_async(51.5074, -0.1278, "gfs", ["temp"])
    )

    return responses

# Run the async function
responses = asyncio.run(get_forecasts())

Using Environment Variables for API Key

import os
from dotenv import load_dotenv
from windy_api import WindyAPI

# Load API key from .env file
load_dotenv()
api = WindyAPI(api_key=os.getenv("WINDY_API_KEY"))

response = api.get_point_forecast(
    latitude=48.8566,
    longitude=2.3522,
    model="iconeu",  # Use ICON EU model for Europe
    parameters=["temp", "precip", "wind"]
)

Error Handling

from httpx import HTTPStatusError

try:
    response = api.get_point_forecast(
        latitude=37.7749,
        longitude=-122.4194,
        model="gfs",
        parameters=["temp"]
    )
except HTTPStatusError as e:
    print(f"API request failed: {e.response.status_code}")
    print(f"Response: {e.response.text}")
except ValueError as e:
    print(f"Invalid parameters: {e}")

Getting Your API Key

To use this library, you need a Windy API key. Visit Windy API to register and obtain your API key.

Compliance & Terms of Use

Important: This library is not affiliated with or endorsed by Windy.com. It is an unofficial Python wrapper for the Windy Map & Point Forecast API.

By using this library, you agree to comply with all of Windy's official Terms of Use for their Map & Point Forecast API. This wrapper does not modify or relax any of Windy's terms — it simply provides Python bindings for easier integration.

Key Requirements You Must Follow

1. API Key Security

  • You must keep your API key confidential — Never commit it to GitHub, share it publicly, or embed it in client-side applications
  • Private Application keys must be held exclusively and cannot be shared with third parties
  • Use environment variables to store your key securely (see example above)

From Windy's Terms: "API Keys for the Private Application are considered confidential and must be held exclusively. Allowing use of an API Key to a Private Application by any third party is forbidden. Usage of an API Key to a Private Application by any third party shall be considered a material breach of the Agreement."

2. No Data Storage or Extraction

Windy explicitly prohibits storing, extracting, or creating derivative weather databases:

  • ❌ No long-term storage of weather data
  • ❌ No creating weather databases or derived datasets
  • ❌ No bulk downloading or archiving forecast data
  • ❌ No reconstructing original meteorological model data

From Windy's Terms: "Users cannot store, extract, modify, distribute, use the weather data or other content of the Services, create any weather works or databases derived therefrom"

3. Attribution Requirements

If you build an application that displays weather data to end users, you must include:

  • The Windy logo (unscaled, 100% opacity, clickable with hyperlink to https://www.windy.com)
  • Text attribution: "Contains data from the Windy database"
  • Additional data source credits in Help or About sections

Example Attribution (HTML):

<a href="https://www.windy.com" target="_blank">
  <img src="https://www.windy.com/img/logo300.png" alt="Windy Logo" />
</a>
<p>Contains data from the Windy database</p>

4. No Replicating Windy Services

You cannot create applications that:

  • ❌ Replicate Windy's services or aim to compete directly with Windy
  • ❌ Provide Windy API data as a service to third parties
  • ❌ Act as an API proxy or forwarding service

From Windy's Terms: "The User is not allowed to create User Applications that would aim to replicate the Services or other services of the Provider."

5. Usage Limits

  • Trial Version: 500 sessions/day maximum (development purposes only, not for production)
  • Professional Version: 10,000 sessions/day (expandable upon request, requires paid plan)

License Notice

The code in this repository is licensed under the MIT License, but the Windy API data is not. All weather data remains the property of Windy.com and is governed by their Terms of Use.

Best Practices for Compliance

  1. Use environment variables for API keys (never hardcode them)
  2. Cache responsibly — keep cached data in-memory or with very short TTL
  3. Add attribution if you display data to users
  4. Respect rate limits — implement backoff strategies for failed requests
  5. Review Windy's terms before deploying to production

Contributing

See CONTRIBUTING.md for instructions on how to contribute.

License

Distributed under the terms of the MIT license.

About

Python Windy API package for interacting with the Windy API.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages