Overview

The Aemet API, provided by the Spanish State Meteorological Agency (Agencia Estatal de Meteorología), offers programmatic access to a range of meteorological data specific to Spain. Established in 1887, Aemet serves as the national authority for meteorology and climatology in Spain. Its API allows developers to integrate official weather forecasts, real-time observation data, and historical climatological records directly into their applications. The service is primarily designed for use in public service applications, academic research, and personal projects that require detailed and official Spanish weather information.

Developers can retrieve data such as daily and hourly forecasts for specific locations, current weather conditions from observation stations, and historical climate summaries. The API is particularly well-suited for scenarios where geographical precision within Spain is critical, making it a valuable resource for regional planning, agricultural applications, tourism-related services, or environmental monitoring within the Spanish territory. Access to the API requires registration and the use of an API key for authentication, which helps manage usage and maintain service quality. While the primary documentation is in Spanish, the API design follows common RESTful principles, providing JSON responses that are structured and parsable, with clear examples to aid integration.

The Aemet API operates on a free-tier model, allowing unlimited requests within specified rate limits: a maximum of 300 requests per minute and 10 requests per second. This structure supports both occasional data retrieval and more frequent updates for applications that need to stay current with meteorological conditions. For developers who prioritize data accuracy and official sourcing for Spanish weather information, Aemet provides a direct and authoritative channel. While other global weather APIs, like OpenWeather's API documentation, offer broader geographical coverage, Aemet specializes in the specific meteorological nuances and official data sets for Spain, ensuring localized precision and authoritative information.

Key features

  • Detailed Spanish Forecasts: Access daily and hourly weather forecasts for municipalities and specific geographical areas within Spain, including temperature, precipitation probability, wind, and sky state information as detailed in the Aemet API documentation.
  • Real-time Observation Data: Retrieve current meteorological observations from Aemet's network of stations across Spain, providing data points such as temperature, humidity, atmospheric pressure, and wind speed.
  • Climatological Data: Obtain historical climate records and summaries, useful for long-term analysis, academic studies, and understanding climate trends within Spain.
  • Geospatial Data Integration: The API supports queries based on geographical coordinates or specific municipality codes, enabling precise data retrieval for localized applications.
  • JSON Data Format: All API responses are provided in JSON format, facilitating parsing and integration into a wide range of programming languages and platforms.
  • API Key Authentication: Secure access is managed via a required API key, which developers obtain upon registration and include in request headers.
  • Rate-limited Free Access: Provides a free service with generous rate limits (300 requests/minute, 10 requests/second) suitable for most public service and personal projects without incurring costs.

Pricing

As of 2026-05-28, the Aemet API operates on a free-tier model. There are no direct costs associated with using the API, but usage is subject to specific rate limits to ensure service stability and fair access for all users. These limits are designed to accommodate a broad range of applications, from personal projects to public service initiatives, without requiring paid subscriptions or tiered plans.

Feature Details
Access Cost Free
Maximum Requests per Minute 300 requests/minute
Maximum Requests per Second 10 requests/second
API Key Requirement Yes, obtained via registration
Data Volume Unlimited within rate limits

For the most current pricing and usage terms, developers should consult the official Aemet API usage policy.

Common integrations

The Aemet API can be integrated into various applications that require specific meteorological data for Spain. Its JSON output and standard HTTP request methods make it compatible with most programming environments. Common integration scenarios include:

  • Web and Mobile Applications: Displaying current weather, forecasts, or historical climate data on websites or mobile apps focused on Spanish regions, tourism, or local services.
  • Geographic Information Systems (GIS): Enhancing maps with real-time weather overlays or using historical climate data for spatial analysis in platforms like ArcGIS Developer documentation.
  • Agricultural Management Systems: Providing localized weather forecasts crucial for irrigation planning, crop protection, and other agricultural decisions within Spain.
  • Environmental Monitoring Projects: Incorporating official weather observations into systems that track air quality, water levels, or other environmental parameters.
  • Academic Research and Data Analysis: Scientists and researchers can use the API to collect large datasets of Spanish weather information for climatological studies, environmental modeling, or statistical analysis.
  • Smart City Initiatives: Integrating weather data to optimize urban planning, traffic management, or public service delivery in Spanish cities.

Alternatives

While Aemet specializes in Spanish meteorological data, several global and commercial alternatives offer broader geographical coverage and different feature sets:

  • OpenWeather: Provides global weather data, including current weather, forecasts, and historical data, with various API plans.
  • AccuWeather: Offers a comprehensive suite of commercial weather APIs for global forecasts, severe weather alerts, and historical data.
  • Tomorrow.io: Delivers hyper-local, minute-by-minute weather forecasts and global data, primarily for business and enterprise use cases.

Getting started

To begin using the Aemet API, you first need to register on the Aemet OpenData portal to obtain an API key. This key will be used for authenticating your requests. The following Python example demonstrates how to fetch a list of available daily forecast endpoints and then retrieve a specific daily forecast for a Spanish municipality.

First, obtain your API key from the Aemet registration portal after logging in.

import requests
import json

# Replace with your actual Aemet API key
API_KEY = "YOUR_AEMET_API_KEY"

# Base URL for Aemet OpenData API
BASE_URL = "https://opendata.aemet.es/opendata/api/"

headers = {
    "api_key": API_KEY
}

def get_data_from_url(url):
    """Helper function to fetch data from a given Aemet URL."""
    response = requests.get(url, headers=headers)
    response.raise_for_status() # Raise an exception for HTTP errors
    data_url = response.json().get("datos")
    if data_url:
        data_response = requests.get(data_url)
        data_response.raise_for_status()
        return data_response.json()
    return None

# --- Example 1: Get list of daily forecast endpoints ---
print("Fetching list of daily forecast endpoints...")
forecast_list_endpoint = BASE_URL + "prediccion/especifica/municipio/diaria"

try:
    list_response = requests.get(forecast_list_endpoint, headers=headers)
    list_response.raise_for_status()
    list_data = list_response.json()
    print(f"Initial response: {list_data}")

    # The actual data is often at a URL provided in the 'datos' field
    if "datos" in list_data:
        daily_forecast_data_url = list_data["datos"]
        print(f"Retrieving data from: {daily_forecast_data_url}")
        forecast_data = requests.get(daily_forecast_data_url)
        forecast_data.raise_for_status()
        municipality_forecasts = forecast_data.json()

        print("\n--- First 3 Daily Forecast Endpoints ---")
        for i, forecast_item in enumerate(municipality_forecasts[:3]):
            print(f"  {i+1}: Name: {forecast_item.get('nombre')}, ID: {forecast_item.get('id')}")
            # Example: Fetching a specific municipality's forecast
            # print(f"     URL: {forecast_item.get('uri')}")

    else:
        print("No 'datos' URL found in the initial response.")

except requests.exceptions.RequestException as e:
    print(f"An error occurred: {e}")

# --- Example 2: Get specific daily forecast for Madrid (municipality ID: 28079) ---
print("\nFetching daily forecast for Madrid (28079)...")
madrid_forecast_endpoint = BASE_URL + "prediccion/especifica/municipio/diaria/28079"

try:
    madrid_forecast_initial_response = requests.get(madrid_forecast_endpoint, headers=headers)
    madrid_forecast_initial_response.raise_for_status()
    madrid_forecast_data = madrid_forecast_initial_response.json()

    if "datos" in madrid_forecast_data:
        madrid_data_url = madrid_forecast_data["datos"]
        print(f"Retrieving Madrid forecast from: {madrid_data_url}")
        final_madrid_forecast = requests.get(madrid_data_url)
        final_madrid_forecast.raise_for_status()
        madrid_json_data = final_madrid_forecast.json()

        # Print some specific forecast details for Madrid
        if madrid_json_data and isinstance(madrid_json_data, list) and madrid_json_data:
            print("\n--- Madrid Daily Forecast Summary ---")
            forecast_day = madrid_json_data[0] # Assuming the first element contains the main forecast
            print(f"Location: {forecast_day.get('nombre')}, Date: {forecast_day.get('fecha')}")
            if 'prediccion' in forecast_day and 'dia' in forecast_day['prediccion']:
                for day_data in forecast_day['prediccion']['dia']:
                    print(f"  Day: {day_data.get('fecha')}")
                    temperatures = day_data.get('temperatura', {}) # Use .get for safety
                    print(f"    Max Temp: {temperatures.get('maxima')}°C, Min Temp: {temperatures.get('minima')}°C")
                    print(f"    Sky State: {day_data.get('estadoCielo')[0].get('descripcion')}")
        else:
            print("No forecast data available for Madrid.")
    else:
        print("No 'datos' URL found for Madrid forecast.")

except requests.exceptions.RequestException as e:
    print(f"An error occurred while fetching Madrid forecast: {e}")

This script first attempts to fetch a list of specific daily forecast endpoints, which is a common pattern in the Aemet API where an initial call provides a URL to the actual data. Then, it demonstrates how to query the daily forecast for Madrid using its municipality ID (28079). Remember to replace "YOUR_AEMET_API_KEY" with your actual key.