Python WeatherAPI Integration Tutorial with Requests

Python Weather Integration with WeatherAPI: Complete Developer Tutorial

Python developers looking to add weather functionality to their applications have a powerful ally in WeatherAPI. With over 850,000 developers already using our service, WeatherAPI provides reliable weather data with an average response time of just 200ms across 4M+ locations worldwide.

This tutorial will walk you through integrating WeatherAPI with Python using the popular requests library, covering current weather, forecasts, and proper error handling.

Getting Started

First, you’ll need a WeatherAPI key. Sign up for free to get 100,000 API calls per month with no credit card required.

Install the requests library if you haven’t already:

pip install requests

Basic Setup and Configuration

Let’s start with a basic Python class to handle our WeatherAPI interactions:

import requests
import json
from typing import Dict, Optional

class WeatherAPI:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.weatherapi.com/v1"
        
    def _make_request(self, endpoint: str, params: Dict) -> Optional[Dict]:
        """Make HTTP request to WeatherAPI with error handling"""
        params['key'] = self.api_key
        
        try:
            response = requests.get(f"{self.base_url}/{endpoint}", params=params)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"API request failed: {e}")
            return None

Getting Current Weather Data

The current weather endpoint (/current.json) provides real-time conditions including temperature, wind, humidity, UV index, and air quality data:

def get_current_weather(self, location: str) -> Optional[Dict]:
    """Get current weather for a location"""
    params = {
        'q': location,
        'aqi': 'yes'  # Include air quality data
    }
    
    data = self._make_request('current.json', params)
    if data:
        current = data['current']
        return {
            'location': data['location']['name'],
            'country': data['location']['country'],
            'temperature_c': current['temp_c'],
            'temperature_f': current['temp_f'],
            'condition': current['condition']['text'],
            'humidity': current['humidity'],
            'wind_kph': current['wind_kph'],
            'uv': current['uv'],
            'air_quality': current.get('air_quality', {})
        }
    return None

# Usage example
weather = WeatherAPI('YOUR_API_KEY')
current_weather = weather.get_current_weather('London')
if current_weather:
    print(f"Temperature in {current_weather['location']}: {current_weather['temperature_c']}°C")

Fetching Weather Forecasts

The forecast endpoint (/forecast.json) provides up to 14 days of weather predictions with hourly breakdowns:

def get_forecast(self, location: str, days: int = 3) -> Optional[Dict]:
    """Get weather forecast for specified days (1-14)"""
    if not 1 <= days <= 14:
        raise ValueError("Days must be between 1 and 14")
    
    params = {
        'q': location,
        'days': days,
        'aqi': 'no',
        'alerts': 'yes'  # Include weather alerts
    }
    
    data = self._make_request('forecast.json', params)
    if data:
        forecast_days = []
        for day in data['forecast']['forecastday']:
            forecast_days.append({
                'date': day['date'],
                'max_temp_c': day['day']['maxtemp_c'],
                'min_temp_c': day['day']['mintemp_c'],
                'condition': day['day']['condition']['text'],
                'chance_of_rain': day['day']['daily_chance_of_rain'],
                'sunrise': day['astro']['sunrise'],
                'sunset': day['astro']['sunset']
            })
        
        return {
            'location': data['location']['name'],
            'forecast': forecast_days,
            'alerts': data.get('alerts', {}).get('alert', [])
        }
    return None

Advanced Error Handling and Rate Limiting

Production applications need robust error handling and respect for API limits. Here's an enhanced version with retry logic and better error management:

import time
from functools import wraps

def retry_on_failure(max_retries: int = 3, delay: float = 1.0):
    """Decorator for retrying failed API calls"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                result = func(*args, **kwargs)
                if result is not None:
                    return result
                if attempt < max_retries - 1:
                    time.sleep(delay * (2 ** attempt))  # Exponential backoff
            return None
        return wrapper
    return decorator

class WeatherAPIException(Exception):
    """Custom exception for WeatherAPI errors"""
    pass

# Enhanced request method with detailed error handling
@retry_on_failure(max_retries=3)
def _make_request(self, endpoint: str, params: Dict) -> Optional[Dict]:
    params['key'] = self.api_key
    
    try:
        response = requests.get(
            f"{self.base_url}/{endpoint}", 
            params=params, 
            timeout=10
        )
        
        if response.status_code == 401:
            raise WeatherAPIException("Invalid API key")
        elif response.status_code == 400:
            raise WeatherAPIException("Bad request - check location parameter")
        elif response.status_code == 403:
            raise WeatherAPIException("API key quota exceeded")
        
        response.raise_for_status()
        return response.json()
        
    except requests.exceptions.Timeout:
        print("Request timeout - retrying...")
        return None
    except requests.exceptions.RequestException as e:
        print(f"Network error: {e}")
        return None

Complete Usage Example

# Complete example with error handling
def main():
    # Initialize with your API key
    weather = WeatherAPI('YOUR_API_KEY')
    
    try:
        # Get current weather
        current = weather.get_current_weather('New York')
        if current:
            print(f"Current: {current['temperature_c']}°C, {current['condition']}")
        
        # Get 5-day forecast
        forecast = weather.get_forecast('New York', days=5)
        if forecast:
            for day in forecast['forecast']:
                print(f"{day['date']}: {day['min_temp_c']}°C - {day['max_temp_c']}°C")
                
    except WeatherAPIException as e:
        print(f"WeatherAPI error: {e}")

if __name__ == "__main__":
    main()

Next Steps

This tutorial covered the fundamentals, but WeatherAPI offers much more. Explore historical weather data, marine conditions, astronomy data, and sports information. For production applications, consider our paid plans starting at just $7/month for 3 million calls.

Ready to start building? Get your free API key today and join over 850,000 developers using WeatherAPI worldwide.

Scroll to Top