---
title: How to Build a Weather API with FastAPI and Vercel
description: Provide real-time weather data to apps and websites with a single FastAPI route.
url: /kb/guide/weather-api-with-fastapi
canonical_url: "https://vercel.com/kb/guide/weather-api-with-fastapi"
published: 2025-11-03
last_updated: 2026-06-16
authors: Ricardo Gonzalez , Ismael Rumzan
related:
  - /docs/functions
  - /docs/fluid-compute
  - /docs/frameworks/backend/fastapi
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

To provide real-time weather data, you need to handle API integration, error handling and automatic scaling. With Vercel functions and FastAPI, you can build a production-ready weather API in minutes.

In this tutorial, you will build and deploy a weather API route using the Open-Meteo API that:

1. Accepts a city name and geocodes it to coordinates
   
2. Fetches current weather data from the Open-Meteo API
   
3. Returns temperature, humidity, wind speed, and other weather metrics with optional metric/imperial unit conversion
   

## Prerequisites

- Python 3.10+ installed locally
  
- A Vercel account
  
- Basic understanding of FastAPI and async/await concepts
  

## Build the Weather API

### 1\. Create your FastAPI project

Start with the template [Deploy FastAPI Boilerplate](https://vercel.com/templates/python/fastapi-python-boilerplate). Once your the project is deployed on Vercel, clone the repository locally.

You can also create the project locally using the Vercel CLI with the following command

```bash
vc init fastapi
```

### 2\. Add the httpx dependency

Update your `requirements.txt` to include the `httpx` library for making async HTTP requests:

```text
fastapi
uvicorn
httpx
```

### 3\. Add the Weather endpoint

Open `main.py` and add the necessary imports at the top of the file:

```python
from fastapi import FastAPI, HTTPException, Query
from fastapi.responses import HTMLResponse
import httpx
```

Then add the weather endpoint after your existing routes:

```python
@app.get("/api/weather/{city}")
async def get_weather(city: str, units: str | None = Query(default="metric")):
    """
    Get current weather for a city.
    
    Args:
        city: City name (e.g., "London", "New York")
        units: Temperature units - "metric" (Celsius) or "imperial" (Fahrenheit)
    
    Returns:
        Weather data including temperature, humidity, wind speed, and location info
    """
    # Normalize units parameter
    normalized_units = "imperial" if units == "imperial" else "metric"
    
    async with httpx.AsyncClient() as client:
        # Step 1: Geocode city to get coordinates
        try:
            geo_response = await client.get(
                "https://geocoding-api.open-meteo.com/v1/search",
                params={
                    "name": city,
                    "count": 1,
                    "language": "en",
                    "format": "json"
                }
            )
            geo_response.raise_for_status()
            geo_data = geo_response.json()
            
            if not geo_data.get("results"):
                raise HTTPException(status_code=404, detail=f"City '{city}' not found")
            
            location = geo_data["results"][0]
            name = location["name"]
            country = location["country"]
            latitude = location["latitude"]
            longitude = location["longitude"]
            
        except httpx.HTTPError as e:
            raise HTTPException(status_code=500, detail=f"Geocoding API error: {str(e)}")
        
        # Step 2: Fetch current weather data
        try:
            weather_params = {
                "latitude": latitude,
                "longitude": longitude,
                "current": "temperature_2m,relative_humidity_2m,apparent_temperature,wind_speed_10m",
                "timezone": "auto"
            }
            
            # Add unit parameters for imperial if needed
            if units == "imperial":
                weather_params["temperature_unit"] = "fahrenheit"
                weather_params["wind_speed_unit"] = "mph"
            
            weather_response = await client.get(
                "https://api.open-meteo.com/v1/forecast",
                params=weather_params
            )
            weather_response.raise_for_status()
            weather_data = weather_response.json()
            
            # Return structured weather data
            return {
                "city": name,
                "country": country,
                "latitude": latitude,
                "longitude": longitude,
                "units": normalized_units,
                "current": weather_data["current"]
            }
            
        except httpx.HTTPError as e:
            raise HTTPException(status_code=500, detail=f"Weather API error: {str(e)}")
```

### 4\. Test the route locally

Install the dependencies and launch the application in dev mode:

```bash
pip install -r requirements.txt
vercel dev
```

Use `curl` to test the API route:

```bash
# Test with default metric units
curl http://localhost:3000/api/weather/london

# Test with imperial units
curl "http://localhost:3000/api/weather/san%20francisco?units=imperial"
```

You can also test the endpoint in your browser using the interactive API documentation at `http://localhost:3000/docs`.

### 5\. Deploy to Vercel

- Push the changes to your remote repository or run the `vercel` cli command
  
- Vercel will create a new preview deployment for your to test
  
- Merge to main branch to deploy to Production
  

> When you deploy a FastAPI app to Vercel, the application becomes a single [Vercel Function](https://vercel.com/docs/functions) and uses [Fluid compute](https://vercel.com/docs/fluid-compute) by default.

## Summary

In this tutorial, you’ve built a real-time weather API using FastAPI on Vercel.

You learned to:

- Structure a dynamic API route and integrate external APIs
  
- Deploy the app to Vercel as a function for automatic scaling
  

For a production application, make sure that you use a weather API that will not be rate limited based on the amount of traffic that you are expecting.

## Next steps

### Explore references

- [Explore the FastAPI on Vercel docs](https://vercel.com/docs/frameworks/backend/fastapi)
  
- [FastAPI documentation](https://fastapi.tiangolo.com/)
  
- [Vercel Functions](https://vercel.com/docs/functions)