# EU Anti-Dumping Duty Checker (by CN Code / Country) (`chosen_loafer/eu-trade-defence-monitor`) Actor

Check whether your imported product (by CN code and origin country) is subject to an EU anti-dumping, anti-subsidy or safeguard measure before you price a shipment, with direct Official Journal links. Can also run on a schedule to monitor new and amended cases. No personal data

- **URL**: https://apify.com/chosen_loafer/eu-trade-defence-monitor.md
- **Developed by:** [Pavel Staurouski](https://apify.com/chosen_loafer) (community)
- **Categories:** Automation, Business, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 case record checkeds

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

## EU Anti-Dumping Duty Checker (by CN Code / Country)

Before you price or clear a shipment, check whether your product (by CN customs code)
and its country of origin are subject to an EU anti-dumping, anti-subsidy or safeguard
duty, and get told the day that status changes. Built for importers, customs brokers and
trade lawyers who currently find out about a new EU duty from an invoice dispute rather
than from the Official Journal itself.

Tracks the European Commission's DG TRADE trade-defence case register (anti-dumping,
anti-subsidy and safeguard investigations against non-EU imports) for new case
initiations and new Official Journal acts -- provisional duties, definitive duties,
amendments, reviews, terminations -- filtered by product CN (Combined Nomenclature /
customs) code, origin country, and/or proceeding category.

### What you get

One record per matching case family that is new, has a new Official Journal publication
since your last check, or has changed measure status, plus one per case removed from the
live register since your last check. Every record carries an explicit `matchState`:
`FIRST_SEEN` (your own baseline run), `NEW` (newly matched a filter since the last check),
`NEW_PUBLICATION` (a new Official Journal act was published for this case -- the main
signal: a new provisional or definitive duty, an amendment, or a termination),
`STATUS_CHANGED`, `UNCHANGED`, or `REMOVED`.

Each record includes: case number and product name, proceeding category (Anti-dumping /
Anti-subsidy / Safeguard), origin countries, CN customs codes covered, current measure
status and type, and `latestPublication` -- the most recent entry that carries a real
Official Journal reference, with a direct link to the EUR-Lex text. Internal procedural
items with no public act (questionnaires, sampling forms) are tracked in the full
publication count but never surface as the "latest" one.

### What it does not do

No personal data: every field is case, product or measure-level (case number, product
description, country, customs code, measure status, Official Journal reference). The
source API has no contact-person field at all -- the one role-title field it does expose
("Case handling team") and the case team's functional mailbox alias are never read by this
Actor in the first place.

### Why you might need this

The EU's own case register and Official Journal are public, but nothing else packages
"watch my products and origins, tell me when something changes." Existing Store
anti-dumping/countervailing-duty Actors are all US Federal Register/CBP-focused -- a
different jurisdiction and source entirely. Steel, aluminium and chemical importers are
the clearest fit today, since those sectors currently carry the most EU trade-defence
cases, but the filters work for any CN code.

### Input

```json
{
  "cnCodePrefixes": ["7219", "7220"],
  "countries": ["People's Republic of China"],
  "categories": ["Anti-dumping", "Anti-subsidy"],
  "maxChecked": 150,
  "maxResults": 100
}
```

All filters are optional and combine as AND (a case must match the category filter AND
the country filter; the CN-code filter is then applied on top). Leave a filter empty to
not filter on that dimension. `maxChecked` bounds how many case details get fetched in one
run (the expensive per-case call); `maxResults` bounds how many records get output.

### Change tracking across runs

Run this Actor on a schedule. Each matched case's publication history and measure status
are stored per Actor, so every subsequent run reports exactly what changed (a new duty, a
review outcome, a termination) since the last one, not just a re-dump of the current
state. A case that still exists in the register but no longer matches a filter you changed
is left untouched in storage, not reported as removed -- only a case that genuinely drops
out of the EU's own register is reported `REMOVED`.

### Sample output

One record, run through this Actor's own field mapping against a real case family (a
captured-during-testing snapshot; `newPublications`/`matchState` show what a scheduled
run reports the day a definitive duty actually gets published, which is the main thing
this Actor exists to catch):

```json
{
  "caseInitId": "2800",
  "caseNumber": "AD734",
  "shortName": "1,4-Butanediol (BDO)",
  "category": "Anti-dumping",
  "caseType": "Initial Investigation",
  "countries": ["People's Republic of China", "Saudi Arabia", "United States of America"],
  "cnCodes": ["29053926", "29053928"],
  "measureStatus": "Measures in force",
  "measureType": "Ad valorem duty",
  "ongoing": false,
  "matchState": "NEW_PUBLICATION",
  "newPublications": [
    {
      "publicationId": 7252,
      "type": "Definitive measures",
      "date": "2026-06-23T22:00:00.000Z",
      "url": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=OJ:L_202601373",
      "title": "COMMISSION IMPLEMENTING REGULATION (EU) 2026/1373 of 22 June 2026 imposing a definitive anti-dumping duty and definitively collecting the provisional duty imposed on imports of 1,4-Butanediol originating in the People's Republic of China, the Kingdom of Saudi Arabia and the United States of America"
    }
  ],
  "latestPublication": {
    "publicationId": 7252,
    "type": "Definitive measures",
    "date": "2026-06-23T22:00:00.000Z",
    "url": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=OJ:L_202601373",
    "title": "COMMISSION IMPLEMENTING REGULATION (EU) 2026/1373 of 22 June 2026 imposing a definitive anti-dumping duty and definitively collecting the provisional duty imposed on imports of 1,4-Butanediol originating in the People's Republic of China, the Kingdom of Saudi Arabia and the United States of America"
  },
  "publicationCount": 15,
  "firstSeenAt": "2026-06-01T09:00:00.000Z",
  "lastSeenAt": "2026-10-10T09:00:00.000Z",
  "checkedAt": "2026-10-10T09:00:00.000Z",
  "sourceCaseUrl": "https://tron.trade.ec.europa.eu/investigations/case-history/2800",
  "matchesCnFilter": true
}
```

On a run where nothing changed since the last check, the same case comes back with
`matchState: "UNCHANGED"` and an empty `newPublications` array instead, so you can filter
your own downstream alerting on `matchState` alone.

### Pricing

Pay per run started (USD 0.05) plus per case record produced: new, newly published,
status-changed, or removed (USD 0.02 each). See the Pricing tab for the current rates.

Worked example: a weekly scheduled run filtered to your own CN codes and one or two
origin countries typically reports 1-5 matching or changed cases a week, so USD 0.05 +
(3 x USD 0.02) = USD 0.11/run, around USD 0.44/month across 4 runs. Running monthly
instead, with a broader filter covering a whole proceeding category, still only charges
for cases that are new or changed, so a single light-month run can cost as little as USD
0.15 (one run-started charge plus a handful of case checks).

# Actor input Schema

## `cnCodePrefixes` (type: `array`):

Combined Nomenclature (customs) code prefixes to filter by, e.g. \["7219"] for stainless steel flat-rolled products. A case matches if ANY of its CN codes starts with ANY of these prefixes. Leave empty to not filter by product code.

## `countries` (type: `array`):

Country names to filter by (case-insensitive, substring match), e.g. \["China", "India"]. Matches the exporting country named in the case. Leave empty to not filter by country.

## `categories` (type: `array`):

Case categories to filter by: Anti-dumping, Anti-subsidy, Bilateral Safeguard ex FTA, Multilateral Safeguard, General Safeguard - art.22 GSP. Leave empty to include all categories.

## `maxChecked` (type: `integer`):

Maximum number of matching case families to fetch full detail for in one run (bounds the expensive per-case API call, independent of how many are actually new/changed). The live register holds ~360 case families and grows over time.

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

Maximum number of records (new, changed or removed cases) to output in one run.

## Actor input object example

```json
{
  "cnCodePrefixes": [
    "7219",
    "7220"
  ],
  "countries": [
    "People's Republic of China"
  ],
  "categories": [
    "Anti-dumping",
    "Anti-subsidy"
  ],
  "maxChecked": 150,
  "maxResults": 100
}
```

# Actor output Schema

## `tradeDefenceResults` (type: `string`):

Per-case records for this run.

# 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 = {
    "cnCodePrefixes": [
        "7219",
        "7220"
    ],
    "countries": [
        "People's Republic of China"
    ],
    "categories": [
        "Anti-dumping",
        "Anti-subsidy"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chosen_loafer/eu-trade-defence-monitor").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 = {
    "cnCodePrefixes": [
        "7219",
        "7220",
    ],
    "countries": ["People's Republic of China"],
    "categories": [
        "Anti-dumping",
        "Anti-subsidy",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("chosen_loafer/eu-trade-defence-monitor").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 '{
  "cnCodePrefixes": [
    "7219",
    "7220"
  ],
  "countries": [
    "People'\''s Republic of China"
  ],
  "categories": [
    "Anti-dumping",
    "Anti-subsidy"
  ]
}' |
apify call chosen_loafer/eu-trade-defence-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chosen_loafer/eu-trade-defence-monitor"
        }
    }
}
```

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/jyykrKoGblbv1gsgB/builds/mZ1RLIbfS50ePFRfj/openapi.json
