# UN Comtrade Bilateral Trade Statistics Scraper (`jungle_synthesizer/un-comtrade-bilateral-trade-statistics-scraper`) Actor

Pull bilateral merchandise trade statistics from UN Comtrade's official API. Select reporters, trading partners, years, import/export flows and HS commodity detail (chapter to 6-digit); every row ships with human-readable reporter, partner and commodity names plus reported-vs-estimated flags.

- **URL**: https://apify.com/jungle\_synthesizer/un-comtrade-bilateral-trade-statistics-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 record scrapeds

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

## Bilateral Trade Statistics Database — UN Comtrade

Pull bilateral merchandise trade statistics straight from [UN Comtrade](https://comtradeplus.un.org/), the UN's official global trade database. Returns reporter/partner country pairs, annual or monthly periods, import/export flows, and HS commodity detail from chapter level down to 6-digit subheadings — with every row carrying human-readable country and commodity names instead of raw codes.

***

### UN Comtrade Scraper Features

- Walks the full reporter x partner x period x flow matrix in one run — pull one country's entire trade book, or the whole dataset, without scripting hundreds of individual queries.
- Selects any combination of 243 reporting countries and 292 trading partners by name or ISO3 code.
- Covers both annual and monthly periods, going back decades.
- Supports Import, Export, Re-Import and Re-Export flows, selectable independently.
- Returns HS commodity detail at four levels: Total, 2-digit chapter, 4-digit heading, and 6-digit subheading.
- Ships human-readable reporter, partner, flow, and commodity names on every row — no code lookup tables required on your end.
- Flags whether a figure was directly reported by the country or estimated/mirrored from its trading partner, so you can tell a filed number from an estimate.

***

### Who Uses UN Comtrade Trade Data?

- **Trade analysts and economists** — build country-level import/export models, track trade balances, or study commodity flows over time.
- **Supply chain and sourcing teams** — size a country's export capacity for a given HS category before committing to a lane.
- **Import/export compliance teams** — cross-check declared trade values against the official record. It's the same database customs brokers reference, minus the manual query-building.
- **Market researchers** — quantify a country's dependence on a trading partner for a specific commodity, or spot shifts in trade flows year over year.
- **Journalists and policy researchers** — pull the underlying figures behind a trade-balance headline, with the reported-vs-estimated flag attached.
- **Data teams building trade dashboards** — feed a structured, joined dataset directly into a BI tool instead of post-processing raw codes.

***

### How the UN Comtrade Scraper Works

1. Pick your reporters, partners, years, flows, and commodity detail level — or leave any of them blank to include everything available.
2. The scraper walks every combination of your selections, pacing requests to stay within the data source's rate limits.
3. Each result is joined against the official reference tables for reporter names, partner names, and commodity descriptions, then saved as a clean row.
4. The run stops once it hits your `maxItems` cap or its timeout — pass the `resumeCursor` from the output back in to keep going from exactly where it left off.

***

### Input

```json
{
  "reporters": ["USA"],
  "partners": ["CHN"],
  "flows": ["M", "X"],
  "freqCode": "A",
  "classificationLevel": "AG2",
  "startYear": 2023,
  "endYear": 2023,
  "maxItems": 1000
}
```

| Field                 | Type    | Default        | Description |
|-----------------------|---------|----------------|------------------------------------------------------------------------------------------------------------------|
| `maxItems`            | integer | `100`          | Maximum records to save. `0` or blank pulls without a cap, bounded only by the run's timeout. |
| `reporters`           | array   | `[]` (all 243) | Reporting countries by ISO3 code (e.g. `USA`, `CHN`, `DEU`). Empty means every reporter UN Comtrade publishes. |
| `partners`            | array   | `[]` (all 292) | Trading partners by ISO3 code. Empty means every partner UN Comtrade publishes. |
| `flows`               | array   | `["M", "X"]`   | Trade flows: `M` (Import), `X` (Export), `RM` (Re-Import), `RX` (Re-Export). |
| `freqCode`            | string  | `"A"`          | `A` for annual periods, `M` for monthly. |
| `classificationLevel` | string  | `"AG2"`        | Commodity detail: `TOTAL`, `AG2` (HS chapter), `AG4` (HS heading), or `AG6` (HS subheading). |
| `startYear`           | integer | `2023`         | Earliest year to include. |
| `endYear`             | integer | `2023`         | Latest year to include (inclusive). |

Leaving `reporters` and `partners` both blank with the default `classificationLevel` pulls the full bilateral matrix for the selected years — a large, complete corpus rather than a single lookup.

#### Resuming a large crawl

Every run emits a `resumeCursor` value in its Output. To continue a crawl that stopped — because it hit `maxItems`, a spend cap, or your own timeout — start a new run with the same input plus that `resumeCursor`. You are not re-charged for records you already received. Resume promptly: the previous run's queue expires with your account's data-retention window.

***

### UN Comtrade Scraper Output Fields

```json
{
  "reporter_code": 842,
  "reporter_iso": "USA",
  "reporter_desc": "USA",
  "partner_code": 156,
  "partner_iso": "CHN",
  "partner_desc": "China",
  "period": "2023",
  "ref_year": 2023,
  "ref_month": 52,
  "freq_code": "A",
  "flow_code": "M",
  "flow_desc": "Import",
  "classification_code": "H6",
  "cmd_code": "84",
  "cmd_desc": "Nuclear reactors, boilers, machinery and mechanical appliances",
  "aggr_level": 2,
  "is_leaf": false,
  "qty": null,
  "qty_unit_code": -1,
  "qty_unit_abbr": null,
  "net_wgt": 12345678.0,
  "gross_wgt": null,
  "cif_value": 98765432.0,
  "fob_value": null,
  "primary_value": 98765432.0,
  "is_reported": true,
  "is_aggregate": false,
  "legacy_estimation_flag": 0,
  "customs_code": "C00",
  "mot_code": 0
}
```

| Field                     | Type          | Description                                                                         |
|---------------------------|---------------|-------------------------------------------------------------------------------------|
| `reporter_code`           | integer       | UN M49 numeric reporter code.                                                       |
| `reporter_iso`            | string        | Reporter ISO3 code.                                                                 |
| `reporter_desc`           | string        | Reporter country/territory name.                                                    |
| `partner_code`            | integer       | UN M49 numeric partner code.                                                        |
| `partner_iso`             | string        | Partner ISO3 code.                                                                  |
| `partner_desc`            | string        | Partner country/territory name.                                                     |
| `period`                  | string        | `YYYY` for annual, `YYYYMM` for monthly.                                            |
| `ref_year` / `ref_month`  | integer       | Reference year and month.                                                           |
| `freq_code`               | string        | `A` (annual) or `M` (monthly).                                                      |
| `flow_code` / `flow_desc` | string        | Import/Export/Re-Import/Re-Export, code and name.                                   |
| `classification_code`     | string        | HS classification vintage in force for this row (e.g. `H6`).                        |
| `cmd_code` / `cmd_desc`   | string        | Commodity code and name — `TOTAL`, or an HS chapter/heading/subheading.             |
| `aggr_level`              | integer       | Digit-depth of the commodity code (`0` = Total, `2`/`4`/`6` = HS digits).           |
| `is_leaf`                 | boolean       | `true` when the commodity code has no finer breakdown beneath it.                   |
| `qty` / `qty_unit_abbr`   | number/string | Quantity and its unit, when reported.                                               |
| `net_wgt` / `gross_wgt`   | number        | Net and gross weight in kilograms.                                                  |
| `cif_value`               | number        | CIF value in USD (imports).                                                         |
| `fob_value`               | number        | FOB value in USD (exports).                                                         |
| `primary_value`           | number        | The primary trade value in USD — CIF for imports, FOB for exports.                  |
| `is_reported`             | boolean       | `true` when the reporter itself filed the figure; `false` means mirrored/estimated. |
| `is_aggregate`            | boolean       | `true` when the row is an aggregate rather than a directly reported line.           |
| `legacy_estimation_flag`  | integer       | UN Comtrade's estimation-method flag.                                               |
| `customs_code`            | string        | Customs procedure code.                                                             |
| `mot_code`                | integer       | Mode-of-transport code.                                                             |

***

### FAQ

#### Does this cover every country UN Comtrade publishes?

Yes — 243 reporting countries/territories and 292 trading partners, including historical entities UN Comtrade still carries in its records. Leave `reporters`/`partners` blank to include all of them.

#### What's the difference between a "reported" and an "estimated" figure?

`is_reported` tells you whether the country itself filed the trade figure. When it's `false`, the value was mirrored or estimated from the partner country's own filing — useful for knowing how much to trust a specific number.

#### Can I pull just one country's entire trade book?

Yes. Set `reporters` to that one country, leave `partners` blank, pick a commodity detail level, and set `maxItems` high (or `0`) — the run walks every partner and commodity code for that reporter.

#### Why does a very detailed (AG6) query sometimes return fewer commodity codes than expected?

Extremely detailed, high-volume bilateral relationships (two large economies at 6-digit HS detail) can occasionally return a partial commodity breakdown for that specific combination — a limit of the free public data tier, not a filter you set.

#### What's the difference between annual and monthly data?

`freqCode: "A"` returns one row per year per combination; `freqCode: "M"` returns one row per calendar month, which multiplies the number of periods by up to 12x for the same year range.

***

### Need More Features?

Have a request — a new field, a bulk-export mode, additional reference joins? [Open an issue](https://console.apify.com/actors) and we'll take a look.

### Why Use This UN Comtrade Scraper?

- **Full bilateral matrix in one run** — no scripting hundreds of individual reporter/partner/period queries by hand.
- **Names, not just codes** — reporter, partner, and commodity descriptions are joined in on every row.
- **Reported-vs-estimated transparency** — `is_reported` and `legacy_estimation_flag` let you tell a filed figure from an estimate, which most trade-data tools don't surface at all.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

What will this data feed? E.g. lead lists, KYB checks, price tracking.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

We'll personally help with your use case. No spam.

## `resumeCursor` (type: `string`):

Leave empty for a fresh crawl. To CONTINUE a previous run where it stopped — without paying again for records you already received — paste the `resumeCursor` value from that run's Output (the run's OUTPUT key). Resume promptly: the previous run's data expires with your account's retention window (free tier: your ~10 most recent runs).

## `maxItems` (type: `integer`):

Maximum number of trade records to save. Leave blank or set to 0 to pull without a cap -- the run stops only at its timeout, and resumeCursor picks up where it left off on the next run.

## `reporters` (type: `array`):

Reporting countries/territories (ISO3). Leave empty to walk all 243 reporters UN Comtrade publishes.

## `partners` (type: `array`):

Bilateral trading partners (ISO3). Leave empty to walk all 292 partner areas UN Comtrade publishes.

## `flows` (type: `array`):

Which trade flow(s) to pull. Import/Export cover standard merchandise trade; Re-Import/Re-Export cover re-exported goods.

## `freqCode` (type: `string`):

Annual or monthly periods. Monthly multiplies the number of periods walked by up to 12x.

## `classificationLevel` (type: `string`):

Commodity aggregation level. TOTAL is one row per partner (fastest, always complete). AG2/AG4/AG6 add HS chapter / heading / subheading detail; AG6 on a large bilateral relationship (e.g. two major economies) may hit the free preview tier's 500-row-per-call cap and return a partial commodity breakdown for that shard -- a limit of the public tier, not this actor.

## `startYear` (type: `integer`):

Earliest year (or YYYYMM month-range start when Frequency=Monthly, e.g. 2023) to include. UN Comtrade's HS-classified series goes back to the late 1980s for most reporters.

## `endYear` (type: `integer`):

Latest year to include (inclusive). Defaults to a single-year run; widen the range for a historical pull.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 100,
  "reporters": [],
  "partners": [],
  "flows": [
    "M",
    "X"
  ],
  "freqCode": "A",
  "classificationLevel": "AG2",
  "startYear": 2023,
  "endYear": 2023
}
```

# Actor output Schema

## `results` (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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 100,
    "reporters": [],
    "partners": [],
    "flows": [
        "M",
        "X"
    ],
    "freqCode": "A",
    "classificationLevel": "AG2",
    "startYear": 2023,
    "endYear": 2023
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/un-comtrade-bilateral-trade-statistics-scraper").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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 100,
    "reporters": [],
    "partners": [],
    "flows": [
        "M",
        "X",
    ],
    "freqCode": "A",
    "classificationLevel": "AG2",
    "startYear": 2023,
    "endYear": 2023,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/un-comtrade-bilateral-trade-statistics-scraper").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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 100,
  "reporters": [],
  "partners": [],
  "flows": [
    "M",
    "X"
  ],
  "freqCode": "A",
  "classificationLevel": "AG2",
  "startYear": 2023,
  "endYear": 2023
}' |
apify call jungle_synthesizer/un-comtrade-bilateral-trade-statistics-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jungle_synthesizer/un-comtrade-bilateral-trade-statistics-scraper"
        }
    }
}
```

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/I0l0xy9jvujjHLA7V/builds/X5u3TLPvw0V4cLe7a/openapi.json
