# EMA European Medicines Search (`ryanclinton/ema-medicines-search`) Actor

Search the European Medicines Agency (EMA) database for medicines authorized across the European Union. This actor queries the official EMA medicines dataset -- updated twice daily -- and returns structured, clean data on human and veterinary medicines.

- **URL**: https://apify.com/ryanclinton/ema-medicines-search.md
- **Developed by:** [Ryan Clinton](https://apify.com/ryanclinton) (community)
- **Categories:** AI, Developer tools
- **Features:** Limited permissions
- **Stats:** 17 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 medicine fetcheds

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

## EMA European Medicines Search

Search the European Medicines Agency (EMA) database for medicines authorized across the European Union. This actor queries the official EMA medicines dataset -- updated twice daily -- and returns structured, clean data on human and veterinary medicines. Filter by medicine name, active substance, INN, therapeutic area, authorisation status, and category. No API key is required. Results include 23 structured fields covering regulatory flags, ATC codes, marketing authorisation holders, and direct links to the EMA product page.

***

### Why use EMA European Medicines Search

The European Medicines Agency maintains the authoritative register of all centrally authorized medicines in the EU. This dataset covers thousands of human and veterinary medicines, each with detailed regulatory metadata including orphan designations, conditional approvals, biosimilar status, and more. Accessing this information manually through the EMA website requires navigating a complex interface with limited export options.

This actor transforms the raw EMA dataset into clean, structured JSON that is ready for analysis, integration, or monitoring. Boolean fields like orphan medicine status and accelerated assessment are converted from raw "yes"/"no" strings into proper boolean values. HTML markup in therapeutic indication text is stripped and normalized. Results are sorted by relevance -- exact medicine name matches appear first, followed by INN matches, then by most recently updated.

Whether you are tracking newly authorized medicines in a therapeutic area, monitoring the status of competitor products, building a pharmaceutical knowledge base, or conducting regulatory intelligence research, this actor provides the data pipeline you need without requiring API keys, authentication, or complex request handling.

***

### Key features

- **Complete EMA database access** -- queries the full European Medicines Agency dataset containing all centrally authorized EU medicines
- **Multi-field text search** -- matches your query against medicine name, active substance, INN, therapeutic area, pharmacotherapeutic group, marketing authorisation holder, ATC code, and EMA product number
- **Category filtering** -- narrow results to Human medicines, Veterinary medicines, or search across both categories
- **Authorisation status filtering** -- filter by Authorised, Withdrawn, Refused, Suspended, Revoked, or Expired/Lapsed status
- **Therapeutic area filtering** -- partial match filtering on MeSH therapeutic area terms such as "Diabetes Mellitus" or "HIV Infections"
- **Relevance-ranked results** -- exact name matches appear first, then INN matches, then sorted by most recently updated date
- **Clean data output** -- HTML tags stripped from indication text, boolean conversion for regulatory flags, normalized whitespace throughout
- **No API key required** -- uses the publicly available EMA dataset with no authentication needed
- **Real-time data** -- EMA updates this dataset twice daily, so results reflect current authorisation status
- **Up to 500 results per run** -- configurable result limit from 1 to 500 medicines per execution

***

### How to use

#### Using the Apify Console

1. Navigate to the [EMA European Medicines Search](https://apify.com/ryanclinton/ema-medicines-search) actor page on Apify.
2. Click the **Try for free** button to open the actor in the Apify Console.
3. Enter your search query in the **Search Query** field (e.g., "insulin", "pembrolizumab", "diabetes").
4. Optionally select a **Category** (Human or Veterinary) and **Authorisation Status** filter.
5. Optionally enter a **Therapeutic Area** for additional filtering (e.g., "Neoplasms").
6. Set the **Max Results** to control how many medicines are returned (default: 50).
7. Click **Start** to run the actor.
8. When the run finishes, view results in the **Dataset** tab or export as JSON, CSV, or Excel.

#### Using the Apify API

You can start the actor programmatically and retrieve results via the Apify API.

**cURL:**

```bash
curl -X POST "https://api.apify.com/v2/acts/ryanclinton~ema-medicines-search/runs?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "insulin",
    "category": "Human",
    "status": "Authorised",
    "maxResults": 20
  }'
```

**JavaScript (Apify Client):**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('ryanclinton/ema-medicines-search').call({
    query: 'insulin',
    category: 'Human',
    status: 'Authorised',
    maxResults: 20,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**Python (Apify Client):**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("ryanclinton/ema-medicines-search").call(run_input={
    "query": "insulin",
    "category": "Human",
    "status": "Authorised",
    "maxResults": 20,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in items:
    print(item["medicineName"], item["authorisationStatus"])
```

***

### Input parameters

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `query` | String | Yes | -- | Medicine name, active substance, INN, ATC code, or keyword to search for |
| `category` | String | No | `All` | Filter by category: `All`, `Human`, or `Veterinary` |
| `status` | String | No | `All` | Filter by authorisation status: `All`, `Authorised`, `Withdrawn`, `Refused`, `Suspended`, `Revoked`, or `Expired` |
| `therapeuticArea` | String | No | -- | Filter by therapeutic area using partial match (e.g., "Diabetes Mellitus", "HIV Infections") |
| `maxResults` | Integer | No | `50` | Maximum number of results to return (1--500) |

**Example input JSON:**

```json
{
    "query": "pembrolizumab",
    "category": "Human",
    "status": "Authorised",
    "therapeuticArea": "Neoplasms",
    "maxResults": 10
}
```

**Tips for best input:**

- Use generic drug names (INN) for the broadest matches -- e.g., "adalimumab" instead of "Humira"
- Use brand names for specific product lookups -- e.g., "Keytruda" for pembrolizumab
- Therapeutic area values use MeSH terminology -- try broad terms like "Neoplasms", "Diabetes Mellitus", or "HIV Infections"
- Combine category and status filters to narrow large result sets
- Set `maxResults` to a smaller value when you only need top matches
- ATC codes can be used as search queries -- e.g., "L01" for antineoplastic agents

***

### Output

Each result contains 23 fields covering medicine identity, regulatory status, and classification flags. Here is a realistic example:

```json
{
    "medicineName": "Keytruda",
    "activeSubstance": "pembrolizumab",
    "inn": "pembrolizumab",
    "therapeuticArea": "Neoplasms",
    "authorisationStatus": "Authorised",
    "authorisationDate": "2015-07-17",
    "marketingAuthorisationHolder": "Merck Sharp & Dohme B.V.",
    "atcCode": "L01FF02",
    "orphanMedicine": false,
    "biosimilar": false,
    "generic": false,
    "conditionIndication": "Keytruda as monotherapy is indicated for the treatment of advanced (unresectable or metastatic) melanoma in adults.",
    "category": "Human",
    "emaProductNumber": "EMEA/H/C/003820",
    "pharmacotherapeuticGroup": "Antineoplastic agents, monoclonal antibodies",
    "conditionalApproval": false,
    "exceptionalCircumstances": false,
    "acceleratedAssessment": false,
    "additionalMonitoring": true,
    "advancedTherapy": false,
    "primePriorityMedicine": false,
    "firstPublishedDate": "2015-07-17",
    "lastUpdatedDate": "2024-11-15",
    "url": "https://www.ema.europa.eu/en/medicines/human/EPAR/keytruda"
}
```

**Output field descriptions:**

| Field | Type | Description |
|-------|------|-------------|
| `medicineName` | String | Brand or product name of the medicine |
| `activeSubstance` | String | Active pharmaceutical ingredient(s) |
| `inn` | String | International Nonproprietary Name (common name) |
| `therapeuticArea` | String | MeSH therapeutic area classification |
| `authorisationStatus` | String | Current regulatory status (Authorised, Withdrawn, etc.) |
| `authorisationDate` | String | Date of marketing authorisation (YYYY-MM-DD) |
| `marketingAuthorisationHolder` | String | Company holding the marketing authorisation |
| `atcCode` | String | Anatomical Therapeutic Chemical classification code |
| `orphanMedicine` | Boolean | Whether the medicine has orphan designation |
| `biosimilar` | Boolean | Whether the medicine is a biosimilar |
| `generic` | Boolean | Whether the medicine is a generic or hybrid |
| `conditionIndication` | String | Approved therapeutic indication (HTML-cleaned) |
| `category` | String | Human or Veterinary |
| `emaProductNumber` | String | EMA product number (e.g., EMEA/H/C/003820) |
| `pharmacotherapeuticGroup` | String | Pharmacotherapeutic classification |
| `conditionalApproval` | Boolean | Granted under conditional marketing authorisation |
| `exceptionalCircumstances` | Boolean | Authorised under exceptional circumstances |
| `acceleratedAssessment` | Boolean | Underwent accelerated assessment procedure |
| `additionalMonitoring` | Boolean | Subject to additional monitoring (black triangle) |
| `advancedTherapy` | Boolean | Classified as an advanced therapy medicinal product |
| `primePriorityMedicine` | Boolean | Designated under the PRIME (Priority Medicines) scheme |
| `firstPublishedDate` | String | Date first published on EMA website |
| `lastUpdatedDate` | String | Date of most recent update |
| `url` | String | Direct link to the EMA product page |

***

### Use cases

- **Pharmaceutical competitive intelligence** -- track newly authorized medicines in your therapeutic area and monitor competitor product statuses
- **Regulatory monitoring** -- detect changes in authorisation status such as withdrawals, suspensions, or revocations across the EU market
- **Orphan drug research** -- identify medicines with orphan designation to analyze rare disease treatment landscapes
- **Biosimilar market tracking** -- filter for biosimilar medicines to monitor market entries and competition against originator biologics
- **Clinical research planning** -- search by therapeutic area and active substance to understand existing treatments before designing clinical trials
- **Pharmacovigilance support** -- identify medicines under additional monitoring (black triangle) or with conditional approvals for safety tracking
- **Healthcare data integration** -- feed structured EMA medicine data into dashboards, databases, or reporting systems via the Apify API
- **Market access analysis** -- combine authorisation dates and MAH data to analyze time-to-market trends across therapeutic areas
- **Academic pharmaceutical research** -- build datasets of authorized medicines for publication analysis, drug classification studies, or policy research
- **Veterinary medicine tracking** -- filter by veterinary category to monitor animal health product authorisations across the EU

***

### API & Integration

Retrieve results programmatically after an actor run completes.

**Python -- fetch dataset results:**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
dataset = client.dataset("DATASET_ID")
items = dataset.list_items().items

for medicine in items:
    print(f"{medicine['medicineName']} -- {medicine['authorisationStatus']}")
```

**JavaScript -- fetch dataset results:**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const { items } = await client.dataset('DATASET_ID').listItems();

items.forEach((medicine) => {
    console.log(`${medicine.medicineName} -- ${medicine.authorisationStatus}`);
});
```

**cURL -- fetch dataset as JSON:**

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&token=YOUR_API_TOKEN"
```

**Export formats:** Download results as JSON, CSV, Excel, XML, or RSS directly from the dataset API endpoint by changing the `format` parameter.

**Integrations:** Connect this actor to your existing workflows using Apify's built-in integrations:

- **Zapier** -- trigger actions in 5,000+ apps when new medicine data is available
- **Make (Integromat)** -- build automated pharmaceutical data pipelines
- **Google Sheets** -- export medicine data directly to spreadsheets for team analysis
- **Slack** -- receive notifications when new medicines match your search criteria
- **Webhooks** -- POST results to your own API endpoints for custom processing
- **GitHub** -- store medicine datasets in repositories for version-controlled research data

***

### How it works

1. **Input validation** -- the actor reads and validates your search query and optional filter parameters
2. **Data fetch** -- a single HTTP request retrieves the complete EMA medicines dataset from the official EMA JSON endpoint (updated twice daily by EMA)
3. **Multi-field search** -- your query is matched case-insensitively against 11 fields: medicine name, active substance, INN, therapeutic area, therapeutic indication, pharmacotherapeutic group (human and veterinary), marketing authorisation holder, ATC code (human and veterinary), and EMA product number
4. **Category filtering** -- results are filtered by Human or Veterinary category if specified
5. **Status filtering** -- results are filtered by authorisation status, with intelligent matching for grouped statuses (e.g., "Expired" matches both "expired" and "lapsed")
6. **Therapeutic area filtering** -- partial case-insensitive match against MeSH therapeutic area terms
7. **Relevance sorting** -- results are ranked with exact medicine name matches first, then INN matches, then by most recently updated date
8. **Data transformation** -- raw EMA fields are mapped to clean output names, HTML is stripped from indication text, and yes/no strings are converted to boolean values
9. **Result limiting** -- output is capped at your specified maxResults (default 50, maximum 500)
10. **Dataset push** -- clean, structured results are pushed to the Apify dataset for retrieval

```
Input Query & Filters
        |
        v
  [Fetch EMA JSON Dataset]
        |
        v
  [Multi-Field Text Search]
        |
        v
  [Apply Category Filter]
        |
        v
  [Apply Status Filter]
        |
        v
  [Apply Therapeutic Area Filter]
        |
        v
  [Sort by Relevance]
        |
        v
  [Transform & Clean Data]
        |
        v
  [Limit & Push to Dataset]
```

***

### Performance & cost

| Metric | Value |
|--------|-------|
| Average run time | 5--15 seconds |
| Memory usage | 256 MB (default) |
| Compute units per run | ~0.005 CU |
| Cost per run (pay-as-you-go) | ~$0.025 |
| Free tier runs (per month) | ~100 runs with free Apify plan |
| Data source freshness | Updated twice daily by EMA |
| Network requests per run | 1 (single dataset fetch) |

The actor makes a single HTTP request to download the complete EMA dataset, then processes everything in memory. This means run times are consistent regardless of query complexity or filter combinations. Smaller `maxResults` values do not significantly affect performance since filtering happens in-memory after the full dataset is loaded.

***

### Limitations

- **Single data source** -- only searches the EMA centrally authorized medicines database; does not include nationally authorized medicines in individual EU member states
- **Dataset freshness** -- data is updated twice daily by EMA; real-time changes may not be reflected immediately
- **Text search only** -- does not support advanced query syntax, boolean operators, or field-specific search targeting
- **No historical tracking** -- returns current state only; does not track changes over time (combine with the Website Change Monitor actor for change detection)
- **500 result cap** -- maximum of 500 results per run; for the complete dataset, consider downloading the EMA JSON directly
- **English language only** -- searches and results are in English as provided by the EMA dataset
- **No pagination** -- all matching results up to maxResults are returned in a single dataset; no cursor-based pagination

***

### Responsible use

- **Respect EMA terms of use** -- this actor accesses publicly available EMA data; ensure your usage complies with the EMA's terms and conditions for data reuse
- **Not for clinical decisions** -- output data is for informational and research purposes only; do not use as the sole basis for clinical, prescribing, or patient care decisions
- **Rate consideration** -- while the actor makes only one request per run, avoid scheduling excessively frequent runs since the dataset only updates twice daily
- **Attribution** -- when publishing or distributing data obtained from this actor, credit the European Medicines Agency as the original data source
- **Data accuracy** -- always verify critical regulatory information against the official EMA website before making business or compliance decisions

***

### FAQ

**Q: Do I need an API key to use this actor?**
**A:** No. The actor accesses the publicly available EMA medicines dataset, which requires no authentication or API key. You only need an Apify account to run the actor.

**Q: How current is the data?**
**A:** The EMA updates the medicines dataset twice daily. The actor fetches the latest version each time it runs, so results are typically no more than 12 hours old.

**Q: Can I search for veterinary medicines?**
**A:** Yes. Set the `category` filter to "Veterinary" to search only veterinary medicines, or leave it as "All" to search across both human and veterinary products.

**Q: What does the "Expired" status filter include?**
**A:** The "Expired" status filter matches both "Expired" and "Lapsed" authorisation statuses in the EMA database, as these represent similar end-of-lifecycle states.

**Q: How does the search matching work?**
**A:** Your query is matched case-insensitively against 11 fields including medicine name, active substance, INN, therapeutic area, therapeutic indication, pharmacotherapeutic group, marketing authorisation holder, ATC code, and EMA product number. Any partial match in any field returns the medicine.

**Q: Can I search by ATC code?**
**A:** Yes. Enter an ATC code (e.g., "L01FF02" or partial codes like "L01") in the search query field. The actor searches both human ATC codes and veterinary ATCvet codes.

**Q: What are the boolean regulatory flags?**
**A:** The output includes boolean fields for: `orphanMedicine`, `biosimilar`, `generic`, `conditionalApproval`, `exceptionalCircumstances`, `acceleratedAssessment`, `additionalMonitoring`, `advancedTherapy`, and `primePriorityMedicine`. These indicate special regulatory designations and are converted from the EMA's raw "yes"/"no" text values.

**Q: How are results sorted?**
**A:** Results are sorted by relevance. Medicines where the query matches the product name appear first, followed by matches on INN (International Nonproprietary Name), then all remaining matches sorted by most recently updated date.

**Q: Can I export results as CSV or Excel?**
**A:** Yes. After the actor run completes, you can export the dataset in JSON, CSV, Excel, XML, or RSS format from the Apify Console or via the API by changing the `format` parameter.

**Q: What is the conditionIndication field?**
**A:** This field contains the approved therapeutic indication text with HTML tags stripped, `&nbsp;` entities removed, and whitespace normalized. It describes what the medicine is authorized to treat.

**Q: Can I schedule this actor to run automatically?**
**A:** Yes. Use Apify's built-in scheduler to run the actor on a recurring basis -- daily or twice daily aligns well with the EMA's update frequency.

**Q: Does this actor cover all EU medicines?**
**A:** It covers all centrally authorized medicines evaluated by the EMA. Medicines authorized only at the national level by individual EU member state agencies are not included.

***

### Related actors

| Actor | Description | Link |
|-------|-------------|------|
| Clinical Trial Tracker | Search ClinicalTrials.gov for active and completed clinical trials | [View on Apify](https://apify.com/ryanclinton/clinical-trial-tracker) |
| FDA Food Recall Monitor | Monitor FDA food product recalls and safety alerts | [View on Apify](https://apify.com/ryanclinton/fda-food-recall-monitor) |
| FDA Medical Device Recall Search | Search FDA medical device recalls and safety notices | [View on Apify](https://apify.com/ryanclinton/fda-device-recalls) |
| openFDA Drug Event Monitor | Search FDA adverse drug event reports and safety data | [View on Apify](https://apify.com/ryanclinton/openfda-drug-events) |
| PubMed Biomedical Literature Search | Search PubMed for biomedical and life science research papers | [View on Apify](https://apify.com/ryanclinton/pubmed-research-search) |
| CPSC Product Recall Monitor | Monitor US Consumer Product Safety Commission recalls | [View on Apify](https://apify.com/ryanclinton/cpsc-recall-monitor) |

# Actor input Schema

## `query` (type: `string`):

Medicine name, active substance, INN, or keyword to search for in the EMA database.

## `category` (type: `string`):

Filter medicines by category (Human or Veterinary).

## `status` (type: `string`):

Filter by authorisation status.

## `therapeuticArea` (type: `string`):

Filter by therapeutic area (e.g. 'Diabetes Mellitus', 'HIV Infections'). Partial match supported.

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

Maximum number of results to return (1-500).

## Actor input object example

```json
{
  "query": "insulin",
  "category": "All",
  "status": "All",
  "maxResults": 50
}
```

# 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 = {
    "query": "insulin"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ryanclinton/ema-medicines-search").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 = { "query": "insulin" }

# Run the Actor and wait for it to finish
run = client.actor("ryanclinton/ema-medicines-search").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 '{
  "query": "insulin"
}' |
apify call ryanclinton/ema-medicines-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ryanclinton/ema-medicines-search"
        }
    }
}
```

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/WYkhQBLXcX4GwwBR2/builds/nR6B7XK0IymRsMrVi/openapi.json
