How to get a USDA hardiness zone from latitude and longitude

Send the coordinate to a lookup API that maps it to a zone. A single HTTP GET to https://coords.zone/api/v1/zone with lat and lng query parameters returns the USDA hardiness zone for that point — for example, latitude 42.36, longitude −71.06 (Boston, Massachusetts) is USDA zone 6b. No API key is required to try it.

The request

curl "https://coords.zone/api/v1/zone?lat=42.36&lng=-71.06"

The response

{
  "lat": 42.36,
  "lng": -71.06,
  "usda_zone": "6b",
  "local_zone": null
}

usda_zone is the USDA zone, from 1a (coldest) to 13b (warmest). local_zone is the equivalent in the country's own hardiness system when it has one — it is null in the United States, because the USDA scale already is the local system. See hardiness zones outside the US for coordinates where it is populated.

You can run that curl without signing up. Unauthenticated requests are capped at 100 per month per IP address; an API key raises that to 1 000 per month at no cost.

In code

It is a plain GET returning JSON, so there is no SDK to install.

JavaScript

const res = await fetch(
  "https://coords.zone/api/v1/zone?lat=42.36&lng=-71.06"
);
const { usda_zone } = await res.json();

console.log(usda_zone); // "6b"

Python

import requests

r = requests.get(
    "https://coords.zone/api/v1/zone",
    params={"lat": 42.36, "lng": -71.06},
)

print(r.json()["usda_zone"])  # 6b

With an API key

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://coords.zone/api/v1/zone?lat=42.36&lng=-71.06"

What the zone number means

A USDA hardiness zone describes the average annual extreme minimum temperature at a location — the coldest night of a typical winter, averaged over 30 years. It is a measure of winter cold only. It says nothing about summer heat, rainfall, humidity, or soil, which is why two places in the same zone can still suit very different plants.

Each numbered zone spans 10 °F (5.6 °C), and the a and b halves split that into 5 °F (2.8 °C) bands. Zone 6b, from the example above, means the coldest night of an average winter falls between −5 °F and 0 °F (−20.6 °C and −17.8 °C).

Zone Average annual minimum (°F) Average annual minimum (°C)
5a −20 to −15 −28.9 to −26.1
5b −15 to −10 −26.1 to −23.3
6a −10 to −5 −23.3 to −20.6
6b −5 to 0 −20.6 to −17.8
7a 0 to 5 −17.8 to −15.0
7b 5 to 10 −15.0 to −12.2

The full scale runs 1a (below −60 °F / −51.1 °C) to 13b (above 65 °F / 18.3 °C) on the same 5 °F step.

Seeing the temperature behind the zone

If you want the number the classification came from rather than the label, /api/v1/climate returns it directly:

curl "https://coords.zone/api/v1/climate?lat=42.36&lng=-71.06"
{
  "lat": 42.36,
  "lng": -71.06,
  "min_temp": -19.34,
  "max_temp": 23.16,
  "frost_last_doy": 95.4,
  "frost_last_date": "Apr 5",
  "frost_first_doy": 312.57,
  "frost_first_date": "Nov 9"
}

min_temp is −19.34 °C, which is −2.8 °F — inside the −5 °F to 0 °F band, which is how the same coordinate classifies as 6b. min_temp and max_temp are truncated here for readability; the API returns full precision.

Where the data comes from

Zones are computed from ERA5-Land, the highest-resolution reanalysis in ECMWF's ERA5 family, over decades of winter records rather than a single cold year. Coverage is global and land-based, so the same call works for a coordinate in any country — not just the United States. It rests on the same climate measure the official USDA map does, but it is computed independently and is not a reproduction of that map.

Next

coords.zone