Display Live Weather Data in WordPress Without a Plugin Using OpenWeatherMap API

Some projects require only one or two weather values on the page — current temperature, an icon, a short description. Installing a full-featured weather plugin for that is overkill. The OpenWeatherMap API is free for up to 60 calls per minute and returns clean JSON that PHP can consume directly.

Problem: A WordPress site needs to display current weather conditions for a specific location, updated automatically, without a third-party plugin or an unstyled <iframe> widget.

Solution: Register for a free OpenWeatherMap API key, fetch current conditions via wp_remote_get() in a shortcode callback, decode the JSON response, and store the result in a transient with a 30-minute expiry to stay within the free-tier rate limit.

Register for a free API key at openweathermap.org, then use one of the functions below.

Current weather for a single location:

<?php
function get_current_weather( $lat, $lng ) {
    $api_key  = 'YOUR_API_KEY';
    $units    = 'metric'; // metric = Celsius, imperial = Fahrenheit
    $api_url  = add_query_arg( [
        'lat'   => $lat,
        'lon'   => $lng,
        'units' => $units,
        'appid' => $api_key,
    ], 'https://api.openweathermap.org/data/2.5/weather' );

    $response = wp_remote_get( $api_url, [ 'timeout' => 10 ] );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    $data = json_decode( wp_remote_retrieve_body( $response ), true );

    return [
        'temperature' => round( $data['main']['temp'] ),
        'description' => ucfirst( $data['weather'][0]['description'] ),
        'icon'        => 'https://openweathermap.org/img/wn/' . $data['weather'][0]['icon'] . '@2x.png',
    ];
}

5-day forecast (one entry per day):

<?php
function get_weather_forecast( $lat, $lng, $days = 5 ) {
    $api_key = 'YOUR_API_KEY';
    $api_url = add_query_arg( [
        'lat'     => $lat,
        'lon'     => $lng,
        'units'   => 'metric',
        'exclude' => 'minutely,hourly,alerts',
        'appid'   => $api_key,
    ], 'https://api.openweathermap.org/data/2.5/onecall' );

    $response = wp_remote_get( $api_url, [ 'timeout' => 10 ] );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    $data   = json_decode( wp_remote_retrieve_body( $response ), true );
    $days   = max( 1, min( (int) $days, 7 ) );
    $result = [];

    for ( $i = 0; $i < $days; $i++ ) {
        $day           = $data['daily'][ $i ];
        $result[ $i ] = [
            'date'        => date( 'D, M j', $day['dt'] ),
            'temp'        => round( $day['temp']['day'] ),
            'description' => ucfirst( $day['weather'][0]['description'] ),
            'icon'        => 'https://openweathermap.org/img/wn/' . $day['weather'][0]['icon'] . '@2x.png',
        ];
    }

    return $result;
}

Cache the API response in a WordPress transient to avoid hitting the rate limit on every page load:

<?php
function get_weather_cached( $lat, $lng ) {
    $cache_key = 'weather_' . md5( $lat . $lng );
    $cached    = get_transient( $cache_key );

    if ( $cached !== false ) {
        return $cached;
    }

    $weather = get_current_weather( $lat, $lng );

    if ( $weather ) {
        set_transient( $cache_key, $weather, 30 * MINUTE_IN_SECONDS );
    }

    return $weather;
}

NOTE: The free OpenWeatherMap tier allows 60 API calls per minute. Without caching, a busy page can exhaust this limit quickly. Always wrap weather API calls in a transient with a reasonable TTL (30–60 minutes is typical for weather data).