Customs duty estimate from declared value and category rate
This customs duty estimator applies a category percentage from the rate table you provide to a shipment's declared value.
Run — free
It returns the matched rate and estimated duty, making the calculation easy to inspect and reproduce. The tool does not guess classifications, retrieve government tariffs, add taxes, or decide whether a shipment qualifies for an exemption. Use the rate and declared value applicable to your shipment, then treat the result as a planning estimate rather than a customs assessment.
Prepare the declared value and category table
Start with the declared value that should be used as the duty basis for your planning scenario. Enter it as a nonnegative number, without a currency symbol or thousands separator. Then provide a rate table in which every row has a unique category name and a nonnegative rate_percent value. The category submitted for the shipment must match one table row exactly, including capitalization and spacing. Exact matching prevents the calculator from silently selecting a similar but legally different classification. Rates belong in percentage form: a rate_percent of 7.5 means seven and a half percent, not the decimal 0.075. Keep every monetary amount in the same currency. The calculator does not convert currencies because no exchange-rate source is consulted. Before calculating, verify that the declared value, category classification, and rate table come from sources appropriate to the destination country and shipment date. Tariff schedules, valuation rules, origin preferences, and exemptions can change the applicable basis or percentage, so the quality of the estimate depends on the inputs you supply.
Understand the calculation and result
The estimator searches the supplied table for the exact category, takes that row's duty rate percentage, and multiplies the declared value by the rate divided by one hundred. For example, the underlying relationship is estimated duty equals declared value times rate_percent divided by one hundred. The result includes the original declared_value, the matched category, duty_rate_percent, and estimated_duty so that another person can audit the inputs without reconstructing the lookup. No rounding is imposed by the algorithm. This preserves the deterministic arithmetic result and avoids pretending that every customs authority uses the same minor-unit or rounding convention. Your invoicing or compliance process can round afterward under the applicable rules. A zero rate produces zero estimated duty, while a zero declared value also produces zero. If the requested category is missing, the operation returns an invalid-input error instead of assuming a default rate. Duplicate category rows are rejected as ambiguous, even when their percentages happen to agree, because a table should provide one authoritative rate per category.
Use the estimate within a landed-cost workflow
Use this result as one component of a landed-cost model, not as a final amount payable to customs. Actual import charges may also include import VAT or sales tax, excise duty, anti-dumping measures, brokerage, handling, disbursement fees, minimum charges, and destination-specific assessments. Some authorities calculate duty on a customs value that includes freight, insurance, assists, royalties, or other adjustments rather than the invoice value alone. Preferential origin rules or de minimis thresholds may reduce the charge, but eligibility requires facts this calculator does not collect. For procurement planning, store the supplied rate table beside the estimate so reviewers know which assumption was used. For catalog operations, run one estimate per item or classification and aggregate only after confirming whether customs treats the shipment at line or consignment level. Recalculate whenever the product classification, declared value, origin, destination, currency basis, or effective tariff schedule changes. The browser calculation is convenient for manual checks, while the API costs $0.002 per request when you automate scenarios in checkout, sourcing, or reporting systems.
What you can do with it
Plan a landed-cost scenario
Apply a verified category rate to a supplier's declared value before comparing sourcing options.
Check a product catalog assumption
Confirm the duty amount produced by a category table used in an ecommerce pricing workflow.
Audit a manual calculation
Return the matched percentage beside the computed duty so reviewers can trace the result to its table row.
FAQ
What formula does the estimator use?
It multiplies declared_value by duty_rate_percent and divides by one hundred.
Does it find the correct customs category or tariff rate?
No. You must supply both the shipment category and the applicable category-rate table.
What happens when the category is absent from the table?
The request returns an invalid-input error identifying the missing category; it never substitutes a default rate.
Does estimated duty include tax, brokerage, or shipping fees?
No. It calculates duty only from the declared value and matched percentage you provide.
Which currency should I use?
Use the currency required for your valuation scenario and keep the declared value and resulting duty in that same currency.
How much does the API request cost?
The API costs $0.002 per request. The browser version runs locally for manual estimates.
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/ecom/customs-duty-estimate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"declared_value":1250,"category":"footwear","duty_rates":[{"category":"books","rate_percent":0},{"category":"footwear","rate_percent":12.5}]}'const res = await fetch("https://api.kit.forhosting.com/ecom/customs-duty-estimate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"declared_value": 1250,
"category": "footwear",
"duty_rates": [
{
"category": "books",
"rate_percent": 0
},
{
"category": "footwear",
"rate_percent": 12.5
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/ecom/customs-duty-estimate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"declared_value": 1250,
"category": "footwear",
"duty_rates": [
{
"category": "books",
"rate_percent": 0
},
{
"category": "footwear",
"rate_percent": 12.5
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/ecom/customs-duty-estimate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"declared_value":1250,"category":"footwear","duty_rates":[{"category":"books","rate_percent":0},{"category":"footwear","rate_percent":12.5}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"declared_value":1250,"category":"footwear","duty_rates":[{"category":"books","rate_percent":0},{"category":"footwear","rate_percent":12.5}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/ecom/customs-duty-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
{
"declared_value": 1250,
"category": "footwear",
"duty_rates": [
{
"category": "books",
"rate_percent": 0
},
{
"category": "footwear",
"rate_percent": 12.5
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "ecom.customs_duty_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.
Limits
max_items | 500 |
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. |