# ClinicalTrials.gov Scraper & New Trials Monitor (`betteratoms/clinicaltrials-gov-monitor`) Actor

Search and monitor ClinicalTrials.gov by condition, sponsor, phase, status and date range. Monitor mode returns only trials that are new or updated since your last run. Official API v2, no start fee.

- **URL**: https://apify.com/betteratoms/clinicaltrials-gov-monitor.md
- **Developed by:** [Better Atoms Technologies LLP](https://apify.com/betteratoms) (community)
- **Categories:** Business, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 trials

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

## ClinicalTrials.gov Scraper & New Trials Monitor (Official API v2)

Search **ClinicalTrials.gov** by **condition, sponsor, phase, recruitment status and date range**, and export clean trial records as JSON, CSV or Excel. Switch on **monitor mode** and each scheduled run returns **only trials that are new or updated since your last run**. That gives you a daily or weekly feed of trial changes for your indication, competitors or sponsors.

The actor uses **only the official ClinicalTrials.gov API v2** (`https://clinicaltrials.gov/api/v2/studies`), the public registry API run by the U.S. National Library of Medicine. You don't need an API key, a login, proxies or a browser, and it doesn't crawl the website.

### Use cases

- **Pharma and biotech competitive intelligence:** track every Phase 2/3 trial in your indication, or every trial a competitor sponsors, and see status changes, new sites and new trials as they're posted.
- **CRO and site business development:** find trials that are recruiting or not yet recruiting, by condition, phase and country, to target sponsors that need sites and services.
- **Investors and analysts:** monitor pipeline events (new trials, terminations with `whyStopped`, results posted) for the companies you follow.
- **Medical affairs, patient advocacy and newsletters:** a weekly digest of new trials for a disease area, sent to Slack, Google Sheets, email or your CRM with Apify integrations and webhooks.
- **AI agents and RAG pipelines:** clean, structured trial records with summaries, outcomes and interventions.

### Filters

| Field | What it does |
|---|---|
| `conditions` | Diseases or conditions, e.g. `obesity`, `non-small cell lung cancer`. ClinicalTrials.gov expands synonyms. Several values are combined with OR |
| `sponsors` | Lead sponsor or collaborator, e.g. `Pfizer`, `Novo Nordisk` |
| `keywords` | Free text anywhere in the record, e.g. a drug name such as `tirzepatide` |
| `locations` | Site location terms, e.g. `India`, `Germany`, `Boston` |
| `phases` | Early phase 1, phase 1, 2, 3, 4 or not applicable |
| `statuses` | Recruiting, Not yet recruiting, Active not recruiting, Completed, Terminated, … |
| `studyTypes` | Interventional, Observational or Expanded access |
| `dateField`, `dateFrom`, `dateTo` | Date range on last update posted, first posted, start, primary completion or completion date |
| `mode` | `search` (all matches) or `monitor` (only new or updated since the last run) |
| `stateKey`, `monitorInitialLookbackDays` | Monitor memory name, and how far back the first monitor run looks |
| `maxItems` | Maximum trials per run, which also caps your cost |

#### Example: recruiting Phase 3 obesity trials

```json
{ "mode": "search", "conditions": ["obesity"], "phases": ["PHASE3"], "statuses": ["RECRUITING"], "maxItems": 500 }
```

#### Example: daily monitor of a competitor's oncology trials

```json
{ "mode": "monitor", "sponsors": ["AstraZeneca"], "conditions": ["cancer"], "stateKey": "az-oncology",
  "monitorInitialLookbackDays": 30, "maxItems": 1000 }
```

Schedule it daily in Apify Console (Schedules). The first run returns trials updated in the last 30 days. Each later run returns only trials that are new or have a newer "last update posted" date, tagged `changeType: "new"` or `"updated"`.

### Sample output

Real record from the local test run on 23 Oct 2026 (summary shortened):

```json
{
  "nctId": "NCT07220772",
  "briefTitle": "A Study Evaluating Mibavademab Treatment of Obesity Due to Leptin (LEP) Gene Mutations in Children, Adolescents and Adults",
  "orgStudyId": "R4461-MOB-2471",
  "overallStatus": "RECRUITING",
  "studyType": "INTERVENTIONAL",
  "phases": ["PHASE3"],
  "conditions": ["Monogenic Obesity"],
  "interventions": [{ "type": "DRUG", "name": "Mibavademab" }],
  "leadSponsor": "Regeneron Pharmaceuticals",
  "leadSponsorClass": "INDUSTRY",
  "collaborators": [],
  "enrollment": 4, "enrollmentType": "ESTIMATED",
  "allocation": "NA", "primaryPurpose": "TREATMENT",
  "sex": "ALL", "minimumAge": "2 Years", "maximumAge": null, "healthyVolunteers": false,
  "primaryOutcomes": ["Percent change in Body Mass Index (BMI)"],
  "startDate": "2026-02-09",
  "primaryCompletionDate": "2027-06-18",
  "completionDate": "2028-04-21",
  "studyFirstPostDate": "2025-10-24",
  "lastUpdatePostDate": "2026-10-22",
  "resultsFirstPostDate": null, "hasResults": false,
  "locationCount": 3,
  "locationCountries": ["Germany", "Turkey (Türkiye)"],
  "briefSummary": "This study is researching an experimental drug called mibavademab. …",
  "url": "https://clinicaltrials.gov/study/NCT07220772",
  "source": "ClinicalTrials.gov API v2",
  "scrapedAt": "2026-10-23T04:12:34.001406Z"
}
```

In monitor mode each record also has `changeType` (`new`, `updated`, or `initial` on the first run). `sample_output.json` holds more real records.

### Pricing

Pay per result: **$0.002 per trial** ($2 per 1,000 trials). There's **no start fee**, so a monitor run that finds nothing new costs you nothing in result fees. Use `maxItems` to cap spend.

### FAQ

**Is this allowed?**
Yes. The actor calls the public ClinicalTrials.gov API v2, which NLM provides for programmatic access. It doesn't scrape the website. Please follow ClinicalTrials.gov's terms and cite it as the source when you republish.

**How does monitor mode know what's new?**
It keeps a small state per `stateKey` in a named key-value store in your Apify account (`clinicaltrials-monitor-state`), with a "last update posted" watermark and the trial IDs already returned for that date. Each run asks the API only for trials updated on or after the watermark and skips versions you already received. The run's default key-value store also gets a copy (`MONITOR_STATE`) and a `RUN_SUMMARY`. Changes are processed oldest first, so if `maxItems` stops a run early, the next run picks up where it left off.

**How often should I run the monitor?**
ClinicalTrials.gov refreshes its data once a day (on weekdays), so a daily schedule is enough.

**Does it include investigator or contact details?**
No. Contact names, emails and phone numbers are left out on purpose. You get sponsor, design, status, dates, countries and site counts.

**Why are some fields `null`?**
The sponsor didn't report them. The actor never fills in or guesses values.

**Rate limits?**
The actor waits 1.5 seconds between API requests (at most about 40 per minute) and retries 429 and 5xx responses with backoff, honouring `Retry-After`. One request returns up to 1,000 trials, so most runs finish in seconds.

### Notes and limits

- Data is provided as-is by sponsors through ClinicalTrials.gov. Always confirm details on the linked study page.
- Dates are reported as the registry publishes them. Some are month-only, such as `2027-06`.
- This actor is not affiliated with or endorsed by NIH, NLM or ClinicalTrials.gov.

### Local development

```bash
pip install -r requirements.txt
## edit storage/key_value_stores/default/INPUT.json, then:
python -m src
## end-to-end test (5 runs against the live API v2, including monitor mode):
python tests/run_local_test.py
```

# Actor input Schema

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

search returns every trial that matches (up to maxItems). monitor remembers what it returned for this stateKey and on later runs returns only trials that are new or have a newer 'last update posted' date.

## `conditions` (type: `array`):

e.g. obesity, type 2 diabetes, Alzheimer disease. Several values are combined with OR. ClinicalTrials.gov expands synonyms.

## `sponsors` (type: `array`):

Lead sponsor or collaborator names, e.g. Pfizer, Novo Nordisk, National Cancer Institute. Several values are combined with OR.

## `keywords` (type: `array`):

Free-text terms matched anywhere in the record, e.g. a drug name such as semaglutide. Several values are combined with OR.

## `locations` (type: `array`):

Trial site location terms, e.g. India, Germany, Boston. Several values are combined with OR.

## `phases` (type: `array`):

Leave empty for all phases.

## `statuses` (type: `array`):

Leave empty for all statuses.

## `studyTypes` (type: `array`):

Leave empty for all study types.

## `dateField` (type: `string`):

Which date the 'from' and 'to' fields filter on.

## `dateFrom` (type: `string`):

Inclusive, YYYY-MM-DD. Leave empty for no lower bound.

## `dateTo` (type: `string`):

Inclusive, YYYY-MM-DD. Leave empty for no upper bound.

## `sort` (type: `string`):

Monitor mode always processes the oldest changes first, so nothing is skipped when maxItems stops a run early.

## `stateKey` (type: `string`):

Name for this saved search's memory. Use a different key for each search you monitor.

## `monitorInitialLookbackDays` (type: `integer`):

On the first monitor run for a stateKey, return trials updated in the last N days (up to maxItems) and remember them.

## `summaryMaxChars` (type: `integer`):

Truncate the brief summary to this many characters. 0 = no limit.

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

Maximum number of trials to return. Each returned trial is one billable result.

## Actor input object example

```json
{
  "mode": "search",
  "conditions": [
    "non-small cell lung cancer"
  ],
  "dateField": "lastUpdatePostDate",
  "sort": "LastUpdatePostDate:desc",
  "stateKey": "default",
  "monitorInitialLookbackDays": 30,
  "summaryMaxChars": 1000,
  "maxItems": 100
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing all output rows

## `runSummary` (type: `string`):

RUN_SUMMARY record with counts and timing 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 = {
    "conditions": [
        "non-small cell lung cancer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("betteratoms/clinicaltrials-gov-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 = { "conditions": ["non-small cell lung cancer"] }

# Run the Actor and wait for it to finish
run = client.actor("betteratoms/clinicaltrials-gov-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 '{
  "conditions": [
    "non-small cell lung cancer"
  ]
}' |
apify call betteratoms/clinicaltrials-gov-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,betteratoms/clinicaltrials-gov-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/DXxzdf1Uv4upBDXfH/builds/lHFSX4h7LLfaVgRnt/openapi.json
