Kullback-Leibler Divergence Calculator for Probability Distributions
The Kullback-Leibler divergence calculator measures how much one discrete probability distribution differs from a reference distribution.
Run — free
Supply two equally sized arrays whose probabilities sum to one, and receive the directed divergence in nats. The calculation is deterministic, uses the natural logarithm, and treats zero probabilities in the first distribution correctly. It also validates the distributions before calculating, so mismatched lengths, invalid totals, negative values, and zero probabilities in the reference distribution are reported clearly instead of producing a misleading infinite or undefined result.
Understand what KL divergence measures
Kullback-Leibler divergence compares a distribution P with a reference distribution Q by calculating the expected logarithmic ratio between their corresponding probabilities. It answers a directed question: how much information is lost when Q is used to represent outcomes that actually follow P? A result of zero means the distributions agree at every position, while a larger positive value indicates a greater discrepancy. The direction matters because swapping P and Q generally changes the answer. This calculator reports D(P || Q), so the first array is the distribution being evaluated and the second is the reference. It uses natural logarithms, which means the output is measured in nats rather than bits. KL divergence is not a distance metric: it is asymmetric and does not satisfy the triangle inequality. Those properties are intentional and make it useful for information theory, statistical inference, model fitting, and comparisons where one distribution has a clear reference role. Read the result as relative information discrepancy, not as an ordinary geometric distance.
Prepare valid probability arrays
Enter the same number of probabilities in both arrays and keep their outcome order aligned. If the first position represents rain in P, the first position must also represent rain in Q. Every value must be a finite number, probabilities cannot be negative, and each complete array must sum to one. The calculator allows a tiny tolerance around one to accommodate normal floating-point representation, but it does not silently normalize arbitrary weights. Normalize counts or scores before submitting them when they are not already probabilities. A zero in P is valid because an impossible observed outcome contributes zero to the sum. A zero in the reference distribution is rejected explicitly. A reference probability of zero makes the logarithmic ratio unavailable for any positive corresponding P value and can imply infinite divergence; this capability uses a strict contract and rejects every zero reference entry so callers never receive a disguised infinity. Clear validation also helps find transposed categories, truncated arrays, percentages entered as whole numbers, and distributions assembled from incompatible label sets before they enter a report or pipeline.
Interpret and use the result responsibly
The returned object contains the divergence and the unit nats. Values near zero indicate that P is well represented by Q, but there is no universal threshold separating a good model from a bad one. The importance of a value depends on the number of categories, the application, the sampling process, and the cost of errors. Compare results produced with the same category definitions and direction. In machine-learning evaluation, you might track divergence across model versions or data windows; in monitoring, you might compare the latest categorical distribution with an approved baseline; in research, you might report it alongside other measures and uncertainty estimates. Do not interpret the result as a probability, percentage, correlation, or symmetric distance. Sampling noise can also create divergence even when two samples come from the same underlying process, so small changes deserve context rather than an automatic alarm. Browser calculation is convenient for individual checks, while an API request costs $0.002 and supports repeatable automation. Because the algorithm is deterministic, identical validated inputs produce identical rounded JSON results across repeated calls.
What you can do with it
Monitor distribution drift
Compare a current categorical distribution with a positive-probability baseline to quantify directional change over time.
Evaluate probabilistic models
Measure how a model reference distribution differs from an observed or target distribution using a standard information-theoretic quantity.
Check compression assumptions
Estimate the information penalty associated with representing outcomes using probabilities that differ from the source distribution.
FAQ
Which direction does the calculator use?
It calculates D(P || Q), from the first distribution to the second, reference distribution. Reversing the arrays can produce a different value.
Why is the result expressed in nats?
The formula uses the natural logarithm. A base-two logarithm would express the result in bits instead.
Can the first distribution contain zero?
Yes. A zero probability in P contributes zero to the divergence by the standard limiting convention.
Why are zero reference probabilities rejected?
A zero in Q makes the logarithmic ratio undefined for a positive corresponding P and may imply infinite divergence. This calculator rejects all zero reference entries explicitly.
Must the probabilities sum exactly to one?
They must sum to one within a small floating-point tolerance. The calculator validates but does not normalize weights automatically.
What does an API calculation cost?
Each API request costs $0.002. You can also run the calculation in the browser for free.
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/stat/kl-divergence \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"distribution":[0.5,0.3,0.2],"reference":[0.4,0.4,0.2]}'const res = await fetch("https://api.kit.forhosting.com/stat/kl-divergence", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"distribution": [
0.5,
0.3,
0.2
],
"reference": [
0.4,
0.4,
0.2
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/stat/kl-divergence",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"distribution": [
0.5,
0.3,
0.2
],
"reference": [
0.4,
0.4,
0.2
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/stat/kl-divergence", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"distribution":[0.5,0.3,0.2],"reference":[0.4,0.4,0.2]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"distribution":[0.5,0.3,0.2],"reference":[0.4,0.4,0.2]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/stat/kl-divergence", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"distribution": [
0.5,
0.3,
0.2
],
"reference": [
0.4,
0.4,
0.2
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "stat.kl_divergence",
"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.
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. |