# EUDAMED Scraper - EU Medical Devices, MDR & IVDR (`perceptr0n/eudamed-medical-device-scraper`) Actor

Export devices, manufacturers and notified-body certificates from EUDAMED, the EU's mandatory medical device registry. Risk class, market status, sterility, latex and CMR flags, market availability per country, CND codes and warnings — codes resolved to plain language.

- **URL**: https://apify.com/perceptr0n/eudamed-medical-device-scraper.md
- **Developed by:** [Thomas Ehrler](https://apify.com/perceptr0n) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.02 / actor start

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## EUDAMED Scraper — EU Medical Device Registry (MDR/IVDR)

Export the EU's **mandatory medical device registry** as clean, analysis-ready
data: **~3 million devices**, **31,800+ manufacturers** and **4,000+
notified-body certificates**, with every regulatory code resolved to plain
language.

EUDAMED is where every manufacturer must register every device sold in the EU
under MDR (2017/745) and IVDR (2017/746). It has **no official API, no export
button and no bulk download**. This actor is the practical alternative.

### Why this is not a five-minute scraper

The registry's own interface hides most of the value behind three obstacles.
This actor solves all three:

| Obstacle | What it means | How this actor handles it |
|---|---|---|
| **Codes instead of values** | Every field arrives as a token like `refdata.risk-class.class-iii` or `CW010` | Resolves against **12 reference tables** — including all **423 standardised warning texts** — so you get "Class III" and the full warning sentence |
| **Thin list view** | The searchable list returns 32 fields of which only ~15 carry data — no trade name, no sterility, no markets | Fetches the **full profile per device** (61 fields) and merges it |
| **Multilingual text arrays** | Trade names and descriptions are stored once per EU language | Flattens to your chosen language with English fallback |

On top of that the registry **throttles hard** — bursts get cut off for minutes.
This actor paces every request and backs off exponentially, so long runs finish
instead of dying halfway.

### What you get per device

| Field | Example |
|---|---|
| `tradeName`, `primaryDi`, `basicUdi`, `referenceNumber` | ASSUPRO · 48033439452423 · 8033439ASSUPRO4P · 02PY891SAM |
| `manufacturerName`, `manufacturerSrn`, `manufacturerStatus` | ASSUT EUROPE SPA · IT-MF-000018178 · Active |
| `riskClass`, `deviceStatus` | Class III · On the market |
| `placedOnTheMarketCountry` | Italy |
| **`marketsWhereAvailable`** | Bulgaria, Cyprus, Czechia, Germany, France, Italy, Malta, Romania |
| `nomenclatures` | `H010201010402` — Polypropylene monofilament with needle for video surgery |
| `isSterile`, `isSingleUse`, `isReprocessed`, `containsLatex`, `containsCmrSubstance`, `isEndocrineDisruptor`, `annexXVIApplicable`, `isOemProduct` | true / false flags |
| `udiProductionIdentifiers` | batchNumber, expirationDate |
| `criticalWarnings` | full standardised warning texts |
| `instructionsForUseUrl` | link to the manufacturer's eIFU document |
| `versionNumber`, `isLatestVersion`, `lastUpdated`, `eudamedUrl` | provenance |

**Manufacturer mode** adds company records with SRN, registration date, full
postal address, **e-mail and phone** — the registry's economic-operator data.

**Certificate mode** returns notified-body certificates with type, status,
issue/expiry dates, manufacturer SRN and notified-body SRN.

### Use cases

- **Regulatory affairs & market access** — verify what a competitor has
  registered, in which countries, under which risk class
- **Competitive intelligence in medtech** — track new registrations, device
  families under a Basic UDI-DI, and market withdrawals
- **Supplier & partner search** — find every EU manufacturer in a device
  category, with contact details
- **Compliance & audit** — check certificate validity and expiry against
  manufacturers you buy from
- **Distribution scouting** — `marketsWhereAvailable` shows which EU countries a
  device is *not* yet sold in
- **Research & data products** — a normalised feed of the EU device market
- **AI agents** — clean schema and plain-language values, callable via MCP

### Input examples

Every high-risk (Class III) device currently on the market, with full profiles:

```json
{
    "mode": "devices",
    "risk_class": "refdata.risk-class.class-iii",
    "device_status": "refdata.device-model-status.on-the-market",
    "include_details": true,
    "max_items": 1000
}
```

All versions of one device family:

```json
{ "mode": "devices", "basic_udi": "8033439ASSUPRO4P" }
```

German manufacturers with contact details:

```json
{ "mode": "manufacturers", "actor_type": "refdata.actor-type.manufacturer", "max_items": 2000 }
```

Notified-body certificates:

```json
{ "mode": "certificates", "max_items": 500 }
```

### Output example (shortened)

```json
{
    "tradeName": "ASSUPRO",
    "primaryDi": "48033439452423",
    "basicUdi": "8033439ASSUPRO4P",
    "manufacturerName": "ASSUT EUROPE SPA",
    "manufacturerSrn": "IT-MF-000018178",
    "riskClass": "Class III",
    "deviceStatus": "On the market",
    "placedOnTheMarketCountry": "Italy",
    "marketsWhereAvailable": ["Bulgaria", "Cyprus", "Czechia", "Germany", "France", "Italy", "Malta", "Romania"],
    "nomenclatures": [{ "code": "H010201010402", "description": "POLYPROPYLENE MONOFILAMENT WITH NEEDLE FOR VIDEO SURGERY" }],
    "isSterile": true,
    "isSingleUse": true,
    "containsLatex": false,
    "udiProductionIdentifiers": ["batchNumber", "expirationDate"],
    "instructionsForUseUrl": "https://www.assuteurope.com/public/eifu/12A_MDR_R0.pdf",
    "eudamedUrl": "https://ec.europa.eu/tools/eudamed/#/screen/search-device/8de0765f-..."
}
```

### Performance & limits — stated honestly

- The registry serves **300 records per page maximum**, and this is a hard
  server-side cap that cannot be raised.
- With `include_details: true` each device costs one extra request. Expect
  roughly **1–2 devices per second**, deliberately — going faster gets the run
  throttled and produces nothing.
- Filters the registry actually supports are **risk class**, **market status**,
  **Primary DI** and **Basic UDI-DI**. Manufacturer-name and country filters are
  *not* supported by the registry's search endpoint; filter those in your own
  pipeline after export. This actor only sends parameters that work, instead of
  silently ignoring your input.
- If the registry throttles the run, the actor **fails loudly with an
  explanation** rather than writing empty rows.

### Data protection & legal

- All data is **mandatory public disclosure** under MDR Art. 33 / IVDR Art. 30.
  The EU publishes it precisely so it can be inspected.
- Records describe **companies and products**, not natural persons. The e-mail
  and phone fields in operator mode are the company's official regulatory
  contact points as published in the registry.
- No login, no paywall and no access control is circumvented; the endpoints used
  are the same ones the public web interface calls.
- Not affiliated with or endorsed by the European Commission.

### What does a run cost?

| Records | Cost |
|---|---|
| 100 devices | $3.02 |
| 1,000 devices | $30.02 |
| 1,000 manufacturers | $30.02 |

$0.02 per run start plus $0.03 per record. For comparison: commercial medtech
market-intelligence subscriptions covering this data start in the five-figure
range per year.

### FAQ

**Is there an official EUDAMED API or export?**
No. EUDAMED has a public web interface but no documented API, no export button
and no bulk download. This actor is the practical way to get the data as a file.

**How many devices are in the registry?**
About 2.99 million device records, of which roughly 122,000 are Class III. Plus
31,800 economic operators and 4,055 notified-body certificates.

**Can I filter by manufacturer or country?**
Not at the registry level — its search endpoint ignores those parameters,
silently. This actor only sends filters that actually work (risk class, market
status, Primary DI, Basic UDI-DI) and tells you so, rather than pretending. For
manufacturer or country filtering, export and filter in your own pipeline, or
use `mode: "manufacturers"` which returns operators with their country.

**Why is it slower than other scrapers?**
Deliberately. The registry throttles bursts and stops answering for minutes.
This actor paces itself at roughly one to two records per second and backs off
exponentially, which is the difference between a run that finishes and a run
that dies at 40 %.

**What is a Basic UDI-DI?**
The identifier for a device *family*. Passing one returns every device version
that belongs to it — the fastest way to map a competitor's product line.

**Is this data legal to use?**
Yes. It is mandatory public disclosure under MDR Art. 33 and IVDR Art. 30, about
companies and products rather than natural persons, published by the EU
precisely so it can be inspected.

### Related actors

| Actor | What it does |
|---|---|
| [EU Public Tenders (TED)](https://apify.com/perceptr0n/eu-tenders-ted-scraper) | EU public procurement notices from all 27 member states |
| [Messe München Exhibitors](https://apify.com/perceptr0n/messe-muenchen-exhibitor-list-scraper) | Trade-fair exhibitors incl. address, e-mail and phone |
| [kununu Scraper](https://apify.com/perceptr0n/kununu-employer-data-scraper) | Employer ratings and salary data for DACH companies |

### Support

Need another field, filter, mode or export shape? Open an issue in the
**Issues** tab — response within 1–2 business days.

# Actor input Schema

## `mode` (type: `string`):

Devices (UDI-DI records), economic operators (manufacturers, importers, authorised representatives) or notified-body certificates.

## `risk_class` (type: `string`):

MDR risk class. Class III is the high-risk segment (implants, life-supporting devices).

## `device_status` (type: `string`):

Whether the device is currently placed on the EU market.

## `primary_di` (type: `string`):

Look up one device by its Primary Device Identifier, e.g. `48033439452423`.

## `basic_udi` (type: `string`):

Return every device version under one Basic UDI-DI, e.g. `8033439ASSUPRO4P`.

## `operator_name` (type: `string`):

Filter economic operators or certificates by company name.

## `actor_type` (type: `string`):

Which kind of economic operator to export.

## `include_details` (type: `boolean`):

ON: adds trade name, sterility, single-use, latex, CMR substances, market availability per country, UDI production identifiers, critical warnings and the instructions-for-use link — one extra request per device. OFF: fast list mode (identifiers, manufacturer, risk class, status).

## `language` (type: `string`):

Trade names and descriptions are stored per language; this picks one, falling back to English.

## `max_items` (type: `integer`):

Stop after this many records. The registry holds ~3 million devices — start small.

## Actor input object example

```json
{
  "mode": "devices",
  "actor_type": "refdata.actor-type.manufacturer",
  "include_details": true,
  "language": "en",
  "max_items": 500
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("perceptr0n/eudamed-medical-device-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("perceptr0n/eudamed-medical-device-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call perceptr0n/eudamed-medical-device-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=perceptr0n/eudamed-medical-device-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/1tZ8r01QQz11Bc84H/builds/botd3bvCkKOi7f273/openapi.json
