Benzo[a]pyrene exposure
Breathing air with 1 ng/m³ of benzo[a]pyrene for 10 years means 20 ng inhaled each day and 73,000 ng in total for a 70 kg adult: a transparent screening dose, not a medical diagnosis. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Concentration
- 1
- Body weight
- 70
- Years
- 10
- Concentration ng m3
- 1 ng/kg
- Body weight kg
- 70
- Inhalation rate m3 day
- 20
- Daily intake ng
- 20
Benzo[a]pyrene is a polycyclic aromatic hydrocarbon released whenever carbon-rich material burns incompletely: diesel and petrol exhaust, wood and coal smoke, tobacco, and high-temperature cooking. Air-quality networks report it in nanograms per cubic metre because even tiny long-term concentrations add up through the lungs. This calculator estimates inhalation exposure from a daily air concentration, a body weight, and a duration in years. It returns the daily intake, the body-weight-normalized daily dose, the cumulative dose over the period, and a lifetime-average daily dose that uses the conventional seventy-year averaging time for carcinogens.
What benzo[a]pyrene inhalation dose means
Benzo[a]pyrene, often abbreviated BaP, is the marker compound used worldwide to represent the carcinogenic fraction of airborne polycyclic aromatic hydrocarbons. It forms in flames and hot exhaust, binds to fine particles, and is inhaled with ordinary outdoor and indoor air. Screening assessments therefore start from a measured or modelled air concentration in nanograms per cubic metre and convert that concentration into a body-weight-normalized dose so two people breathing the same air can be compared.
The conversion used here is the standard inhalation average daily dose: daily intake equals concentration times inhalation rate; daily dose equals that intake divided by body weight; cumulative dose multiplies the daily dose by three hundred sixty-five days and by the number of years of exposure. A second figure, the lifetime-average daily dose, spreads the same intake over a conventional seventy-year lifetime so the number can sit next to slope-factor tables later if a toxicologist needs it.
The calculator does not apply a cancer slope factor, a unit risk, or an occupancy factor: it returns mass of benzo[a]pyrene per kilogram, not a probability of disease. Treat the output as a transparent screening estimate you can audit, not as a medical diagnosis or a regulatory determination of acceptable risk.
Typical ambient annual means sit near or below one nanogram per cubic metre, which is why the default example uses that concentration; a smoky indoor or occupational setting can be many times higher and should use the concentration you actually measured.
Who uses a benzo[a]pyrene dose estimate
Environmental consultancies, municipal air-quality desks and university exposure labs use a deterministic benzo[a]pyrene calculator to turn a monitoring annual mean into a first-pass inhaled dose before anyone opens a full risk-assessment workbook. Occupational hygienists screening a workshop with known BaP in air can swap the default inhalation rate for a task-specific ventilation volume and keep the rest of the contract unchanged. Failed validation does not consume balance.
Keep requests small, pin the rounded fields in tests, and you get a reproducible screening dose without standing up a chemistry model or a geographic information system of your own.
What you can do with it
Ambient air screening from a monitoring mean
Convert an annual benzo[a]pyrene air concentration and resident body weights into daily and cumulative inhaled doses for a first-pass exposure memo.
Indoor wood-smoke or tobacco studies
Estimate occupant-specific BaP dose from a measured indoor concentration, each person's mass, and how many years they lived with the source.
Occupational hygiene first pass
Screen a workshop air concentration against worker body weights and tenure, optionally replacing the default twenty cubic metres per day with a task ventilation rate.
FAQ
How is the benzo[a]pyrene inhalation dose calculated?
Daily intake is concentration (ng/m³) times inhalation rate (m³/day). Daily dose divides that intake by body weight. Cumulative dose multiplies the daily dose by 365 and by years. Lifetime-average daily dose spreads the same intake over a conventional 70-year lifetime.
What units should I use for the air concentration?
Nanograms per cubic metre (ng/m³), the unit air-quality networks use for benzo[a]pyrene. If your lab reports µg/m³, multiply by 1,000 before calling. The returned masses are nanograms and nanograms per kilogram.
What inhalation rate does the calculator assume?
Pass a different finite non-negative rate for children, workers with high exertion, or a study-specific ventilation volume.
Why are negative or non-numeric inputs rejected?
An air concentration, body weight, duration or inhalation rate that is negative or not a finite number cannot describe a physical exposure.
Does this estimate cancer risk, and what does it cost?
No. It returns an inhaled dose in nanograms per kilogram, not a slope-factor risk. The browser tool is free.
Related tools
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/eco/benzoapyrene \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"concentration":1,"body_weight":70,"years":10}'const res = await fetch("https://api.kit.forhosting.com/eco/benzoapyrene", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"concentration": 1,
"body_weight": 70,
"years": 10
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/eco/benzoapyrene",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"concentration": 1,
"body_weight": 70,
"years": 10
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/eco/benzoapyrene", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"concentration":1,"body_weight":70,"years":10}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"concentration":1,"body_weight":70,"years":10}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/eco/benzoapyrene", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"concentration": 1,
"body_weight": 70,
"years": 10
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "eco.benzoapyrene",
"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. |
Technical notes
Negative or non-numeric values fail with invalid_input instead of inventing a dose.
Inputs, defaults, units and error behaviour
Any negative value is rejected: an air concentration, a body mass, a duration or a ventilation rate below zero is not a physical exposure. A body weight of zero is also rejected because dividing intake by zero is undefined. Numbers are rounded to twelve decimal places so goldens and clients compare byte-for-byte across runtimes. Send a JSON object with three required finite numbers: concentration, the daily inhaled air concentration of benzo[a]pyrene in nanograms per cubic metre; body_weight, the body mass in kilograms; and years, the exposure duration. An optional inhalation_rate in cubic metres per day defaults to twenty, the classic adult long-term rate from the EPA Exposure Factors Handbook, so a call that omits it still produces a complete adult screening dose. Each field also accepts a numeric string and a short list of aliases (conc, air_concentration, weight, mass, duration, exposure_years, ir, ventilation) so spreadsheets and forms do not have to rename columns. Non-numeric tokens, empty strings, booleans and missing required fields fail with invalid_input that names the field. On success the response echoes the resolved inputs, then reports daily_intake_ng, daily_dose_ng_per_kg, total_intake_ng, total_dose_ng_per_kg, ladd_ng_per_kg_day, the day count (three hundred sixty-five times years), the unit string ng/kg, the compact formula, and the method label epa_inhalation_add. There is no network lookup, no random draw, and no dependence on the current date: the same inputs always produce the same JSON.
Where a benzo[a]pyrene dose API earns its keep
Indoor-air studies that log wood-stove or tobacco contributions can post many independent tasks, one per occupant weight and duration, and store the returned total_dose_ng_per_kg beside the sample identifier. If you later need cancer risk, feed the lifetime-average daily dose into a slope-factor step that you control; this endpoint stops at mass per kilogram on purpose.