Parse, validate and look up HS (Harmonized System) codes — with MFN duty rates for the US, EU, UK and China side by side, and landed-cost math that follows each destination's official dutiable-value rules.
Built while running tariffpedia, a free HS code and import duty lookup covering all four destinations.
Three things go wrong constantly when people calculate import duty by hand:
-
Wrong dutiable base. The US assesses duty on transaction value (the invoice price, usually excluding international freight). The EU, UK and China assess on CIF. Run a US entry through a CIF formula and you overpay; run an EU entry through a US formula and you underpay, then get a bill from customs 8 months later.
-
Missing duty layers. The MFN rate is the opening number, not the total. Depending on origin and product you may also owe Section 301, Section 232, antidumping/countervailing, plus MPF and HMF in the US. A calculator that shows "3%" and stops there is how a 28% CBP bill happens.
-
Stale or unverified codes. The first 6 digits are the international HS code and they change with every WCO review cycle. A code your supplier gave you in 2019 may no longer mean what it meant.
This library handles the parts that are stable and mechanical: parsing, validation, chapter lookup, MFN rates, and the arithmetic. It deliberately does not bundle the political layers (Section 301 lists, Section 232, IEEPA, forced-labor provisions) — those change every few weeks and shipping stale versions of them in a package is worse than not shipping them at all. Pass them in as extraAdValoremPct, or look them up per code at tariffpedia.com.
npm install hs-code-lookupNo runtime dependencies. Node 18+.
import { lookup, landedCost, format, chapterName } from 'hs-code-lookup';
const entry = lookup('610910'); // cotton T-shirts
console.log(entry.description); // 'Of cotton'
console.log(entry.chapterName); // 'Articles of apparel, knitted or crocheted'
console.log(entry.rates.US.mfnPct); // 16.5
console.log(entry.rates.EU.mfnPct); // 12
console.log(entry.rates.UK.mfnPct); // 12
console.log(entry.rates.CN.mfnPct); // 6
const quote = landedCost({
destination: 'US',
unitValue: 10000,
quantity: 1,
freight: 1200,
insurance: 150,
mfnPct: entry.rates.US.mfnPct,
extraAdValoremPct: 25, // e.g. Section 301 — your call, not baked in
brokerage: 65,
});
console.log(quote.duty); // 4150 (16.5% + 25% of 10,000)
console.log(quote.mpf); // 34.64 (0.3464% of value)
console.log(quote.hmf); // 12.5 (0.125%, sea freight only)
console.log(quote.total);import { normalize, isValid, chapter, heading, hs6, format, extract } from 'hs-code-lookup';
normalize('6109.10'); // '610910'
isValid('610910'); // true
isValid('8517620000', 10); // true
chapter('610910'); // '61'
heading('610910'); // '6109'
hs6('8517620000'); // '851762' — trim national suffixes
format('8517620000'); // '8517.62.0000'
extract('HS Code: 6109.10'); // '610910' — pull a code out of invoice textimport { lookup, allCodes, listByChapter, search } from 'hs-code-lookup';
lookup('610910');
// {
// hs6Code: '610910',
// chapter: '61',
// chapterName: 'Articles of apparel, knitted or crocheted',
// description: 'Of cotton',
// coverage: ['US','EU','UK','CN'],
// rates: {
// US: { mfnPct: 16.5, dutyType: 'ad_valorem', specificRule: null, vatPct: 0 },
// EU: { mfnPct: 12, dutyType: 'ad_valorem', specificRule: null, vatPct: 20 },
// ...
// },
// lastVerified: '2026-08-03'
// }
allCodes(); // every HS6 in the bundled sample
listByChapter('85'); // all sampled codes in chapter 85
search('transformer');lookup() returns null for codes not in the sample. Passing an 8- or 10-digit code trims it to 6 digits first.
A note on mfnPct values of 0: zero means duty-free. It does not mean "no data" — a country with no data is simply absent from rates, and the code won't appear in coverage.
import { landedCost, US_MPF_RATE, US_HMF_RATE } from 'hs-code-lookup';| Option | Default | Meaning |
|---|---|---|
destination |
'US' |
'US' | 'EU' | 'UK' | 'CN' |
unitValue |
0 |
Unit price on the invoice |
quantity |
1 |
Number of units |
freight |
0 |
Total international freight |
insurance |
0 |
Total insurance |
mfnPct |
0 |
Base MFN ad-valorem rate (%) |
extraAdValoremPct |
0 |
Additional ad-valorem layers (%) — 301, 232, etc. |
specificDutyPerUnit |
0 |
Specific duty per unit, in the same currency |
vatPct |
0 |
VAT rate (%) |
brokerage |
0 |
Flat broker fee |
mpfMin / mpfMax |
null |
Current-year MPF floor / ceiling (US) |
seaFreight |
true |
Whether HMF applies |
Returns a full breakdown: dutiableBase, dutiableBasis, duty, mpf, hmf, vat, total, plus effectiveDutyRatePct and effectiveLandedRatePct.
MPF and HMF rates are fixed by regulation — 0.3464% (19 CFR 24.23(b)(1)) and 0.125% (19 CFR 24.24). But the minimum and maximum dollar amounts are adjusted annually by CBP, so they aren't hardcoded. Pass the current year's figures via mpfMin / mpfMax if you need billing-grade accuracy.
import { CHAPTERS, chapterName } from 'hs-code-lookup';
chapterName('85'); // 'Electrical machinery and equipment and parts thereof...'
chapterName('85', 'zh'); // 中文章名All 99 WCO chapter titles, English and Chinese.
data/hs6-tariff-sample.csv ships with 375 HS6 codes across 84 chapters — high-traffic codes (consumer electronics, apparel, furniture, EVs, wine, plastics) plus an even spread so every covered chapter has real examples.
Columns:
hs6_code, chapter, description, coverage,
us_mfn_pct, eu_mfn_pct, uk_mfn_pct, cn_mfn_pct,
us_duty_type, eu_duty_type, uk_duty_type, cn_duty_type,
us_specific_rule, eu_specific_rule, uk_specific_rule, cn_specific_rule,
us_vat_pct, eu_vat_pct, uk_vat_pct, cn_vat_pct,
last_verified
duty_type is ad_valorem or specific. Where it's specific, specific_rule carries the human-readable rate (32 EUR/hl, 253 GBP/100kg) — the numeric column alone won't tell you the unit.
Compiled from the official schedules, not resold from a third party:
| Destination | Source |
|---|---|
| US | USITC HTS |
| EU | European Commission TARIC |
| UK | UK Trade Tariff |
| China | Ministry of Finance tariff schedule |
Verified 2026-08-03. Every row in the full dataset is checked against its official source and carries a verification date.
The sample covers 375 codes. The complete set — 7,953 HS6 codes, four destinations, national 8/10-digit subheadings, and the additional-duty layers (Section 301, Section 232, forced-labor provisions, AD/CVD) tracked with their effective dates — lives at tariffpedia.com, free to query in a browser.
Issues and PRs welcome. If you spot a rate that's drifted from the official schedule, open an issue with the source URL and the date you checked.
MIT. The bundled CSV is derived from public government tariff schedules.