# HS Code Lookup API - Tariff, Duty Rates, Commodity Codes (`martin10291/hs-code-tariff-lookup`) Actor

HS code lookup API, no key: product keyword to ranked HS / commodity codes, and any code to its full description chain, import duty (third-country), VAT, preferential rate for an origin country, quotas, anti-dumping and other measures for the UK tariff and the EU Common Customs Tariff. Code validati

- **URL**: https://apify.com/martin10291/hs-code-tariff-lookup.md
- **Developed by:** [Martin Petrov](https://apify.com/martin10291) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Code Lookup API - Tariff, Duty Rates, Commodity Codes

**Problem:** your checkout, customs form, freight quote or AI agent needs the right HS / commodity code for a product and the import duty and VAT that apply to it. Classification lists are huge, tariff sites have no simple API, and the popular HS code APIs time out or fail.

**This API:** one JSON call, no API key, official HMRC tariff data, answers in milliseconds from a 24-hour cache (first lookup of a code ~0.1 s).

- **search:** product keyword (`cotton t-shirt`, `lithium battery`) -> ranked commodity codes with HS6, description chain, declarable flag and score.
- **code:** any 2-10 digit code (`6109.10`, `6109100010`) -> full chain section > chapter > heading > subheading > commodity, **third-country duty**, **VAT**, **preferential rate and the duty that applies for an origin country** (`origin: "CN"`), quotas, anti-dumping/countervailing duties, controls, supplementary unit. A non-declarable code returns its declarable children with their duties.
- **validate:** up to 100 codes -> exists, declarable, normalized code, closest parent.
- **bulk:** up to 50 lookups in one call; a bad query returns an error row, the others still answer.
- **Markets:** `UK` = UK Global Tariff; `EU` = EU Common Customs Tariff (as published by the UK Trade Tariff Northern Ireland service; EU import VAT is set per member state, so EU rows carry a VAT note instead of one rate).
- **Monitor:** `onlyNew` + `monitorId` returns a code again only when its duty, VAT or origin rate changed.

### Example (API)

```bash
curl -X POST "https://api.apify.com/v2/acts/martin10291~hs-code-tariff-lookup/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "code", "code": "6109100010", "market": "EU", "origin": "CN"}'
```

Output row (measured 2026-11-14, shortened):

```json
{"code": "6109100010", "hs6": "610910", "description": "T-shirts",
 "chain": "Section XI Textiles and textile articles > 61 Articles of apparel and clothing accessories, knitted or crocheted > 6109 T-shirts, singlets and other vests, knitted or crocheted > Of cotton > T-shirts",
 "declarable": true, "origin": "CN", "originName": "China",
 "thirdCountryDuty": {"rate": "12.00%", "ratePercent": 12.0, "measureType": "Third country duty"},
 "originDuty": {"rate": "12.00%", "ratePercent": 12.0, "basis": "thirdCountry"},
 "preferentialNote": "No tariff preference for origin CN on this code; the third-country duty applies.",
 "market": "EU", "source": "UK Trade Tariff API (HMRC), Open Government Licence v3.0 (XI service = EU Common Customs Tariff)"}
```

More inputs:

- `{"mode": "search", "q": "cotton t-shirt"}` -> 6109100010 T-shirts (score 100), 6109100090 ...
- `{"mode": "code", "code": "8517130000", "origin": "VN"}` -> smartphones, UK: 0% duty, 20% VAT, Vietnam and CPTPP preferences.
- `{"mode": "code", "code": "61.09"}` -> heading 6109 with its declarable children and their duties.
- `{"mode": "validate", "codes": ["0101210000", "123"]}`

### Use from agents (MCP)

Add the Apify MCP server (`https://mcp.apify.com?tools=martin10291/hs-code-tariff-lookup`) to Claude, Cursor or any MCP client and ask: "What is the HS code for a cotton t-shirt, and what duty does a shipment from China pay in the EU?".

### Data source

GOV.UK Trade Tariff API (HMRC), UK and Northern Ireland (XI) services, Open Government Licence v3.0 (Crown copyright), cached 24 hours as HMRC asks. Duties shown are the published tariff measures; preferential rates need proof of origin under the trade agreement. Not legal or customs advice: binding classification comes from the customs authority. No scraping, no personal data.

### Schedule it

Call it live from your checkout or customs form, or schedule it on Apify (Schedules -> every week) with your product codes in `bulk`, `onlyNew: true` and a `monitorId`: you get a row only when a duty, VAT or preferential rate changed. Chain it with an integration (webhook, Google Sheets, Zapier, Make).

### FAQ

- **How fresh is the data?** HMRC updates the tariff daily; we cache each answer for 24 hours as HMRC asks. `fetchedAt` is on every row; if the source is down the last copy is served with `"stale": true`.
- **Limits:** search up to 50 results, validate up to 100 codes, bulk up to 50 queries per call.
- **Errors:** an invalid or unknown code returns a clear error (in bulk only that row); a non-declarable code returns its declarable children instead of an error.
- **Is this customs advice?** No: these are the published tariff measures. Preferential rates need proof of origin; binding classification comes from the customs authority.
- **EU VAT:** set by each member state of import, so EU rows carry a `vatNote` instead of one rate.

### Pricing

$1.00 per 1,000 rows. One `code` lookup = 1 row.

# Actor input Schema

## `mode` (type: `string`):

search = keyword to ranked HS/commodity codes; code = full details of one code (duty, VAT, origin rate, measures, or declarable children); validate = check that codes exist and are declarable; bulk = up to 50 queries in one call.

## `q` (type: `string`):

search mode: product words in English, e.g. cotton t-shirt, lithium battery, roasted coffee.

## `code` (type: `string`):

code mode: HS / commodity code with 2, 4, 6, 8 or 10 digits; dots and spaces are ignored, e.g. 6109.10 or 6109100010.

## `codes` (type: `array`):

validate mode: up to 100 codes.

## `market` (type: `string`):

UK = UK Global Tariff (default); EU = EU Common Customs Tariff as published by the UK Trade Tariff Northern Ireland (XI) service.

## `origin` (type: `string`):

ISO 2-letter country of origin, e.g. CN, VN, US. code mode returns the preferential rate and the duty that applies to this origin.

## `queries` (type: `array`):

bulk mode: up to 50 objects, each one an input of another mode, e.g. {"mode":"code","code":"8517130000","origin":"VN"}. A failing query returns an error row; the others still answer.

## `limit` (type: `integer`):

search mode: 1-50, default 10.

## `onlyNew` (type: `boolean`):

Return only rows not returned before for the same Monitor ID. Schedule the run to get changes only.

## `monitorId` (type: `string`):

Name of this monitor; each ID keeps its own memory of rows already returned.

## Actor input object example

```json
{
  "mode": "search",
  "q": "red wine",
  "market": "UK",
  "limit": 10,
  "onlyNew": false
}
```

# Actor output Schema

## `results` (type: `string`):

search: ranked commodity codes for the keyword; code: one row per code with chain, duty, VAT, origin rate and measures (or the declarable children); validate: one row per code; bulk rows carry the query index.

# 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 = {
    "mode": "search",
    "q": "red wine"
};

// Run the Actor and wait for it to finish
const run = await client.actor("martin10291/hs-code-tariff-lookup").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 = {
    "mode": "search",
    "q": "red wine",
}

# Run the Actor and wait for it to finish
run = client.actor("martin10291/hs-code-tariff-lookup").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 '{
  "mode": "search",
  "q": "red wine"
}' |
apify call martin10291/hs-code-tariff-lookup --silent --output-dataset

```

## MCP server setup

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

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/oFXs6vygfbG8Gsnz9/builds/KHfGa79GiDxdnEhY0/openapi.json
