# EU Safety Gate Product Matcher: RAPEX vs Your Catalog (`dafei-data/eu-safety-gate-product-matcher`) Actor

Match your product list (name, brand, model, EAN barcode) against official EU Safety Gate (RAPEX) dangerous-product alerts. Confidence score and match reason for every hit, category filter (default Toys), bilingual English/Chinese output. Not legal advice.

- **URL**: https://apify.com/dafei-data/eu-safety-gate-product-matcher.md
- **Developed by:** [dafei-data](https://apify.com/dafei-data) (community)
- **Categories:** E-commerce, Business, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 Safety Gate Product Matcher: RAPEX Alerts vs Your Catalog (EN/中文)

> ⚠️ **Disclaimer:** Informational only. **This is not legal or compliance advice.** Matches are automated and may be incomplete or wrong; always verify on the official Safety Gate alert page (`alertUrl`).
>
> ⚠️ **免责声明：** 仅供参考，**不构成法律或合规意见**。匹配结果由程序自动生成，可能遗漏或有误，请以 Safety Gate 官方预警页面为准。

Check your own product list against the official **EU Safety Gate (RAPEX)** weekly alerts for dangerous non-food products. Every hit comes with a **confidence score** and the **reason it matched**, in **English and Chinese**.

### Sample output · 样例输出

![Sample output from a real cloud run](https://api.apify.com/v2/key-value-stores/rZAPAMH2laMhiHfpr/records/safetygate-sample-output.png)

*Real Apify cloud run (weekly report 2026-W42) with the example input below. Chinese fields are generated from a fixed glossary.*

### Pricing (pay per event)

| Event | Price |
|---|---|
| Alert listed (monitor mode) | $0.003 |
| Product checked (per product, per run) | $0.001 |
| Match found | $0.01 |

### Bilingual Excel report (free) · 中英双语 Excel 报告（免费）

With `excelReport` on (default), every run saves **`REPORT.xlsx`** to the run's default key-value store. It is **free** and does not change the dataset or the price.

- Sheet **Results 结果**: two header rows (English + 中文), frozen header, filters, a clickable link to each official alert, English original and Chinese (Zh) columns side by side.
- Sheet **About 说明**: disclaimer, translation notice, source attribution, licence and the link to the official reuse terms.
- **Download:** Console → your run → **Storage → Key-value store → REPORT.xlsx**, or `GET https://api.apify.com/v2/key-value-stores/<defaultKeyValueStoreId>/records/REPORT.xlsx` (add your API token). The exact URL is printed in the run log. It also appears in the run's **Output** tab.

### Subscribe by country of origin and category (monitor mode + Schedule) · 按原产地和品类订阅

1. Leave `products` empty (monitor mode) and set the filters, e.g.:

```json
{ "categories": ["Toys", "Childcare articles and children's equipment"], "countriesOfOrigin": ["China"], "weeks": 1, "incremental": true, "stateStoreName": "sg-toys-china" }
```

2. Click **Save as a new task**.
3. In Apify Console open **Schedules → Create new**, add the task, and set a weekly cron such as `0 8 * * 6` (Saturdays 08:00 UTC). Safety Gate publishes one weekly report every Friday. Docs: https://docs.apify.com/platform/schedules
4. With `incremental: true` each run outputs only alerts it has not output before (remembered in the named key-value store `stateStoreName`), so you are charged only for new alerts. Use one store name per subscription.
5. Optional: add an email / Slack integration to the task to receive each run (https://docs.apify.com/platform/integrations).
   The same works in match mode: keep `products` filled and `incremental` on to be notified only about new matches.

### EAN / barcode matching details

- Your barcode is matched **exactly** (digits only) against every barcode in the alert. GTIN-8/12/13/14 are compared after removing leading zeros, so `02765238030004` equals `2765238030004`.
- Safety Gate often stores several barcodes concatenated without a separator (e.g. `50529311163315052931116324`) or with spaces inside. The Actor splits such values into fixed-length codes **only if every part has a valid GTIN check digit**, and never matches on a partial / substring code.
- Numbers or strings are both accepted as input; `yourProduct.barcodeValid` tells you whether your own code has a valid check digit.

### Reuse terms, source and licence · 再利用条款、出处与许可

Official Safety Gate disclaimer (reuse terms): https://webgate.ec.europa.eu/safety/consumers/consumers_safety_gate/menu/documents/New_disclaimer_EN.pdf

- Reuse is authorised (Commission Decision 2011/833/EU) **provided the original meaning is not distorted and the source is acknowledged** as: *"Alerts from the Rapid Alert System for dangerous non-food products, published free of charge on the Safety Gate website (https://ec.europa.eu/safety-gate-alerts) © European Union, 2005 – 2025"*. Every dataset item (`attribution`) and the Excel report carry this exact text.
- **Translations must be acknowledged; the English version prevails.** All `…Zh` fields are an **unofficial translation generated from a fixed glossary** (`translationNotice` / `translationNoticeZh` in every item). English originals are always kept next to them.
- The European Commission is not liable for the accuracy of alert information provided by national authorities.
- The weekly report list XML is published as CC0 on data.europa.eu: https://data.europa.eu/data/datasets/rapex-rapid-alert-system-non-food

### How matching works

| Confidence | Rule |
|---|---|
| 1.0 (high / 高) | Your barcode (EAN/GTIN) is identical to a barcode in the alert |
| 0.85 (high / 高) | Same brand **and** your model number appears in the alert's model / name / batch |
| 0.6 (medium / 中) | Your model number appears in the alert |
| 0.5 (medium / 中) | Same brand + similar product words |
| 0.4 (low / 低) | Same brand only (generic brands like "Unknown" / "No brand" are ignored) |
| 0.3 (low / 低) | Similar product: at least half of your product-name words appear in the alert's product/name |

### Use cases

#### 1. Toy exporter to the EU: barcode pre-check before listing

Before you list or ship a batch of toys to EU buyers, check your EAN/GTIN barcodes against the latest Safety Gate alerts. Barcodes are compared exactly (leading zeros ignored), so a hit means the same code appears in an official alert.

**Input** (paste into the Input tab and replace with your own SKUs; TOY-001 and TOY-002 use barcodes taken from real alerts so the demo returns hits, TOY-003 is not in any alert of the period):

```json
{
  "products": [
    { "sku": "TOY-001", "name": "Toy gun set", "barcode": "04250383846504" },
    { "sku": "TOY-002", "name": "Key ring with soft toy", "barcode": "3760323741727" },
    { "sku": "TOY-003", "name": "Wooden puzzle", "barcode": "4006381333931" }
  ],
  "categories": ["Toys"],
  "weeks": 4,
  "minConfidence": 1
}
```

**Output** — excerpt of one dataset item from a real run on 2026-10-28 (weekly reports 2026-39 to 2026-42: 406 alerts, 111 in Toys; 4 matches — TOY-001 once, TOY-002 three times in three separate alerts; TOY-003 no match):

```json
{
  "type": "match",
  "confidence": 1,
  "matchBasis": [
    "Barcode 04250383846504 is identical",
    "Similar product (shared words: gun)"
  ],
  "matchBasisZh": [
    "条码 04250383846504 完全一致",
    "同类商品（共同词：gun）"
  ],
  "yourProduct": {
    "name": "Toy gun set",
    "brand": null,
    "model": null,
    "barcode": "04250383846504",
    "sku": "TOY-001",
    "barcodeValid": true
  },
  "alertNumber": "SR/03013/26",
  "alertUrl": "https://ec.europa.eu/safety-gate-alerts/screen/webReport/alertDetail/10118725",
  "reportDate": "2026-10-23",
  "product": "Toy gun set",
  "barcode": "4250383846504",
  "riskLevel": "Serious risk",
  "riskLevelZh": "严重风险",
  "measures": [
    "Recall of the product from end users"
  ],
  "measuresZh": [
    "从终端用户处召回"
  ],
  "countryOfOrigin": "People's Republic of China",
  "countryOfOriginZh": "中国",
  "attribution": "Alerts from the Rapid Alert System for dangerous non-food pr …"
}
```

`barcodeValid` tells you whether your own barcode has a correct GS1 check digit. A bilingual `REPORT.xlsx` is saved in the run's key-value store.

**Schedule it:** Save the input as a Task, set `"weeks": 1`, `"incremental": true` and a `stateStoreName` (e.g. `my-toy-catalog`) → Console → **Schedules** → *Create* → e.g. `0 9 * * 6` (Saturday 09:00; Safety Gate publishes a weekly report, usually on Friday) → add the Task and an e-mail/Slack integration. Each run then only reports alerts not seen before.

### Example input

```json
{
  "products": [
    { "sku": "A1", "name": "Squishy slime toy", "brand": "MyBrand", "model": "SL-01" },
    { "sku": "A2", "name": "Baby rattle", "barcode": "6901234567892" }
  ],
  "categories": ["Toys"],
  "weeks": 4
}
```

Leave `products` empty to simply list all alerts in the chosen categories (monitor mode). Default category: **Toys**.

### Chinese output (中文字段)

Chinese fields (`categoryZh`, `riskTypesZh`, `riskLevelZh`, `measuresZh`, `economicOperatorsZh`, `countryOfOriginZh`, `dangerKeyTermsZh`, `matchBasisZh` …) are produced **deterministically from a fixed glossary** in `src/glossary.js` — no machine-translation API. Free text (`danger`, `description`) stays in English; `dangerKeyTermsZh` lists the key technical terms detected in it (e.g. 邻苯二甲酸酯, 小零件, REACH 法规). Terms not in the glossary are listed in `untranslatedTerms`.

### Data source, licence, robots

- Official list of weekly reports: `https://ec.europa.eu/safety-gate-alerts/api/download/weeklyReport/list/xml/en` (dataset "Safety Gate (the EU rapid alert system – non-food)" on data.europa.eu, XML distribution licensed CC0); each weekly report XML is linked from that list.
- The Actor only downloads these official XML files (1 request per second, N+1 requests per run). It does not crawl web pages. `https://ec.europa.eu/robots.txt` does not disallow `/safety-gate-alerts/`.
- No personal data: alerts describe products, brands, risks and measures.
- Attribution, translation notice and licence: see **Reuse terms, source and licence** above (exact wording from the official disclaimer, kept in every item).
- Independent tool, not affiliated with the European Commission.

### Related · 相关工具

- UK equivalent: [UK Product Recall Matcher](https://apify.com/dafei-data/uk-product-recall-matcher) — match your Amazon ASINs, EANs and models against UK OPSS product safety reports and recalls (GOV.UK). 英国版：用 ASIN / EAN / 型号匹配英国 OPSS 召回与安全报告。
- Canada equivalent: [Canada Recalls & Safety Alerts Product Matcher](https://apify.com/dafei-data/canada-recalls-product-matcher) — match your products (brand, model, UPC/EAN, ASIN) against Health Canada, CFIA and Transport Canada recalls (Government of Canada open data). 加拿大版：用品牌 / 型号 / 条码匹配加拿大官方召回与安全警报。
- Developer news: [Hacker News Monitor: Keywords, Domains, Show HN + Chinese](https://apify.com/dafei-data/hacker-news-monitor-chinese) — only-new Hacker News alerts for your keywords, domains and Show HN launches, with Chinese machine-translated titles and a bilingual Excel report.

### Free plan limit & upgrade

- **Apify free plan:** up to **100 output items per run** (the run finishes normally and the status message says when the limit was applied).
- **Paid Apify plan:** the full `maxItems` (default 1,000, up to 100,000), same per-event prices.
- Upgrade your Apify plan: https://apify.com/pricing
- Run this Actor on Apify Store: https://apify.com/dafei-data/eu-safety-gate-product-matcher

# Actor input Schema

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

Your catalog. Each item may have: name, brand, model, barcode (EAN/GTIN), barcodes (array), sku, keywords. Leave empty to just list alerts (monitor mode).

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

Safety Gate categories (English, exact) or their Chinese names, e.g. Toys / 玩具, Cosmetics / 化妆品, "Childcare articles and children's equipment". Empty = all categories.

## `countriesOfOrigin` (type: `array`):

Optional. Substring of the English country name (e.g. China) or the Chinese name (e.g. 中国).

## `weeks` (type: `integer`):

Number of most recent weekly reports (published every Friday).

## `minConfidence` (type: `number`):

1.0 barcode identical; 0.85 brand+model; 0.6 model only; 0.5 same brand + similar product; 0.4 same brand; 0.3 similar product words.

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

Maximum dataset items. Free Apify plan: capped at 100 items per run; paid plans use the full value.

## `incremental` (type: `boolean`):

Remember already-output alerts (and alert+product matches) in a named key-value store and output only new ones. Turn on when you run the Actor on an Apify Schedule.

## `stateStoreName` (type: `string`):

Named key-value store for incremental mode. Use a different name per subscription (e.g. sg-toys-china).

## `excelReport` (type: `boolean`):

Also save REPORT.xlsx (English + Chinese headers, About sheet with source, licence and disclaimer) to the run's default key-value store. Free: no extra charge.

## Actor input object example

```json
{
  "products": [
    {
      "sku": "DEMO-1",
      "name": "Plush teddy bear",
      "brand": "MyBrand",
      "model": "TB-30",
      "barcode": "6901234567892"
    },
    {
      "sku": "DEMO-2",
      "name": "Slime putty toy",
      "brand": "MyBrand",
      "model": "SL-01"
    }
  ],
  "categories": [
    "Toys"
  ],
  "weeks": 4,
  "minConfidence": 0.3,
  "maxItems": 1000,
  "incremental": false,
  "stateStoreName": "safety-gate-seen",
  "excelReport": true
}
```

# Actor output Schema

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

No description

## `overview` (type: `string`):

No description

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

No description

## `report` (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 = {
    "products": [
        {
            "sku": "DEMO-1",
            "name": "Plush teddy bear",
            "brand": "MyBrand",
            "model": "TB-30",
            "barcode": "6901234567892"
        },
        {
            "sku": "DEMO-2",
            "name": "Slime putty toy",
            "brand": "MyBrand",
            "model": "SL-01"
        }
    ],
    "categories": [
        "Toys"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dafei-data/eu-safety-gate-product-matcher").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": [
        {
            "sku": "DEMO-1",
            "name": "Plush teddy bear",
            "brand": "MyBrand",
            "model": "TB-30",
            "barcode": "6901234567892",
        },
        {
            "sku": "DEMO-2",
            "name": "Slime putty toy",
            "brand": "MyBrand",
            "model": "SL-01",
        },
    ],
    "categories": ["Toys"],
}

# Run the Actor and wait for it to finish
run = client.actor("dafei-data/eu-safety-gate-product-matcher").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": [
    {
      "sku": "DEMO-1",
      "name": "Plush teddy bear",
      "brand": "MyBrand",
      "model": "TB-30",
      "barcode": "6901234567892"
    },
    {
      "sku": "DEMO-2",
      "name": "Slime putty toy",
      "brand": "MyBrand",
      "model": "SL-01"
    }
  ],
  "categories": [
    "Toys"
  ]
}' |
apify call dafei-data/eu-safety-gate-product-matcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dafei-data/eu-safety-gate-product-matcher"
        }
    }
}
```

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/1Xh2fqw94RADR1emW/builds/9BXPXv7fpfMLPs2Jj/openapi.json
