Koppen Climate Classification Calculator
The Koppen climate classification calculator converts twelve monthly mean temperatures and twelve monthly precipitation totals into a familiar Koppen-Geiger code such as Af, Cfb, BWh, or ET.
Run — free
It applies the aridity test first, then evaluates tropical, temperate, continental, or polar temperature limits and the relevant precipitation seasonality. Choose the correct hemisphere so summer and winter rainfall tests use the right six-month periods. The result includes the class name and useful annual and monthly diagnostics, making the decision easy to inspect instead of presenting only an unexplained code.
Prepare monthly climate normals in calendar order
Provide exactly twelve monthly mean temperatures in degrees Celsius and exactly twelve monthly precipitation totals in millimetres. Both arrays must run from January through December. Climate normals calculated across several decades are the most meaningful inputs because the Koppen-Geiger system describes climate, not the weather of one unusual year. Precipitation cannot be negative, while temperature may legitimately fall below zero. Set the hemisphere to north or south so the calculator assigns April through September and October through March to the proper summer and winter half-years. This distinction matters for the dry-summer and dry-winter letters and for the precipitation distribution used by the aridity threshold. The calculator deliberately rejects arrays with missing or extra entries rather than guessing which month is absent. It also rejects nonnumeric values and non-finite numbers. Before submitting data copied from a spreadsheet, confirm that monthly precipitation totals have not been supplied in centimetres and that temperatures are monthly means rather than daily maxima. Consistent units and calendar order are essential because every later threshold depends on them.
Understand the threshold sequence
Classification follows a decision tree. Dry B climates are tested first because aridity depends on both annual temperature and whether precipitation is concentrated in summer, winter, or neither half-year. Annual precipitation below half the aridity threshold is desert BW; precipitation between half and the full threshold is semi-arid BS. The annual mean temperature then supplies the hot h or cold k suffix. If the site is not dry, every month at or above eighteen degrees Celsius produces a tropical A climate. Tropical rainfall determines rainforest f, monsoon m, or a seasonally dry w or s class. Polar E climates have no month warmer than ten degrees: an annual maximum below zero is ice cap EF, otherwise it is tundra ET. Remaining sites enter temperate C when the coldest month is above zero or continental D when it is zero or below. Summer dryness, winter dryness, and year-round moisture determine the second letter. The warmest month and count of months above ten degrees determine the final heat letter, including the extremely cold continental d subtype.
Interpret and compare the result responsibly
Use the returned code as a reproducible summary of the supplied monthly series. The accompanying climate name makes the code readable, while annual mean temperature, annual precipitation, the computed aridity threshold, and the coldest and warmest monthly means show why major branches were selected. A boundary result deserves special care: a small difference caused by the normal period, station elevation, missing-data treatment, or gridded-data interpolation can move a location into a neighbouring class. Different published Koppen-Geiger maps may also use a minus-three-degree boundary between C and D climates; this calculator uses the widely adopted zero-degree boundary and states that choice explicitly. It does not infer a location, correct measurements, adjust for elevation, or assess future climate projections. For comparisons, use datasets with the same normal period, spatial resolution, units, and missing-data method. The calculation is deterministic, so identical arrays and hemisphere settings always return identical results. Browser use is free, while automated API requests cost $0.002 each. That makes the tool suitable for both individual station checks and repeatable processing pipelines without concealing the classification logic.
What you can do with it
Classify a weather station
Turn published monthly climate normals into a documented Koppen-Geiger code with threshold diagnostics.
Check a mapped climate class
Compare station or gridded monthly values with a class shown on a climate map and investigate boundary differences.
Standardize a research pipeline
Apply one deterministic rule set to many prepared locations while retaining consistent output fields for analysis.
FAQ
Which temperature boundary separates C and D climates?
The calculator uses a coldest-month boundary of zero degrees Celsius: above zero is C, while zero or below is D when the other requirements are met.
Why must I choose a hemisphere?
Dry-summer and dry-winter rules compare opposite six-month seasons. The hemisphere determines which calendar months belong to summer.
Can I use data from a single year?
The calculation will run, but a multi-decade climate normal is preferable because the system describes long-term climate rather than one year's weather.
Why is a dry climate checked before a tropical or temperate climate?
That is part of the Koppen-Geiger decision order. A location meeting the aridity threshold belongs to group B even when its temperatures could otherwise fit another group.
What happens if either array has fewer or more than twelve values?
The request fails with an invalid-input error identifying the array that must contain exactly twelve monthly values.
How much does an API classification cost?
Each API request costs $0.002. The same deterministic calculation is also available free in the browser.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/earth/koppen-classification \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"temperatures_c":[26.5,26.8,27.1,27.3,27.1,26.6,26.2,26.3,26.5,26.7,26.6,26.4],"precipitation_mm":[220,210,240,260,250,190,170,160,180,210,230,240]}'const res = await fetch("https://api.kit.forhosting.com/earth/koppen-classification", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"temperatures_c": [
26.5,
26.8,
27.1,
27.3,
27.1,
26.6,
26.2,
26.3,
26.5,
26.7,
26.6,
26.4
],
"precipitation_mm": [
220,
210,
240,
260,
250,
190,
170,
160,
180,
210,
230,
240
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/earth/koppen-classification",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"temperatures_c": [
26.5,
26.8,
27.1,
27.3,
27.1,
26.6,
26.2,
26.3,
26.5,
26.7,
26.6,
26.4
],
"precipitation_mm": [
220,
210,
240,
260,
250,
190,
170,
160,
180,
210,
230,
240
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/earth/koppen-classification", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"temperatures_c":[26.5,26.8,27.1,27.3,27.1,26.6,26.2,26.3,26.5,26.7,26.6,26.4],"precipitation_mm":[220,210,240,260,250,190,170,160,180,210,230,240]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"temperatures_c":[26.5,26.8,27.1,27.3,27.1,26.6,26.2,26.3,26.5,26.7,26.6,26.4],"precipitation_mm":[220,210,240,260,250,190,170,160,180,210,230,240]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/earth/koppen-classification", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"temperatures_c": [
26.5,
26.8,
27.1,
27.3,
27.1,
26.6,
26.2,
26.3,
26.5,
26.7,
26.6,
26.4
],
"precipitation_mm": [
220,
210,
240,
260,
250,
190,
170,
160,
180,
210,
230,
240
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "earth.koppen_classification",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_items | 12 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |