# ClinicalTrials.gov Study Monitor & Search (`brightish_ascent/clinicaltrials-study-monitor`) Actor

Unofficial; not affiliated with NIH/NLM. Search and monitor clinical studies from the official ClinicalTrials.gov API by condition, drug, sponsor, status, phase, location and dates. Only-new results plus status, recruiting and results-posted changes. Not medical advice.

- **URL**: https://apify.com/brightish_ascent/clinicaltrials-study-monitor.md
- **Developed by:** [Michael Rice](https://apify.com/brightish_ascent) (community)
- **Categories:** Business, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 study rows

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 Study Monitor & Search

**Unofficial.** Not affiliated with or endorsed by ClinicalTrials.gov, the U.S. National Library of Medicine (NLM), the National Institutes of Health (NIH) or the U.S. Department of Health and Human Services (HHS). Data comes from the official [ClinicalTrials.gov Data API v2](https://clinicaltrials.gov/data-api/api). Source: ClinicalTrials.gov, a U.S. Government database run by NLM. Use of the data is subject to the [ClinicalTrials.gov Terms and Conditions](https://clinicaltrials.gov/about-site/terms-conditions).

**Not medical advice.** This tool returns registry records for research, business and monitoring use. Do not use it to make medical decisions. Talk to a health care provider before joining a study, and check the study page on ClinicalTrials.gov for current details.

Search clinical studies by condition, intervention, sponsor, overall status, phase, location and dates. Put it on a schedule with **Only new or changed since last run** to get just newly matching studies, plus studies whose status, recruiting sites or results changed.

### What you get

One row per study (`nctId`), most recently updated first: titles, overall status (and why stopped), results posted flag and date, study type, phases, enrollment, conditions, interventions (type and name), lead sponsor and class, collaborators, start / primary completion / completion dates, first posted and last update posted dates, location count, recruiting-site count, countries, the first 10 locations (facility, city, state, country, site status) and the study page link.
Rows also carry `updateType` (`new` / `changed` in monitor mode, otherwise `null`), `changeReasons`, `previousStatus`, `changeHash` and `dataTimestamp` (when ClinicalTrials.gov last processed its data). `compact` output keeps the key fields, including `updateType`, `changeReasons`, `changeHash` and `dataTimestamp`.

**No personal contact data:** contact names, email addresses and phone numbers are never output. (The ClinicalTrials.gov terms also forbid using its email addresses for marketing.)

### Input

| Field | Notes |
|---|---|
| condition | e.g. "type 2 diabetes" (synonyms included by ClinicalTrials.gov) |
| intervention | drug, device or other intervention, e.g. "pembrolizumab" |
| sponsor | lead sponsor or collaborator, e.g. "Pfizer" |
| location | facility, city, state or country of a site |
| keywords | free-text search across the record |
| statuses | overall status list, e.g. RECRUITING, NOT_YET_RECRUITING, COMPLETED, TERMINATED |
| phases | EARLY_PHASE1, PHASE1, PHASE2, PHASE3, PHASE4, NA |
| startDateFrom / startDateTo | study start date range (YYYY-MM-DD) |
| firstPostedFrom / firstPostedTo | first posted date range |
| lastUpdatedFrom / lastUpdatedTo | last update posted date range |
| onlyWithResults | only studies with posted results |
| maxItems | rows per run, default 25, max 5000 |
| onlyNewSinceLastRun, lookbackDays | monitor mode, see below |
| outputFormat | full or compact |

At least one filter is required (an unfiltered query would cover the whole registry).

Example: recruiting Phase 2/3 lung cancer studies with a site in Colorado, only new or changed:

```json
{ "condition": "lung cancer", "statuses": ["RECRUITING"], "phases": ["PHASE2", "PHASE3"], "location": "Colorado", "onlyNewSinceLastRun": true }
```

### Only new or changed since last run

The first run with a set of filters is a baseline: normal results, then a watermark is saved in a named key-value store in **your** Apify account (`clinicaltrials-study-monitor-state`). Later runs with the same filters ask ClinicalTrials.gov only for studies whose last update was posted since the previous complete run (minus one day, because updates are posted by date), and never more than `lookbackDays` (default 30) back. They return:

- `new`: studies not delivered before for these filters (including studies that newly match, e.g. a status filter they now meet);
- `changed`: delivered studies where a tracked field changed: overall status, number of recruiting / not-yet-recruiting sites, results posted, phases, enrollment count, why stopped, primary completion date or completion date. `changeReasons` lists `statusChanged`, `resultsPosted`, `recruitingSitesChanged` and/or `otherTrackedField`; `previousStatus` is set when the status changed.

Record updates that touch only other fields (for example eligibility text or contacts) are not re-sent. Changed rows are charged like any other row. If a monitor run is cut short (maxItems, your cost limit or the request cap), the rest arrive on the next run. If a baseline run is cut short, older matching studies (last updated before the oldest delivered row) are not delivered later unless they are updated; run once without monitor mode to get them. If a schedule is paused longer than `lookbackDays`, updates older than that window are not caught up. Studies that stop matching your filters (for example no longer recruiting, with a RECRUITING filter) are not reported, because the API no longer returns them; leave `statuses` empty if you want to see status changes in every direction. Withdrawn or removed records are not reported as deletions. Compact rows include `changeHash`.

### Run summary

The `OUTPUT` record has `count`, `chargedCount`, the API request URL, `pagesFetched`, `returnedByApi`, `totalMatching`, `apiVersion`, `dataTimestamp`, `truncated` (true only when more matching rows exist beyond `maxItems`, the cost limit or the request cap; a run with exactly `maxItems` matches is not truncated; on a cut-short monitor baseline `olderMatchesSkipped` is also true), monitor details (`newCount`, `changedCount`, `statusChangedCount`, `resultsPostedCount`, all counted from pushed rows, plus `skippedUnchanged`, the cursor and the window used) and request stats.

### Limits and notes

- The Actor waits at least 1.3 seconds between requests (retries included; well above the 250 ms minimum, to stay under the commonly reported ClinicalTrials.gov limit of about 50 requests per minute per IP) and makes at most 40 requests per run (200 studies per page). A default run makes 2 requests.
- Records are summary information supplied by sponsors and investigators; ClinicalTrials.gov does not verify their scientific accuracy. Data can be out of date; ClinicalTrials.gov updates daily, so re-run or schedule the Actor to keep data current.
- Modifications to the data: fields are selected, renamed and flattened, location lists are summarized (first 10 sites, plus counts), and contact details are removed. Nothing else is changed.
- When you republish this data, the ClinicalTrials.gov terms ask you to credit ClinicalTrials.gov, keep it current, show the date it was processed (`dataTimestamp`) and describe any modifications.
- Some data may be subject to third-party copyright, and ClinicalTrials.gov data carries an international copyright outside the United States; see the terms.

### Support

Questions or problems: digitalpromohub.support@gmail.com

# Actor input Schema

## `condition` (type: `string`):

Condition search, e.g. "type 2 diabetes" or "breast cancer" (ClinicalTrials.gov condition search, synonyms included).

## `intervention` (type: `string`):

Drug, device or other intervention name, e.g. "pembrolizumab".

## `sponsor` (type: `string`):

Lead sponsor or collaborator name, e.g. "Pfizer" or "National Cancer Institute".

## `location` (type: `string`):

Facility, city, state or country of a study site, e.g. "Denver" or "Germany".

## `keywords` (type: `string`):

Free-text search across the study record (titles, keywords, NCT ids, etc.).

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

Only studies with one of these overall (recruitment) statuses. Empty = any status.

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

Only studies in one of these phases. Empty = any phase.

## `startDateFrom` (type: `string`):

Study start date on or after this date (YYYY-MM-DD).

## `startDateTo` (type: `string`):

Study start date on or before this date (YYYY-MM-DD).

## `firstPostedFrom` (type: `string`):

Study first posted on ClinicalTrials.gov on or after this date (YYYY-MM-DD).

## `firstPostedTo` (type: `string`):

Study first posted on or before this date (YYYY-MM-DD).

## `lastUpdatedFrom` (type: `string`):

Last update posted on or after this date (YYYY-MM-DD).

## `lastUpdatedTo` (type: `string`):

Last update posted on or before this date (YYYY-MM-DD).

## `onlyWithResults` (type: `boolean`):

Only return studies that have results posted on ClinicalTrials.gov.

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

Maximum study rows per run (each row is one charged event). Default 25, max 5000.

## `outputFormat` (type: `string`):

full = all fields; compact = key fields incl. updateType, changeReasons and changeHash.

## `onlyNewSinceLastRun` (type: `boolean`):

For schedules: return only studies not delivered before for these filters, plus delivered studies whose status, recruiting sites, results, phase, enrollment or completion dates changed.

## `lookbackDays` (type: `integer`):

Monitor mode: never look further back than this many days of posted updates (protects paused schedules from huge catch-up runs).

## Actor input object example

```json
{
  "condition": "glioblastoma",
  "onlyWithResults": false,
  "maxItems": 25,
  "outputFormat": "full",
  "onlyNewSinceLastRun": false,
  "lookbackDays": 30
}
```

# Actor output Schema

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

Default dataset. full rows: nctId, briefTitle, officialTitle, acronym, overallStatus, whyStopped, hasResults, resultsFirstPostDate, studyType, phases, enrollmentCount, enrollmentType, conditions, interventions \[{type, name}], leadSponsor, leadSponsorClass, collaborators, startDate, primaryCompletionDate, completionDate, firstPostedDate, lastUpdatePostDate, statusVerifiedDate, locationCount, recruitingLocationCount, countries, locations (first 10: facility, city, state, country, status), url, updateType (monitor mode: new | changed; otherwise null), changeReasons (statusChanged | resultsPosted | recruitingSitesChanged | otherTrackedField), previousStatus, changeHash, dataTimestamp, source. compact rows: nctId, updateType, changeReasons, previousStatus, changeHash, briefTitle, overallStatus, hasResults, phases, leadSponsor, conditions, recruitingLocationCount, lastUpdatePostDate, dataTimestamp, url.

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

OUTPUT record fields: ok, count, chargeEvent, chargedCount, chargeLimitReached (only when the cost limit cut the run), outputFormat, requestUrl, pagesFetched, returnedByApi, totalMatching, apiVersion, dataTimestamp, truncated, olderMatchesSkipped (monitor baseline only), incomplete, truncationNote, message, warnings, onlyNewSinceLastRun; monitor mode adds watermarkStore, watermarkKey, baselineRun, cursorBefore, cursorAfter, queriedUpdatedFrom, lookbackDays, newCount, changedCount, statusChangedCount, resultsPostedCount (all counted from pushed rows), skippedUnchanged; apiRequests {total, retries, throttled, minIntervalMs, perRunCap, userAgent}; disclaimer. On invalid input: ok false, error.

# 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 = {
    "condition": "glioblastoma"
};

// Run the Actor and wait for it to finish
const run = await client.actor("brightish_ascent/clinicaltrials-study-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 = { "condition": "glioblastoma" }

# Run the Actor and wait for it to finish
run = client.actor("brightish_ascent/clinicaltrials-study-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 '{
  "condition": "glioblastoma"
}' |
apify call brightish_ascent/clinicaltrials-study-monitor --silent --output-dataset

```

## MCP server setup

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