# HS Code Classifier – HTS Tariff & Duty Rate Lookup (`callmefaka/hs-code-classifier`) Actor

Classify product names into official US HTS tariff codes with duty rates and units of quantity. Bulk HS code lookup for importers, e-commerce sellers and customs brokers - data from the USITC Harmonized Tariff Schedule. No API key, no login, JSON/CSV output.

- **URL**: https://apify.com/callmefaka/hs-code-classifier.md
- **Developed by:** [Fakih](https://apify.com/callmefaka) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 product classifieds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## HS / HTS Tariff Code Classifier

**Turn a product name into an official US tariff code — with the duty rate — in one run.**

Give it a list of product names. Get back the official **HTS code**, the **duty rate**, the
**unit of quantity** and the full **classification path** for each one.

Data comes straight from the **USITC Harmonized Tariff Schedule** (`hts.usitc.gov`) — the
official US government source. No API key, no login, nothing to maintain on your side.

***

### Why people use it

Getting the tariff code wrong is expensive. It means shipments held at customs, unexpected
duty bills, penalties and re-filed entries.

The code for a single product is easy to look up by hand. A **catalog of 5,000 SKUs** is not.
This Actor classifies the whole catalog in one run and gives you a code you can defend,
because every answer points back to the exact line of the official schedule it came from.

Built for:

- **E-commerce sellers** shipping into the US who need codes for every SKU
- **Importers and freight forwarders** preparing customs entries
- **Customs brokers** pre-classifying client catalogs
- **Marketplaces and ERP teams** enriching product data with tariff codes

***

### What you get

For every product, one dataset item:

| field | meaning |
|---|---|
| `product` | the name you supplied |
| `htsCode` | best-match HTS code, e.g. `8518.30.20.00` |
| `description` | the official tariff description of that code |
| `dutyRate` | General (MFN) duty rate, e.g. `Free`, `16.5%` |
| `unit` | unit of quantity used for duty calculation, e.g. `No.`, `kg` |
| `confidence` | how decisive the match was, 0–1 |
| `path` | the classification path, chapter → subheading |
| `alternatives` | runner-up codes with their own duty rates |
| `needsDetail` | attributes the schedule splits on, when the name is too vague |
| `source` / `sourceUrl` | where the answer came from, so you can verify it |

***

### Input

```json
{
  "products": [
    "wireless bluetooth earbuds",
    "16oz stainless steel water bottle",
    "men cotton t-shirt"
  ],
  "topN": 3
}
```

| field | type | description |
|---|---|---|
| `products` | array | Product names as they appear on a listing, invoice or storefront. A single string or a comma/newline separated list also works. |
| `topN` | integer | How many alternative codes to return per product (1–10, default 3). |

**Tip:** include material, function or capacity when you know it. `"16oz stainless steel
water bottle"` classifies far better than `"bottle"`.

***

### Output example

```json
{
  "product": "men cotton t-shirt",
  "htsCode": "6109.10.00.12",
  "description": "T-shirts, singlets, tank tops and similar garments, knitted or crocheted:",
  "dutyRate": "16.5%",
  "unit": "doz., kg",
  "confidence": 0.82,
  "path": [
    "T-shirts, singlets, tank tops and similar garments, knitted or crocheted:",
    "Of cotton"
  ],
  "alternatives": [
    {
      "htsCode": "6111.20.20.00",
      "description": "T-shirts, singlets and similar garments, except those imported as parts of sets",
      "dutyRate": "14.9%"
    }
  ],
  "needsDetail": null,
  "source": "USITC Harmonized Tariff Schedule (official, hts.usitc.gov)",
  "sourceUrl": "https://hts.usitc.gov/search?query=men%20cotton%20t-shirt"
}
```

***

### Verified results

Every row below is a real run against the live USITC schedule:

| product | HTS code | duty rate |
|---|---|---|
| wireless bluetooth earbuds | 8518.30.20.00 | Free |
| laptop | 8471.30.01.00 | Free |
| 16oz stainless steel water bottle | 9617.00.10.00 | 7.2% |
| men cotton t-shirt | 6109.10.00.12 | 16.5% |
| vitamin c supplement tablets | 2936.27.00.00 | Free |
| led desk lamp | 9405.11.60.10 | 7.6% |
| led light bulb | 8539.52.00 | 2% |
| coffee maker | 8516.71.00.80 | 3.7% |
| backpack | 4202.92.31.20 | 17.6% |
| sunglasses | 9004.10.00.00 | 2% |
| bluetooth speaker | 8518.21.00.00 | Free |
| pet food dog treats | 2309.10.00.10 | Free |
| silk scarf | 6117.10.40.00 | 1.5% |
| yoga mat | 9506.91.00.30 | 4.6% |
| usb-c charger 65w | 8504.40.95.20 | Free |
| sneakers running shoes | 6404.11.20.71 | 10.5% |

***

### How it works

1. The full HTS (about 35,800 rows, ~12 MB) is downloaded once per run and cached for 12
   hours — so the first call pays the download and the rest are fast.
2. The flat export is rebuilt into a real tree using code-prefix parenting, so inherited
   values (duty rate, unit of quantity) are correct.
3. Products are matched with IDF-weighted term scoring against each row **and its
   ancestors**, so a specific line deep in the schedule is still reachable from a plain
   product name.
4. Everyday language is bridged to tariff language (`earbuds` → `headphones and earphones`,
   `air fryer` → `electric ovens`).
5. Age and gender branches are hard-filtered: a men's product never resolves into a
   babies' garment line.
6. Physical specs decide between sibling branches — `16oz` picks the capacity line,
   `2000W` picks the power line.
7. Rows that describe a **part** of a product are rejected as the product itself.
8. When the schedule cannot be narrowed further, the item carries `needsDetail` naming the
   exact attributes that split the heading, instead of guessing.

***

### Pricing

**Pay per event** — you are charged only for products that actually receive a code.
Failed lookups are free.

| event | price |
|---|---|
| `classification` | $0.02 per product classified |

Classifying a 1,000-SKU catalog costs about **$20**.

***

### FAQ

**Is the data official?**
Yes. It comes from the USITC Harmonized Tariff Schedule, published by the US International
Trade Commission. Every result carries a `sourceUrl` you can open and check.

**Do I need an API key for the data?**
No. Nothing to sign up for.

**What about the duty rates — are they current?**
The schedule is fetched live and cached for 12 hours, so rates track the published schedule.
Note that the rate shown is the **General (MFN)** rate. Preferential rates under a free
trade agreement, and Section 301 additional duties, are not included.

**Can I run this on my whole catalog?**
Yes — pass as many product names as you like. This is the main use case.

**What if a product comes back with a low confidence or `needsDetail`?**
That means the name is too generic for the schedule to decide. Add the attribute the field
names (usually material, capacity or intended use) and run it again.

**Is this a binding customs ruling?**
No. It is a classification aid that gives you the code and the exact schedule line behind
it, so you can verify and file with confidence. A licensed customs broker or CBP ruling is
still the authority for a formal entry.

***

### Local development

```bash
npm install
node test_regression.js   # 14 products with hand-checked codes — must all pass
node test_hints.js        # every curated code hint / synonym vs the live schedule
node test_smoke.js        # 52 products: never crashes, always well-formed output
node test_local.js        # ad-hoc product list
npx apify-cli run         # run as an Actor locally
```

Source layout:

```
main.js                 Actor entry: input -> classify -> dataset -> charge
src/classify.js         classification engine
.actor/actor.json       Actor manifest
.actor/input_schema.json
Dockerfile
```

# Actor input Schema

## `products` (type: `array`):

Product names as they appear on a listing, invoice or storefront. Include material, function or capacity when you know it — "16oz stainless steel water bottle" classifies better than "bottle".

## `topN` (type: `integer`):

How many candidate codes to return per product (the best code plus this many alternatives).

## Actor input object example

```json
{
  "products": [
    "wireless bluetooth earbuds",
    "16oz stainless steel water bottle",
    "men cotton t-shirt"
  ],
  "topN": 3
}
```

# Actor output Schema

## `classifiedProducts` (type: `string`):

One item per input product: HTS code, duty rate, unit of quantity, description, confidence, alternatives and classification path.

## `classifiedProductsCsv` (type: `string`):

Same results as a CSV file, ready to open in Excel or import into a customs/shipping system.

## `consoleRun` (type: `string`):

Open this run in Apify Console to inspect the table view and download the results.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "products": [
        "wireless bluetooth earbuds",
        "16oz stainless steel water bottle",
        "men cotton t-shirt"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("callmefaka/hs-code-classifier").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "products": [
        "wireless bluetooth earbuds",
        "16oz stainless steel water bottle",
        "men cotton t-shirt",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("callmefaka/hs-code-classifier").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "products": [
    "wireless bluetooth earbuds",
    "16oz stainless steel water bottle",
    "men cotton t-shirt"
  ]
}' |
apify call callmefaka/hs-code-classifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,callmefaka/hs-code-classifier"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xudgsKJNtJ1vLbmre/builds/7mk0ORRmMLdQYRHCo/openapi.json
