Why batch=true Is the Most Underused Feature in WeatherAPI for Multi-Location Apps

If you’re making one API call per location, you’re doing it the hard way. The moment an app needs weather for more than a handful of coordinates — a fleet management dashboard, a multi-depot logistics tool, an agriculture platform watching 50 fields — the loop-and-call approach turns into a quota problem, a latency problem, and a rate-limit problem simultaneously.

WeatherAPI supports bulk/batch requests. Most developers using it for multi-location work never reach for it. Here’s what it actually does, when it genuinely helps, and where it still won’t save you.

What the Bulk Endpoint Actually Does

The /v1/current.json and /v1/forecast.json endpoints accept a q parameter as a pipe-delimited list of location strings — lat/lon pairs, city names, IATA codes, or any mix. A single HTTP request returns a JSON array with one result object per location, processed server-side in parallel. You pay one API call from your quota, not N.

That’s the core mechanic. It sounds simple because it is, but the implications ripple out further than they first appear.

The Quota Math Changes Your Architecture

Say you’re on a plan with 1 million calls/month and you need current conditions every 10 minutes for 200 locations. Individual calls: 200 × 6 per hour × 24 × 30 = 8.64 million calls/month. Way over. Batched into one call per cycle: 6 × 24 × 30 = 4,320 calls/month. Under by three orders of magnitude.

That’s not a marginal improvement — it changes which plan tier the product needs to sit on at all. For free-tier users especially, this is often the difference between a prototype that works and one that hits the wall by day two.

Latency Is the Second Win, and It’s Not Obvious Why

Making 200 sequential HTTP requests from a backend server isn’t just slow — it’s fragile. Each round-trip adds TCP overhead, TLS handshake cost degrades if connections aren’t pooled correctly, and a single upstream hiccup anywhere in the sequence stalls everything downstream.

Even with connection pooling and async patterns, parallel individual requests mean you’re still waiting on the slowest response in the set. One batch call hands that problem to the API server, which resolves all locations internally before sending a single response back. You get the worst-case latency of one request, not the accumulated tail latency of N.

In a .NET environment, the difference between firing HttpClient.GetAsync() in a loop versus a single awaited batch call shows up not just in raw milliseconds but in connection pool exhaustion risk under load. That’s the failure mode that tends to surface in production rather than in testing.

How to Structure the Request

Locations go into a pipe-delimited q parameter. A minimal example in Python:

import requests

API_KEY = "your_key_here"
locations = ["51.5074,-0.1278", "55.8642,-4.2518", "48.8566,2.3522", "40.7128,-74.0060"]

params = {
    "key": API_KEY,
    "q": "|".join(locations),
    "aqi": "no"
}

resp = requests.get("https://api.weatherapi.com/v1/current.json", params=params)
data = resp.json()  # list of location result objects

for result in data:
    loc = result["location"]
    current = result["current"]
    print(f"{loc['name']}: {current['temp_c']}°C, {current['condition']['text']}")

Each object in the response has the same schema as a normal single-location response — location, current, and if you’re hitting /forecast.json, the forecast block. No structural surprises. You can deserialize into the same model class you already use for single-location responses.

Where Batching Breaks Down

It’s not a universal fix. A few places where it gets messy:

Error handling per location

With individual requests, a 400 or 404 for one bad coordinate is isolated. With a batch, you need to check each result object for error flags rather than relying on the HTTP status code alone. A single unresolvable location in a batch of 50 can silently drop or fail that entry while the rest succeed. Your parsing code needs to handle partial success — checking resp.status_code == 200 and moving on isn’t enough.

Caching granularity

If you cache a batch response as a single blob, you can’t serve a cached result for London while refreshing New York. You either split the response on write — one cache key per location — or you forfeit location-level freshness control entirely. For most apps, splitting on write is the right move: iterate the response array after the batch call and write each result into Redis or KeyDB under its own key. The read path then doesn’t need to know the data came from a batch call at all.

Batch size limits

There’s a practical ceiling on how many locations fit in a single request before the server rejects it or the response size becomes unwieldy. For very large location sets you’ll still need to chunk into groups and make several batch calls. That’s still dramatically better than one-per-location, but your calling code needs clean chunking logic rather than assuming one batch covers everything.

A Note on Forecast Batch Requests

Batching works on /forecast.json too, which is where the data-volume savings compound. A 3-day hourly forecast per location is a fat response. Fifty of them in one call means pulling roughly 50x the payload in a single round-trip. That’s fine if you need all of it — but be deliberate about the days parameter, and strip aqi and alerts from the response if you don’t use them. Unnecessary fields inflate response size, and at batch scale that matters for both transfer time and parsing overhead.

When Individual Calls Still Make More Sense

If your app is user-driven — one user requesting weather for one location on demand — batching adds complexity with no benefit. The overhead of grouping, chunking, and splitting responses only pays off when you have a known, repeating set of locations you control. Background jobs, scheduled polling, server-side aggregation: that’s the right context. Don’t retrofit it onto a low-volume request-response flow where it doesn’t fit.

If a well-structured batch implementation is still pushing against quota limits, the question shifts from “how do I call the API more efficiently” to “how do I cache more aggressively.” Forecast data for most locations doesn’t change materially in under 15 minutes. If your polling cycle is shorter than that, you’re spending quota to retrieve data you already have.

Scroll to Top