Beer Bitterness IBU Estimator
This beer bitterness IBU estimator calculates the approximate International Bitterness Units contributed by a hop addition.
Run — free
Enter the hop weight in grams, the hop's alpha acid percentage, its boil time in minutes, and the final beer volume in liters. The calculator applies the Tinseth utilization curve at a fixed reference wort gravity of 1.050, making the result deterministic from exactly those four inputs. It is useful for recipe planning and comparison, while remaining an estimate rather than a laboratory measurement of finished beer.
What the IBU estimate represents
International Bitterness Units express the approximate concentration of bitter iso-alpha acids in beer, conventionally treated as milligrams per liter. This estimator begins with the mass of hops and their labeled alpha acid percentage, then estimates how much of that potential bitterness becomes soluble during the boil. Longer boils generally extract and isomerize more alpha acids, but the gain slows over time rather than increasing in a straight line. The final volume matters because the same extracted amount produces a lower concentration in a larger batch. The returned IBU is therefore a recipe calculation, not a promise about sensory perception. Malt sweetness, water chemistry, yeast, hop products, fermentation losses, aging, and measurement practices can all change how bitter a beer tastes or how a laboratory reports it. Use the number as a consistent planning reference for comparing recipes, adjusting additions, and checking whether an ingredient change moves bitterness in the intended direction. For a finished commercial specification, confirm the result with appropriate brewing records or laboratory analysis.
How the calculation works
The calculation uses the Tinseth utilization model. Its time factor follows a saturating curve: utilization rises quickly during the earlier part of the boil and then approaches a plateau. Classic Tinseth calculations also include wort gravity because denser wort tends to reduce utilization. This capability deliberately accepts only the four requested recipe inputs, so it applies a fixed reference specific gravity of 1.050 and reports that assumption in every successful result. It multiplies hop weight by alpha acid as a decimal, predicted utilization, and the gram-to-milligram conversion, then divides by volume in liters. The result is rounded to two decimal places, while utilization is returned as a percentage for transparency. A zero-minute addition is valid and produces zero calculated bitterness under this boil model. Whirlpool, hop-stand, and dry-hop contributions are not modeled because their temperature and process details require different assumptions. If your wort gravity differs substantially from 1.050, interpret the estimate as a standardized comparison rather than a fully customized brewhouse prediction.
Using the estimator in recipe design
For one hop addition, enter the exact weight, the alpha acid value printed for that hop lot, the scheduled boil duration, and the volume of beer the contribution will be distributed through. Alpha acid varies between varieties, harvests, storage conditions, and packages, so the lot-specific label is more useful than a generic variety average. When a recipe contains several additions, calculate each addition separately and add their estimated IBU values; this preserves the different utilization associated with each boil time. Keep volume definitions consistent when comparing versions of a recipe, particularly when one record uses kettle volume and another uses packaged volume. This estimator uses the volume you provide without correcting for evaporation, trub, transfer loss, or fermentation loss. It is well suited to quick formulation checks, brewing software cross-checks, educational examples, and deterministic automated workflows. API use costs $0.002 per request. Invalid, missing, nonnumeric, infinite, or out-of-range inputs return an input error instead of silently producing a misleading value, which makes the function safe to place inside repeatable recipe pipelines.
What you can do with it
Plan a single hop addition
Estimate the bitterness contribution of a measured hop charge before finalizing a brew-day recipe.
Compare hop substitutions
Check how a different alpha acid percentage or hop weight changes the standardized IBU estimate.
Audit recipe calculations
Recalculate additions with a transparent deterministic method when reviewing brewing notes or software output.
FAQ
What formula does the estimator use?
It uses the Tinseth utilization curve with a fixed reference wort gravity of 1.050, then converts the estimated iso-alpha acid contribution to milligrams per liter.
Why is original gravity not an input?
The capability is designed around four inputs, so it standardizes gravity at 1.050. This makes comparisons deterministic but may differ from a gravity-adjusted recipe calculation.
Can I calculate several hop additions?
Yes. Run each addition with its own weight, alpha acid percentage, and boil time, then add the returned IBU estimates.
Does this estimate dry-hop bitterness?
No. The utilization model covers boiled hops. Dry hopping and whirlpool additions need temperature, duration, and process assumptions that are outside this input contract.
Is calculated IBU the same as perceived bitterness?
No. Sweetness, water chemistry, hop character, fermentation, and aging affect perception, while this result estimates iso-alpha acid concentration from recipe inputs.
What does an API request cost?
Each API request costs $0.002. The same deterministic calculation can also run 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/cook/beer-ibu-estimate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"hop_weight_g":28,"alpha_acid_percent":5.5,"boil_time_minutes":60,"volume_liters":20}'const res = await fetch("https://api.kit.forhosting.com/cook/beer-ibu-estimate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"hop_weight_g": 28,
"alpha_acid_percent": 5.5,
"boil_time_minutes": 60,
"volume_liters": 20
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/cook/beer-ibu-estimate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"hop_weight_g": 28,
"alpha_acid_percent": 5.5,
"boil_time_minutes": 60,
"volume_liters": 20
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/cook/beer-ibu-estimate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"hop_weight_g":28,"alpha_acid_percent":5.5,"boil_time_minutes":60,"volume_liters":20}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"hop_weight_g":28,"alpha_acid_percent":5.5,"boil_time_minutes":60,"volume_liters":20}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/cook/beer-ibu-estimate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"hop_weight_g": 28,
"alpha_acid_percent": 5.5,
"boil_time_minutes": 60,
"volume_liters": 20
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "cook.beer_ibu_estimate",
"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. |