# UN Comtrade Trade Flow Watch (`automatic/comtrade-trade-watch`) Actor

Bilateral commodity trade flows from UN Comtrade's official free API: annual trade records per reporter, partner, HS code and year, with values, weights and quantities, per-pair aggregates and change vs previous run. Official UN open data, no key needed. Latest published year per reporter.

- **URL**: https://apify.com/automatic/comtrade-trade-watch.md
- **Developed by:** [Philip Kirkbride](https://apify.com/automatic) (community)
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 94.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 result rows

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

## UN Comtrade Trade Flow Watch: Bilateral Trade Data

Collect official bilateral commodity trade flows from the UN Comtrade database: import and export values in USD, net weight and quantity, for any reporter, partner country and HS commodity code. Each run returns one record per trade row plus a summary with totals per pair and flow and the change since your previous run, so a scheduled run works as a trade watch. Built for trade analysts, economists, commodity researchers and anyone monitoring who ships what to whom. Official UN open data; no account or API key is needed.

### Use cases

- **Trade watch:** schedule a monthly run on your key country pairs and products and see when a new year's figures land or published figures are revised.
- **Market sizing:** import and export values and weights for one HS code between two countries, or against the World aggregate.
- **Supply-chain research:** compare a country's imports of a product from several partners in one run.
- **Dashboards and models:** feed annual trade values per pair into spreadsheets, BI tools or your own models.

### Quick start

1. Open the Actor and click **Start**. The form is prefilled with Peru's trade with the World in HS 8517 (phones) for the latest published year.
2. Read the rows in the **Output** tab, or export them as JSON, CSV or Excel.

One pair for a set year:

```json
{"reporter": "peru", "partner": "china", "cmdCode": "8517", "period": 2024}
```

To watch several pairs in one run, use a watchlist:

```json
{"watchlist": [
  {"reporter": "peru", "partner": "china", "cmdCode": "8517", "period": 2024},
  {"reporter": "peru", "partner": "united states", "cmdCode": "8517", "period": 2024},
  {"reporter": "usa", "partner": "china", "cmdCode": "8517"}
]}
```

An empty input (`{}`) runs the same default pair as the prefilled form: Peru, World, HS 8517, latest published year.

### Input

| Name | Type | Default | Meaning |
| --- | --- | --- | --- |
| `reporter` | string | `peru` | Reporting country: ISO numeric code (`"604"`) or name (`"peru"`, `"china"`, `"united states"`). |
| `partner` | string | `world` | Partner country, same rules; `"world"` is the World aggregate. |
| `cmdCode` | string | `8517` | HS commodity code (`"8517"` phones, `"2710"` petroleum oils); deeper codes give more detail. |
| `period` | integer | latest | Reference year (2010 or later). When omitted, the current year and the two before it are tried, newest first; set `period` explicitly for older years. |
| `watchlist` | array | `[]` | 1–25 pairs `{reporter, partner, cmdCode, period}`; overrides the four fields above. `period` may be omitted per pair; any other key in a pair is rejected by name. |
| `requestDelaySecs` | number | `6` | Pause between pairs, 1–60 seconds. |
| `maxResults` | integer | `500` | Upper bound on records kept per pair (1–500). Pairs usually return far fewer (see below). |

### What it returns

One dataset row per trade row. UN Comtrade's free preview data currently gives flow totals only: typically a few rows per pair (one per flow, such as imports, exports and re-exports), with no breakdown by transport mode or customs procedure.

| Field | Meaning |
| --- | --- |
| `recordKey` | Stable key for the row. |
| `period` | Reference year. |
| `reporterCode`, `reporter` | Reporting country code and name. |
| `flowCode` | `M` import, `X` export, `RX` re-export, `DX` re-import. |
| `partnerCode`, `partner` | Partner country code and name. |
| `cmdCode` | HS commodity code. |
| `primaryValue` | Trade value in USD (CIF for imports, FOB for exports). |
| `netWgt` | Net weight in kg. |
| `qty`, `qtyUnitAbbr` | Quantity and its unit. |
| `cifvalue`, `fobvalue` | CIF and FOB values in USD where reported. |
| `customsCode` | Customs procedure code (`C00` = all procedures). |
| `motCode` | Mode of transport (`0` = all transport modes, the total). |
| `isAggregate`, `isReported` | UN Comtrade aggregate and reported flags. |
| `pairKey` | The watched pair this row belongs to. |
| `sourceQuery` | The UN Comtrade query that produced the row. |
| `collectedAt` | UTC time the row was collected. |

The run summary (`OUTPUT`) reports per-pair record counts, the resolved year and totals per flow. For the import figure, take the row with `flowCode == "M"`; for exports, `flowCode == "X"`.

#### Change since the previous run

For each pair, the summary's `delta` compares this run's totals per flow with the totals your previous run of this Actor collected for the same pair and year: `current`, `previous`, `absChange` and `pctChange` for value, net weight, quantity and row count, plus `previousAt` (when that run collected them). The first run for a pair has nothing to compare with and is marked `isFirstRun: true`. Later runs on your account compare with the most recent earlier run that watched the pair, whatever else that run watched. `pctChange` is `null` when the previous figure was zero or missing. When `period` is left empty and a newer year is published, the pair moves to that year and starts a new comparison.

If a pair fails in a run, its entry reports the error together with the last comparison on record.

### Output example

The import row for USA from China, HS 8517, 2025, built from a recorded UN Comtrade response (`collectedAt` is an example):

```json
{"recordKey":"2025:842:M:156:0:8517:C00:0","period":"2025","reporterCode":842,"reporter":"USA","flowCode":"M","partnerCode":156,"partner":"China","cmdCode":"8517","primaryValue":30506258399.0,"netWgt":52715091.379,"qty":0.0,"qtyUnitAbbr":null,"cifvalue":30506258399.0,"fobvalue":30205777507.0,"customsCode":"C00","motCode":0,"isAggregate":true,"isReported":false,"pairKey":"842:156:8517:2025","sourceQuery":"reporterCode=842&period=2025&cmdCode=8517&partnerCode=156","collectedAt":"2026-10-21T04:20:15+00:00"}
```

The same run also returned the export (`X`), re-export (`RX`) and re-import (`DX`) totals for the pair.

### Pricing

- **$0.001 per result row** (one trade row).
- **$0.005 per run start.** The run-start event is charged per GB of memory; the default 512 MB run is one start event. The start is charged even if the run saves no rows.

Worked cost: one pair usually returns a few rows, so a single-pair run costs about **$0.008**. A full 25-pair watchlist at about 3 rows per pair (75 rows) costs about **$0.08**.

### Scheduling and monitoring

- Schedule a monthly or quarterly run on the same input; each run's summary shows what changed per pair and flow since the previous run (see above). To keep the history yourself, store the rows in your own table keyed on `recordKey`.
- Leave `period` empty to follow the latest published year automatically.

### FAQ

**How fresh is the data?** These are annual UN statistics: most reporters publish the previous calendar year, a few (such as the USA) publish current-year estimates. When `period` is omitted, the current year and the two before it are tried in turn and the first with published figures is used; for older years, set `period` explicitly.

**Which flows can I watch?** Any reporter/partner pair worldwide with any HS commodity code from 2010 onward, plus the World aggregate per reporter.

**What are the limits?** Up to 25 pairs per run. `maxResults` (up to 500 per pair) is only an upper bound: with flow totals only, a pair typically returns a few records. Larger watchlists take a little longer because pairs are collected one after another.

**What happens if a pair fails?** That pair becomes a warning in the run summary while the rest of the run completes.

**Can I restart the comparison?** Comparisons are kept per pair and year in a key-value store named `comtrade-trade-watch-state` in your Apify account. Delete that store (under **Storage**) to make the next run start fresh.

**Export formats?** JSON, CSV, Excel, XML or RSS from the dataset, or read it through the Apify API in your own pipeline.

### Limits

- Annual data only (no monthly series), from 2010 onward.
- Flow totals per pair; no breakdown by transport mode or customs procedure in the current free data.
- Up to 25 pairs per run, collected one after another.

For support, contact Apify support and include the Actor run ID.

# Actor input Schema

## `reporter` (type: `string`):

Reporting country for single-pair mode: an ISO numeric code ('604') or a name ('peru', 'china', 'united states'). Resolved against a static UN country list. Ignored when a watchlist is given.

## `partner` (type: `string`):

Partner country for single-pair mode: ISO numeric code, name, 'world'/'0' for the World aggregate. Defaults to 'world'. Ignored when a watchlist is given.

## `cmdCode` (type: `string`):

HS commodity code for single-pair mode ('8517' = phones, '2710' = petroleum oils). Chapter-level codes return aggregated rows; deeper codes return more detailed ones. Ignored when a watchlist is given.

## `period` (type: `integer`):

Reference year. Leave empty for the latest published year: the current calendar year and the two before it are tried per reporter, newest first, and the first with published figures is used. Set a year explicitly for older data.

## `watchlist` (type: `array`):

Optional list of pairs to watch in one run (overrides reporter/partner/cmdCode/period). Each item: {reporter, partner, cmdCode, period} with the same value rules; 'period' may be omitted to use the default resolution.

## `requestDelaySecs` (type: `number`):

Pause between pair requests. The source is free but rate-limited, so keep the spacing moderate.

## `maxResults` (type: `integer`):

Cap on records kept per pair after parsing (the endpoint itself caps at 500 rows per response).

## Actor input object example

```json
{
  "reporter": "peru",
  "partner": "world",
  "cmdCode": "8517",
  "watchlist": [],
  "requestDelaySecs": 6,
  "maxResults": 500
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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 = {
    "reporter": "peru",
    "partner": "world",
    "cmdCode": "8517",
    "watchlist": [],
    "requestDelaySecs": 6,
    "maxResults": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("automatic/comtrade-trade-watch").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 = {
    "reporter": "peru",
    "partner": "world",
    "cmdCode": "8517",
    "watchlist": [],
    "requestDelaySecs": 6,
    "maxResults": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("automatic/comtrade-trade-watch").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 '{
  "reporter": "peru",
  "partner": "world",
  "cmdCode": "8517",
  "watchlist": [],
  "requestDelaySecs": 6,
  "maxResults": 500
}' |
apify call automatic/comtrade-trade-watch --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automatic/comtrade-trade-watch"
        }
    }
}
```

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/tHirUdDrkc0irubIs/builds/Lzz4AOvvwFVm0WVAK/openapi.json
