Stacked ND Filters Total Stops Calculator
When neutral density filters are stacked, their light reductions in stops add together.
Run — free
This calculator accepts two or more ND filter ratings expressed in stops and returns the combined reduction, the corresponding exposure-time multiplier, and the percentage of light that reaches the camera. It is useful when planning long exposures, combining filters already in a camera bag, or checking whether a proposed stack is practical before attaching anything to the lens. The calculation is deterministic and does not depend on camera brand, lens size, or filter diameter.
Add filter ratings in stops
Enter the stop rating printed on, or documented for, each neutral density filter in the stack. A three-stop filter combined with a six-stop filter produces nine stops of total reduction because photographic stops are logarithmic units designed to be added. The order of the filters does not change the mathematical total, although the physical order can still affect reflections, flare, or handling. Use the actual stop specification whenever possible rather than relying only on a product name such as ND64, because naming conventions can vary and real filters may deviate slightly from their nominal values. Decimal stop ratings are accepted, which is helpful for graduated, variable, measured, or unusually rated filters. Zero is also accepted for completeness, though it adds no reduction. The calculator requires at least two entries because its purpose is to evaluate a stack rather than a single filter. It supports up to twenty values, well beyond a practical photographic stack while keeping the input deliberately bounded and easy to validate.
Interpret the combined exposure effect
The total-stops result tells you the combined reduction directly, while the exposure multiplier translates that result into a practical exposure adjustment. Every additional stop halves the light and therefore doubles the exposure time needed to record the same brightness, assuming aperture and ISO remain unchanged. A total of nine stops corresponds to a multiplier of 512, so an unfiltered shutter time of one one-hundred-and-twenty-fifth of a second becomes roughly four seconds after multiplication. The returned light-transmission percentage expresses the same relationship from the opposite direction: it reports how much incident light remains after the idealized stack. These figures describe ideal stop values and are best treated as a planning baseline. Manufacturing tolerances, color casts, metering behavior, reciprocity characteristics, and ambient light changes can shift the final exposure. Take a test frame and inspect the histogram when accuracy matters. The calculator does not recommend an aperture, ISO, or shutter time because those choices depend on your original exposure and creative intent.
Plan a stack before mounting it
Use the total to decide whether stacking is preferable to carrying one stronger filter. Stacking offers flexibility: filters you already own can create several combined strengths, and removing one element quickly changes the reduction. The tradeoff is optical and mechanical rather than mathematical. Multiple filter rings can increase the chance of vignetting on wide-angle lenses, create more reflective surfaces, make flare more visible, and complicate removal if threads bind. Very strong stacks can also make composing or autofocus difficult because so little light reaches the viewfinder or sensor. Plan composition and focus first when necessary, then mount the filters and apply the calculated multiplier to the baseline shutter time. If a variable ND filter is included, use its selected or measured stop value, not merely its advertised range. Avoid combining filters in ways the manufacturers warn against, and watch for uneven polarization artifacts. For automated use, the same calculation is available through the API for $0.002 per request; the browser calculation remains suited to quick field planning.
What you can do with it
Plan a long exposure
Combine the filters in your bag and find the total reduction before converting a metered shutter time into a longer exposure.
Compare stack options
Check whether two moderate filters provide the same nominal reduction as one stronger filter you are considering carrying or buying.
Document a repeatable setup
Record the combined stops, multiplier, and transmission for a filter stack used in a repeatable landscape or studio workflow.
FAQ
How are stacked ND filter stops combined?
Add the stop values. For example, a two-stop filter and a three-stop filter produce a five-stop reduction.
Does the order of the filters change the total stops?
No. Addition gives the same nominal total in any order, although physical order may affect reflections, vignetting, or handling.
Can I enter fractional stop values?
Yes. Each entry may be a finite non-negative number, so decimal and fractional-stop measurements are supported.
Is the result exact for real filters?
It is exact for the stop ratings supplied. Real transmission can differ because of manufacturing tolerances, spectral response, color cast, and other optical effects.
What does the exposure multiplier mean?
Multiply the unfiltered exposure time by this value to preserve nominal brightness while keeping aperture and ISO unchanged.
What does an API calculation cost?
Each API request costs $0.002. The calculation uses no network services or camera data.
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/hobby/photo-nd-filter-stack \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"stops":[3,6]}'const res = await fetch("https://api.kit.forhosting.com/hobby/photo-nd-filter-stack", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"stops": [
3,
6
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/hobby/photo-nd-filter-stack",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"stops": [
3,
6
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/hobby/photo-nd-filter-stack", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"stops":[3,6]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"stops":[3,6]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/hobby/photo-nd-filter-stack", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"stops": [
3,
6
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "hobby.photo_nd_filter_stack",
"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. |