# Medicare Revoked Providers List (CMS Revocations) Scraper (`jserle/medicare-revoked-providers`) Actor

Medicare revoked providers list from CMS: every provider and supplier with a revoked Medicare enrollment, with NPI, state, provider type, 42 CFR 424.535 reason codes, revocation date and re-enrollment bar expiration. Filter by state, type, date, reason, active bar or NPI/name. $0.02/record.

- **URL**: https://apify.com/jserle/medicare-revoked-providers.md
- **Developed by:** [Jonathan Serle](https://apify.com/jserle) (community)
- **Categories:** Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 revoked provider records

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

## Medicare Revoked Providers List (CMS Revocations) Scraper

Pulls the CMS Revoked Medicare Providers and Suppliers list into clean, deduplicated JSON records: NPI, name, state, provider type, the 42 CFR 424.535 revocation authorities, the revocation effective date and the re-enrollment bar expiration. Filter by state, provider type, revocation date, reason code, active bar, or name/NPI.

It is the second exclusion-type screen most compliance teams want alongside the OIG LEIE, and it answers a question LEIE does not: *why* the enrollment was revoked, under which authority, and *when* the provider is allowed to come back. **8,136 records on 2026-08-23**: 4,739 organizations, 3,397 individuals, across 53 states and territories and 172 provider types.

### Who uses this data

- **Payer and health-system credentialing teams** re-screening a provider roster. Match on NPI or name, get the revocation authority and the date the bar lifts.
- **Compliance and FWA teams** running a second exclusion screen alongside the OIG LEIE. A CMS revocation is not the same event as an OIG exclusion, and the two lists do not carry the same people.
- **Healthcare recruiters and MSOs** checking a candidate or acquisition target before an offer or a deal.
- **Provider data vendors and RCM platforms** that need the list as records rather than as a quarterly CSV to re-parse.
- **Analysts** studying revocation patterns: which authorities, which provider types, which states, over time.

### What you get

One dataset item per revoked enrollment, most recent revocation first.

```json
{
  "source": "https://data.cms.gov/data-api/v1/dataset/a6496a7d-4e19-479a-a9ad-d4c0a49e07c3/data",
  "attribution": "Centers for Medicare & Medicaid Services (CMS)",
  "enrollmentId": "I20100324000818",
  "npi": "1518295484",
  "entityType": "individual",
  "fullName": "FARBOD FARMAND",
  "organizationName": null,
  "firstName": "FARBOD",
  "middleName": null,
  "lastName": "FARMAND",
  "state": "CA",
  "providerType": "PRACTITIONER - INTERNAL MEDICINE",
  "revocationReason": "424.535(A)(19) Affiliation That Poses An Undue Risk",
  "revocationReasonCodes": ["424.535(A)(19)"],
  "revocationReasons": [
    { "code": "424.535(A)(19)", "description": "Affiliation That Poses An Undue Risk" }
  ],
  "revocationEffectiveDate": "2026-05-27",
  "reenrollmentBarExpirationDate": "2036-05-26",
  "reenrollmentBarActive": true,
  "multipleNpi": false,
  "landingPage": "https://data.cms.gov/provider-characteristics/medicare-provider-supplier-enrollment/revoked-medicare-providers-and-suppliers",
  "fetchedAt": "2026-08-23T11:38:08.544Z"
}
```

Notes on the fields that are easy to get wrong:

- **`enrollmentId` is the key, not `npi`.** One NPI can hold several revoked Medicare enrollments; NPI `1801839063` has five, one each in FL, OH, TX, TN and ME. Records are deduplicated on `enrollmentId`, so all five are delivered. Deduplicating on NPI would silently drop four real findings.
- **`npi` can be `null`.** CMS publishes no NPI for 123 of the 8,136 records. The enrollment is still real.
- **`revocationReasons` is split out of the source's semicolon-joined string** so you can test a code without substring-matching prose. `revocationReasonCodes` is the same list flattened.
- **`reenrollmentBarActive` is computed at fetch time**, as `reenrollmentBarExpirationDate >= the day the data was read`. Because CMS refreshes quarterly, a bar that lapsed since the last refresh is still published: 90 of the 8,136 records were already past their bar date on 2026-08-23. Those records are delivered by default, since they are what CMS publishes. Set `activeBarOnly` to drop them.
- **`entityType` is derived** from whether CMS filled `ORG_NAME` or the person-name columns. `fullName` gives you one column to match on either way.
- Dates are ISO 8601 calendar dates, exactly as CMS publishes them. Missing values are `null`, never `""`.

The run summary under the `OUTPUT` key reports the table size, rows fetched, records matched, records delivered, and whether the charge limit stopped the run.

### Input

Everything is optional. Run it with no input and you get the 100 most recent revocations.

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `state` | string\[] | - | Two-letter codes, matched exactly, e.g. `["NY","TX"]`. |
| `providerType` | string | - | Case-insensitive substring, e.g. `PHARMACY`, `HOME HEALTH`, `DME SUPPLIER`. |
| `revokedFrom` | ISO date | - | Revocation effective date on or after this day, inclusive. |
| `revokedTo` | ISO date | - | Revocation effective date on or before this day, inclusive. |
| `reasonCode` | string\[] | - | 42 CFR 424.535 authorities, as an OR. Full (`424.535(A)(3)`) or shorthand (`A3`). |
| `keyword` | string | - | Case-insensitive substring across name, organization name, NPI and enrollment ID. |
| `activeBarOnly` | boolean | false | Keep only records whose re-enrollment bar has not expired as of the fetch date. |
| `maxResults` | integer | 100 | 1 to 10000. This is your cost cap: you pay per delivered record. |
| `includeRaw` | boolean | false | Attach a `raw` object with the CMS columns under their original names. |

Filters combine as AND. `reasonCode` matches a code **anywhere** in a multi-reason record, not only the first one listed. 4,460 of the 8,136 records carry more than one authority, so a first-reason-only match would miss most felony revocations.

#### Example inputs

**Screen one provider by NPI or name** (credentialing):

```json
{
  "keyword": "1518295484",
  "maxResults": 10
}
```

**Every provider still under an active re-enrollment bar in your states** (roster re-screen):

```json
{
  "state": ["NY", "NJ", "CT"],
  "activeBarOnly": true,
  "maxResults": 2000
}
```

**Felony-based revocations this year** (424.535(a)(3) is the felony conviction authority):

```json
{
  "reasonCode": ["A3"],
  "revokedFrom": "2026-01-01",
  "maxResults": 1000
}
```

### Pricing

**$0.02 per record; you pay only for records delivered.** One charge per dataset item, nothing else. Set `maxResults` and you have set your bill: 100 records is $2.00. Filters are applied before delivery, so a search that matches nothing costs nothing.

### Data source, refresh and licence

Data comes from the **Centers for Medicare & Medicaid Services (CMS)** dataset *Revoked Medicare Providers and Suppliers*, read from its public API:

- Dataset page: [data.cms.gov: Revoked Medicare Providers and Suppliers](https://data.cms.gov/provider-characteristics/medicare-provider-supplier-enrollment/revoked-medicare-providers-and-suppliers)
- API: `https://data.cms.gov/data-api/v1/dataset/a6496a7d-4e19-479a-a9ad-d4c0a49e07c3/data`
- [Data dictionary](https://data.cms.gov/resources/revoked-medicare-providers-and-suppliers-data-dictionary) and [methodology](https://data.cms.gov/resources/revoked-medicare-providers-and-suppliers-methodology)

**Refresh:** CMS publishes the dataset quarterly (`accrualPeriodicity: R/P3M` in its catalogue). The extract available on 2026-08-23 was modified 2026-08-04 and covered the quarter 2026-04-01 to 2026-06-30. A monthly or quarterly schedule tracks it; running more often will usually return the same rows.

**Licence:** CMS lists the dataset's licence in its own catalogue (`https://data.cms.gov/data.json`) as **<https://www.usa.gov/government-works>**.

**Attribution:** Centers for Medicare & Medicaid Services (CMS). This Actor is **not affiliated with or endorsed by CMS**, and it is not a legal or regulatory determination about any provider. Verify a finding against the CMS record before acting on it.

`https://data.cms.gov/robots.txt` sets `crawl-delay: 10` and disallows `/data-api/v1/download-request` and the view tracker; the dataset data path this Actor reads is not disallowed. The Actor honours the ten-second delay between every request, sends a descriptive User-Agent, never opens parallel connections, and caches nothing between runs. A full unfiltered read is two requests and about twelve seconds, because the API caps one response at 6,500 rows.

### Limitations

- **Revocations, not exclusions.** This is CMS enrollment revocation under 42 CFR 424.535. It is a different action from an OIG exclusion on the LEIE, and neither list is a superset of the other. Screen both.
- **This is CMS's currently published revoked-provider table, which can lag bar expiration.** A revoked provider drops off once CMS processes the lapsed bar out, so it is not a historical record of every revocation ever issued; and until that processing happens, expired bars are still listed. Use `activeBarOnly` for the strict view, and treat `reenrollmentBarExpirationDate` as the authoritative field either way.
- **No address, no specialty taxonomy, no OIG cross-reference.** CMS publishes twelve columns and this Actor delivers all of them; there is nothing richer behind the endpoint.
- **Names are as CMS publishes them**, uppercase and unpunctuated, with no middle name on many records. Match loosely.
- **A record is an enrollment, not a person.** Counting rows counts enrollments; count distinct `npi` if you want providers.

### FAQ

#### How do I check if a provider has been revoked from Medicare?

Put the NPI, name or enrollment ID in `keyword`. Every revoked enrollment that matches comes back with the revocation authority, the effective date and the date the re-enrollment bar expires. No match means the provider is not on CMS's currently published list; it does not prove there was never a revocation.

#### What is the difference between a Medicare revocation and an OIG exclusion?

A revocation is CMS terminating a provider's Medicare enrollment under 42 CFR 424.535, with a re-enrollment bar. An OIG exclusion is a separate action under the Social Security Act that appears on the LEIE. Neither list is a superset of the other, so compliance screening uses both.

#### What is a Medicare re-enrollment bar?

The period after a revocation during which the provider may not re-enroll in Medicare. `reenrollmentBarExpirationDate` is the date it ends, and `reenrollmentBarActive` tells you whether it was still running on the day the data was read.

#### What do the 424.535 reason codes mean?

Each code is a paragraph of 42 CFR 424.535(a), the regulation listing the grounds for revocation. `revocationReasons` carries CMS's own short description next to each code, for example `424.535(A)(19) Affiliation That Poses An Undue Risk`.

#### How often is the CMS revoked providers list updated?

Quarterly. The extract read on 2026-08-23 was modified 2026-08-04 and covered April to June 2026.

#### Does the list include addresses?

No. CMS publishes twelve columns and none is an address. Join on `npi` against the NPPES registry if you need one.

### Related datasets

Other datasets by the same author, all pay-per-record with source, refresh cadence and licence stated on each listing:

**Nursing home and long-term care data**

- [Nursing Home Deficiency Citations (CMS) Scraper](https://apify.com/jserle/nursing-home-deficiency-citations)
- [Nursing Home Fines & Civil Money Penalties (CMS) Scraper](https://apify.com/jserle/nursing-home-penalties-fines)
- [Nursing Home Directory & Ownership (CMS Form 671) Scraper](https://apify.com/jserle/ltc-facility-characteristics)
- [Nursing Home Daily Nurse Staffing (CMS PBJ) Scraper](https://apify.com/jserle/cms-nursing-home-staffing-daily)
- [Nursing Home Change of Ownership (CMS SNF CHOW) Scraper](https://apify.com/jserle/snf-change-of-ownership-tracker)
- [New York Nursing Home Bed Availability (NYSDOH) Scraper](https://apify.com/jserle/ny-nursing-home-bed-census)

**Medicare provider enrollment data**

- [Medicare Opt-Out Providers List (CMS Affidavits) Scraper](https://apify.com/jserle/medicare-opt-out-physicians)
- [Medicare Revalidation Due Date List (CMS) Scraper](https://apify.com/jserle/medicare-revalidation-due-leads)

**Public procurement and RFP feeds**

- [E-Rate Form 470 RFP Scraper (USAC School & Library Bids)](https://apify.com/jserle/erate-form-470-rfp-feed)
- [NYC PASSPort Procurement Scraper (RFPs, Bids & Contracts)](https://apify.com/jserle/nyc-passport-procurement)

**Developer and AI test data**

- [Synthetic Invoice OCR Ground Truth Dataset Generator](https://apify.com/jserle/ocr-ground-truth-document-factory)

# Actor input Schema

## `state` (type: `array`):

Two-letter state or territory codes, matched exactly. Leave empty for all 53 states and territories CMS publishes. Example: NY, TX, PR

## `providerType` (type: `string`):

Case-insensitive substring matched against the CMS provider type. Examples: PHARMACY, HOME HEALTH, PRACTITIONER - INTERNAL MEDICINE, DME SUPPLIER

## `revokedFrom` (type: `string`):

ISO date, for example 2024-01-01. Keeps records whose revocation effective date is on or after this day.

## `revokedTo` (type: `string`):

ISO date, for example 2026-06-30. Keeps records whose revocation effective date is on or before this day.

## `reasonCode` (type: `array`):

42 CFR 424.535 authorities to keep, as an OR. A record matches if ANY of its reasons carries one of these codes, including when it is not the first reason listed. Write them in full or in shorthand: 424.535(A)(3) or A3. Common codes: A1 enrollment requirements not met, A2 provider or supplier conduct / OIG exclusion, A3 felonies, A4 false or misleading information, A5 on-site review, A9 failure to report, A12 other program termination, A13 prescribing authority, A19 affiliation posing undue risk.

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

Case-insensitive substring matched against the provider or organization name, the NPI and the CMS enrollment ID. Example: ACME HOME HEALTH, or 1801839063

## `activeBarOnly` (type: `boolean`):

CMS refreshes this table quarterly, so it can still list a provider whose re-enrollment bar expired since the last refresh (90 of 8,136 records on 2026-08-23). Turn this on to keep only records whose bar expiration date is on or after the day the data is read.

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

How many records to deliver, newest revocation first. You are charged per delivered record, so this is also your cost cap. The whole table held 8,136 records on 2026-08-23, so 10000 returns everything that matches.

## `includeRaw` (type: `boolean`):

Attach a `raw` object with the CMS columns under their original names (ENRLMT\_ID, REVOCATION\_RSN, and so on), whitespace-trimmed. Useful for auditing the normalization.

## Actor input object example

```json
{
  "activeBarOnly": false,
  "maxResults": 100,
  "includeRaw": false
}
```

# Actor output Schema

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

One item per revoked enrollment delivered by this run.

## `summary` (type: `string`):

Table size, rows fetched, records matched, records delivered, and whether the charge limit stopped the 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 = {
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("jserle/medicare-revoked-providers").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 = { "maxResults": 100 }

# Run the Actor and wait for it to finish
run = client.actor("jserle/medicare-revoked-providers").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 '{
  "maxResults": 100
}' |
apify call jserle/medicare-revoked-providers --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jserle/medicare-revoked-providers"
        }
    }
}

```

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/bBosFp76D5tOm29dT/builds/hgcKdYzVcHB9gOZt8/openapi.json
