# EU Safety Gate: dangerous product alerts per weekly report (`steadydata/eu-safety-gate`) Actor

Product safety alerts from the EU's Safety Gate (RAPEX) per weekly report since 2005: product, brand, model, barcode, category, risk, danger, measures, notifying country, origin, online trader and pictures, from the official XML export. Filter on category, country and keyword. Pay per alert.

- **URL**: https://apify.com/steadydata/eu-safety-gate.md
- **Developed by:** [Steadydata Team](https://apify.com/steadydata) (community)
- **Categories:** Business, News, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.65 / 1,000 alert listeds

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

## EU Safety Gate: dangerous product alerts per weekly report

Product safety alerts from the EU's Safety Gate (RAPEX) per weekly report since 2005: product, brand, model, barcode, category, risk, danger, measures, notifying country, origin, online trader and pictures, from the official XML export. Filter on category, country and keyword. Pay per alert.

### Why this scraper

- **Only delivered results are charged.** Inputs that fail come back as clear error
  records at no cost.
- Read from the portal's own XML export, the file the European Commission publishes for exactly this purpose, not from the search screen. Measured on the platform: the two latest weekly reports, 184 alerts, in 15 seconds for a third of a cent.
- One row per alert with everything the weekly report carries: case number, category, product, brand, name, model, batch, barcode, risk type and level, the danger in the authority's words, the measures ordered (recall, withdrawal, ban, with dates), notifying country, country of origin, the online marketplace it was sold on, manufacturer recall codes and pages, and the photos.
- Every week since 2005 is reachable: `latest`, `latest-1`, a report reference such as `Report-2026-38`, or a date. Filters on category, notifying country, keyword and serious-risk-only keep a run to what matters.

### Who this is for

Put reports in `reports` (up to 50 per run: `latest`, `latest-3`, `Report-2026-30`, `2026-07-10`), optionally `categories`, `notifyingCountries`, `keyword`, `seriousOnly` and `maxAlertsPerReport`. Built for product compliance and quality teams, importers and marketplaces checking what they sell, insurers, consumer organisations and journalists, and anyone building a recall watch on a brand, a barcode or a category.

### Who this is not for

Safety Gate covers non-food consumer products notified by EU and EEA market surveillance authorities; food, medicines and medical devices have their own systems (for US food, drug and device recalls, see the related actor). A report is published on Fridays and an alert appears in the report of the week it was notified, so a same-day feed is not possible. Brand, model, barcode and batch are what the notifying authority filled in, and are empty for no-name products. The measures field is the authority's running text, not a structured list.

### Input fields

| Field | Type | Required or default | What it does |
|---|---|---|---|
| `reports` | list of text | required | One per row, up to 50: latest, latest-1 (the week before), a reference such as Report-2026-38, or a publication date (YYYY-MM-DD, the Friday of that week). |
| `categories` | list of text |  | Only these product categories, as Safety Gate names them: Toys, Electrical appliances and equipment, Cosmetics, Motor vehicles, Clothing, textiles and fashion items. Empty means every category. |
| `notifyingCountries` | list of text |  | Only alerts notified by these countries, by name as Safety Gate writes them (Germany, France, Netherlands). Empty means every country. |
| `keyword` | text |  | Only alerts whose product, brand, name, description or danger contains this word. Empty means every alert. |
| `seriousOnly` | true/false | false | Only alerts at risk level Serious risk. Off means every level. |
| `maxAlertsPerReport` | number | 500 | Cost ceiling per weekly report; a report holds 50 to 150 alerts. |

### Input example

```json
{
    "reports": [
        "latest",
        "latest-1"
    ],
    "seriousOnly": false,
    "maxAlertsPerReport": 500
}
```

### Output example

| Field | Type | What it holds | Example |
|---|---|---|---|
| `caseNumber` | text | Safety Gate's case number, for example SR/02546/26 (SR is serious risk, INFO an information notice). | `SR/02546/26` |
| `reportReference` | text | The weekly report the alert was published in, for example Report-2026-38. | `Report-2026-38` |
| `reportDate` | text | The Friday the weekly report was published. | `2026-09-25` |
| `category` | text | The product category as Safety Gate classifies it, for example Toys or Electrical appliances and equipment. | `Toys` |
| `product` | text | The kind of product, for example Sand-filled toy. | `Sand-filled toy` |
| `brand` | text | The brand on the product; empty for unbranded products. | `Tickit` |
| `name` | text | The product name or title as sold. | `Sensory Blocks Set of 16` |
| `model` | text | The type or model number the notifying authority gives. | `73281` |
| `batchNumber` | text | The batch or lot number of the affected units. | `2519` |
| `barcode` | text | The EAN or UPC barcode. | `5060138820289` |
| `riskType` | text | The kind of risk: chemical, choking, electric shock, fire, injuries, health risk and so on. | `Health risk / other` |
| `riskLevel` | text | Serious risk, or Other risk level for information notices. | `Serious risk` |
| `danger` | text | What can go wrong and why the product does not comply, in the authority's words. | `The toy could rupture and the filling of the inside could...` |
| `measures` | text | The measures taken: who took them (distributor, importer, authority), what (recall, withdrawal, ban) and since when. | `Type of economic operator taking notified measure(s): Dis...` |
| `description` | text | How the product looks and is packaged, so it can be recognised. | `Set of 16 wooden sensory sand-filled toys, including tria...` |
| `notifyingCountry` | text | The member state that notified the alert. | `Slovenia` |
| `countryOfOrigin` | text | Where the product was made, as reported. | `People's Republic of China` |
| `alertType` | text | Consumer for products sold to consumers, Professional for professional equipment. | `Consumer` |
| `onlineTrader` | text | The online marketplace or shop the product was sold on, when known (Amazon, AliExpress, Other(shop)). | `Other(www.mesto-igrac.si)` |
| `companyRecallCode` | text | The manufacturer's own recall code, when the alert is a company recall. |  |
| `productionDates` | text | The production period of the affected units, when the manufacturer states one. |  |
| `recallUrl` | text | The manufacturer's recall page, when there is one. |  |
| `pictures` | list | URLs of the product photos on the Safety Gate portal. | `["https://ec.europa.eu/safety-gate-alerts/public/api/noti...` |
| `url` | text | The alert page on the Safety Gate portal. | `https://ec.europa.eu/safety-gate-alerts/screen/webReport/...` |

Error codes: `INVALID_REPORT`, `NOT_FOUND`, `NO_ALERTS`, `BLOCKED`.

One delivered row looks like this (two of the pictures shown):

```json
{
  "caseNumber": "OR/00114/26",
  "reportReference": "Report-2026-37",
  "reportDate": "2026-09-18",
  "category": "Electrical appliances and equipment",
  "product": "Flashlight",
  "brand": "Rebel LIGHT",
  "name": "RECHARGEABLE MULTIFUNCTIONAL FLASHLIGHT",
  "model": "URZ0941",
  "batchNumber": null,
  "barcode": "5901890078412",
  "riskType": "Burns",
  "riskLevel": "Other risk levels",
  "danger": "The battery management system lacks a cell temperature monitoring device. The product can overheat and cause burns. The product does not comply with the requirements of the General Product Safety Regulation nor with the European Standard EN 62133-2.",
  "measures": "Type of economic operator to whom the measure(s) were ordered: DistributorCategory of measure(s): Ban on the marketing of the product and any accompanying measuresDate of entry into force: 20/04/2026Type of economic operator to whom the measure(s) were ordered: DistributorCategory of measure(s): Recall of the product from end usersDate of entry into force: 20/04/2026",
  "description": "Multifunctional rechargeable LED flashlight with micro USB cable.",
  "notifyingCountry": "Hungary",
  "countryOfOrigin": "People's Republic of China",
  "alertType": "Consumer",
  "onlineTrader": "Other(www.jet.hu)",
  "companyRecallCode": null,
  "productionDates": null,
  "recallUrl": null,
  "pictures": [
    "https://ec.europa.eu/safety-gate-alerts/public/api/notification/image/11234008",
    "https://ec.europa.eu/safety-gate-alerts/public/api/notification/image/11234009"
  ],
  "url": "https://ec.europa.eu/safety-gate-alerts/screen/webReport/alertDetail/10118699",
  "status": "ok"
}
```

### Related actors from steadydata

- [fda-recalls](https://apify.com/steadydata/fda-recalls): US food, drug and device recalls, the American counterpart
- [google-news](https://apify.com/steadydata/google-news): press coverage of a recalled brand
- [eu-tenders](https://apify.com/steadydata/eu-tenders): what EU public bodies are buying

### Pricing

Pay per event: one `alert-listed` event per delivered result. No charge for inputs
that fail, no separate platform-usage surcharge.

**Free Apify plan:** this actor delivers up to 25 rows per run for accounts on the Apify free
plan, and then stops with a message. That limit is set by us, not by Apify. It exists so the
actor keeps paying for itself for the people who do pay. Any paid Apify plan runs it at full
size, billed per delivered row, with failed rows never charged.

**Reviews:** if this actor saves you time, a short review on this page is the one thing that
helps most. Ratings are what other buyers look at first, and we have no other way to ask.

### FAQ

**Is personal data collected?**
No. Alerts name products, brands, countries and, where known, the marketplace; no person appears in the rows.

**How do I watch for new alerts every week?**
Run `latest` every Friday evening or Saturday with your categories or a keyword. A week with nothing matching comes back as a free `NO_ALERTS` row.

**How do I get the whole history of a category?**
Give a list of reports: `latest`, `latest-1`, ... `latest-52` covers a year (Safety Gate publishes about 50 reports a year), or references from `Report-2005-01` onward. Each report is one request to the source.

**What is the difference between Serious risk and Other risk levels?**
Serious risk alerts (case numbers starting with SR) require rapid action such as a recall or a ban; other levels are information notices about products with a lower risk. `seriousOnly` keeps the first kind.

**Why does the barcode search matter?**
Because a barcode identifies the exact product across shops and languages; matching `barcode` against your catalogue is the surest way to find out whether you sell an alerted product.

**What does a run cost when a report has no matching alerts?**
Nothing. `NO_ALERTS`, `NOT_FOUND`, `INVALID_REPORT` and `BLOCKED` rows are free; only delivered alerts are charged.

**What happens when the source changes?**
Sources change from time to time; that is the nature of this work. The actor is
monitored daily and fixed fast, and while it is broken you are not charged, because
only delivered results cost anything.

# Changelog

This Actor's version history is a separate document: https://apify.com/steadydata/eu-safety-gate/changelog.md

# Actor input Schema

## `reports` (type: `array`):

One per row, up to 50: latest, latest-1 (the week before), a reference such as Report-2026-38, or a publication date (YYYY-MM-DD, the Friday of that week).

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

Only these product categories, as Safety Gate names them: Toys, Electrical appliances and equipment, Cosmetics, Motor vehicles, Clothing, textiles and fashion items. Empty means every category.

## `notifyingCountries` (type: `array`):

Only alerts notified by these countries, by name as Safety Gate writes them (Germany, France, Netherlands). Empty means every country.

## `keyword` (type: `string`):

Only alerts whose product, brand, name, description or danger contains this word. Empty means every alert.

## `seriousOnly` (type: `boolean`):

Only alerts at risk level Serious risk. Off means every level.

## `maxAlertsPerReport` (type: `integer`):

Cost ceiling per weekly report; a report holds 50 to 150 alerts.

## Actor input object example

```json
{
  "reports": [
    "latest",
    "latest-1"
  ],
  "seriousOnly": false,
  "maxAlertsPerReport": 500
}
```

# 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 = {
    "reports": [
        "latest",
        "latest-1"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadydata/eu-safety-gate").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 = { "reports": [
        "latest",
        "latest-1",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadydata/eu-safety-gate").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 '{
  "reports": [
    "latest",
    "latest-1"
  ]
}' |
apify call steadydata/eu-safety-gate --silent --output-dataset

```

## MCP server setup

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

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/qv2TFcfBxSGeIosOC/builds/AKYVCZi9cOaiwDG6S/openapi.json
