# Nursing Home Deficiency Citations (CMS) Scraper (`jserle/nursing-home-deficiency-citations`) Actor

Nursing home deficiency citations from CMS: every health inspection violation (F-tag) for every US nursing home, about 418,000 records, with scope/severity decoded and correction status. Filter by state, CCN, facility, survey date, severity, tag or cycle. $0.003/record.

- **URL**: https://apify.com/jserle/nursing-home-deficiency-citations.md
- **Developed by:** [JS Tech Solutions](https://apify.com/jserle) (community)
- **Categories:** Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 deficiency citation 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/actors/running/actors-in-store.md#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

## Nursing Home Deficiency Citations (CMS) Scraper

Pulls every nursing home health deficiency citation CMS publishes, about **418,000 citations** across the last three inspection cycles at every certified nursing home in the US, into clean JSON records. One item per citation: facility, survey date, F-tag with CMS's plain-English definition, scope and severity already decoded, correction status, and a link to the facility's Care Compare page.

CMS puts this data behind a browser table and a monthly CSV. This Actor filters it at the source by state, CCN, facility name, survey date, scope/severity, tag and inspection cycle, so a nursing home inspection history for one facility or every immediate-jeopardy citation in one state is a single cheap run.

### Who uses this data

- **Elder-law and nursing home abuse attorneys** screening a defendant facility or building its citation history. Filter `scopeSeverityCodes` to `J`, `K`, `L` and you have every immediate-jeopardy finding in your state, newest survey first, each with CMS's definition of the tag cited.
- **Long-term care liability underwriters and reinsurers** pricing a facility or a chain. Pull a CCN or a provider-name pattern and you get the full three-cycle citation record, including scope, severity and whether the deficiency was corrected.
- **Nursing home brokers, lenders and REIT analysts** running diligence on a facility before a sale or refinance.
- **Senior placement services and care advisors** vetting homes for a family. `providerUrl` on every record links to the facility's Care Compare page.
- **Researchers, journalists and state agencies** studying enforcement patterns, tag frequency, or how quickly deficiencies are corrected.

### What you get

One dataset item per citation, most recent survey date first. A real record:

```json
{
  "source": "https://data.cms.gov/provider-data/dataset/r5ix-sfxw",
  "attribution": "Centers for Medicare & Medicaid Services (CMS)",
  "citationId": "505154|2026-06-22|F-0656|D|1|S|",
  "ccn": "505154",
  "providerName": "TACOMA NURSING AND REHABILITATION CENTER",
  "providerAddress": "2102 SOUTH 96TH STREET",
  "city": "TACOMA",
  "state": "WA",
  "zipCode": "98444",
  "providerLocation": "2102 SOUTH 96TH STREET,TACOMA,WA,98444",
  "providerUrl": "https://www.medicare.gov/care-compare/details/nursing-home/505154/?state=WA",
  "surveyDate": "2026-06-22",
  "surveyType": "Health",
  "inspectionCycle": 1,
  "deficiencyTag": "F-0656",
  "deficiencyPrefix": "F",
  "deficiencyTagNumber": "0656",
  "deficiencyCategory": "Resident Assessment and Care Planning Deficiencies",
  "deficiencyDescription": "Develop and implement a complete care plan that meets all the resident's needs, with timetables and actions that can be measured.",
  "scopeSeverityCode": "D",
  "severity": "No actual harm with potential for more than minimal harm that is not immediate jeopardy",
  "scope": "Isolated",
  "isImmediateJeopardy": false,
  "deficiencyCorrected": "Deficient, Provider has no plan of correction",
  "correctionDate": null,
  "isStandardSurvey": true,
  "isComplaintSurvey": false,
  "isInfectionControlSurvey": false,
  "isUnderIdr": false,
  "isUnderIidr": false,
  "processingDate": "2026-07-01",
  "fetchedAt": "2026-08-23T11:40:03.834Z"
}
```

`severity` and `scope` are the decoded meaning of `scopeSeverityCode`, taken from CMS's own scope/severity grid (Table 1 of the [Five-Star Technical Users' Guide](https://www.cms.gov/medicare/provider-enrollment-and-certification/certificationandcomplianc/downloads/usersguide.pdf)): severity runs from "No actual harm with potential for minimal harm" up to "Immediate jeopardy to resident health or safety", and scope is Isolated, Pattern or Widespread. A code outside that grid is passed through with `severity` and `scope` left `null` rather than guessed.

**What `deficiencyDescription` is, and is not.** It is CMS's plain-English definition of the F-tag, the same wording for every citation of that tag. It is **not** the surveyor's facility-specific statement of deficiencies (the CMS-2567 narrative), which CMS does not publish in this dataset. Verified: across 126 distinct tags in a 1,500-row sample, no tag carried more than one distinct description. Use it to know what was cited; get the 2567 from the state survey agency.

Dates are ISO 8601 calendar dates exactly as CMS publishes them; a value that is not a real date becomes `null` and is counted in the run summary, never repaired into something plausible. Missing values are `null`, never an empty string. `Y`/`N` columns become real booleans. Records are deduplicated on `citationId`, a composite of facility, survey date, tag, scope/severity, cycle and survey kind, because CMS publishes no row id of its own.

A run summary is written to the `OUTPUT` key: the filters actually sent to CMS, how many citations matched, how many HTTP requests it took, and whether a charge limit stopped the run.

### Input

Everything is optional. Run it with no input and you get the 100 most recently surveyed citations nationwide.

Every filter below is applied by the CMS API itself, not after download, so a narrow search is also a fast and cheap one.

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `states` | string\[] | - | Two-letter postal codes, exact. `["NY","NJ"]`. |
| `ccns` | string\[] | - | CMS Certification Numbers, exact. Keep the leading zero: `["015009"]`. |
| `providerNameContains` | string | - | Case-insensitive substring on the facility name, e.g. `MANOR`. |
| `surveyDateFrom` | ISO date | - | Surveys on or after this date. |
| `surveyDateTo` | ISO date | - | Surveys on or before this date. |
| `scopeSeverityCodes` | string\[] | - | Letters `A` to `L`, exact. `["J","K","L"]` is immediate jeopardy. |
| `tagPrefix` | string | - | Single letter. Every citation here is an `F` tag; see Limitations. |
| `tagNumbers` | string\[] | - | Four-digit tag numbers without the prefix, e.g. `["0689"]`. |
| `inspectionCycles` | string\[] | - | `1`, `2` or `3`, where 1 is the most recent cycle. |
| `surveyKind` | enum | `any` | `any`, `standard`, `complaint` or `infectionControl`. |
| `maxResults` | integer | 100 | 1 to 50000. 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. |

#### Example inputs

**Immediate jeopardy citations in one state** (plaintiff screening, underwriting):

```json
{
  "states": ["NY"],
  "scopeSeverityCodes": ["J", "K", "L"],
  "maxResults": 500
}
```

**Full citation history for one facility** (case file, diligence on a sale):

```json
{
  "ccns": ["505154"],
  "maxResults": 1000
}
```

**Recent abuse and neglect citations nationwide** (F-0600 is the free-from-abuse tag; F-0689 is accidents and supervision):

```json
{
  "tagNumbers": ["0600", "0689"],
  "surveyDateFrom": "2026-01-01",
  "surveyKind": "complaint",
  "maxResults": 2000
}
```

### Pricing

**$0.003 per record; you pay only for records delivered.** One charge per dataset item, nothing else. Set `maxResults` and you have set your bill: 1,000 records is $3.00. Filters are applied at the source, so a narrow search costs less than a broad one, and a filter that matches nothing costs nothing.

### Data source, refresh and licence

Data comes from the **Centers for Medicare & Medicaid Services (CMS)** Provider Data Catalog, dataset "Health Deficiencies":

- Landing page: <https://data.cms.gov/provider-data/dataset/r5ix-sfxw>
- Read through the datastore query API: `https://data.cms.gov/provider-data/api/1/datastore/query/154d0bc8-8214-5dd3-a552-f3aa2e034177`
- Field definitions: [Nursing Home Data Dictionary](https://data.cms.gov/provider-data/sites/default/files/data_dictionaries/nursing_home/NH_Data_Dictionary.pdf), Table 7

**Refresh:** CMS refreshes this dataset monthly. At the time of writing the published file was `NH_HealthCitations_Jul2026.csv`, last modified 2026-07-01, with CMS's catalog giving 2026-08-26 as the next expected update. Every record carries CMS's own `processingDate` so you can see which monthly cut you received. A monthly schedule tracks the source; running it more often will return the same data.

**Licence:** This is CMS provider data, public domain as a US government work. CMS's catalog at `https://data.cms.gov/data.json` states the licence for its datasets as <https://www.usa.gov/government-works>; the Provider Data Catalog sub-catalog (`https://data.cms.gov/provider-data/data.json`) publishes no per-dataset licence field, so that parent-catalog licence is what this listing relies on.

**Attribution:** Centers for Medicare & Medicaid Services (CMS), carried on every record in the `attribution` field. This Actor is **not affiliated with or endorsed by the Centers for Medicare & Medicaid Services**. No login, API key or account is involved in reading this data.

`https://data.cms.gov/robots.txt` declares `crawl-delay: 10` and its `User-agent: *` rules do not disallow `/provider-data/api/`. The Actor makes strictly sequential requests with a 10 second gap between them, sends a descriptive User-Agent, and caches nothing between runs. Pages are requested at the API's own maximum of 1,500 rows, so a 100-record run is a single request and even a 50,000-record run is 34.

### Limitations

- **Health deficiencies only.** Every citation here carries the `F` prefix, confirmed against the live data: a query for any other prefix returns zero rows. Fire safety and life safety citations (`K` and `E` tags) are a separate CMS dataset and are not included.
- **Three inspection cycles, not three calendar years.** CMS's catalog blurb says "the last three years", but the data dictionary says "the last three cycles", and the data agrees with the dictionary: survey dates observed on 2026-08-23 ran from 2017-03-23 to 2026-06-22. A facility surveyed infrequently can carry an old citation.
- **Not every citation is used for the star rating.** CMS notes that this dataset includes citations excluded from the health inspection rating, such as those under Informal Dispute Resolution (`isUnderIdr` / `isUnderIidr`) and cycle 3 standard surveys. Two tags, F731 and F884, are not reported on Care Compare; F884 does not appear in this dataset at all.
- **A citation is an allegation of noncompliance as recorded by a state surveyor**, not a finding of liability. `deficiencyCorrected` and `correctionDate` tell you the compliance status CMS recorded, and `correctionDate` is blank on roughly 2,400 rows.
- **No full statement of deficiencies.** As described above, `deficiencyDescription` is CMS's per-tag definition, not the surveyor's CMS-2567 narrative for a specific survey.
- **Monthly, not live.** A survey conducted after the last monthly cut will not appear until the next one.

### FAQ

#### How do I look up nursing home inspection results and violations by state?

Set `states` to one or more two-letter codes. The filter runs on the CMS API itself, so a single state is one or two requests. Add `surveyDateFrom` to keep only recent surveys, or `scopeSeverityCodes` to keep only the serious ones.

#### What do nursing home scope and severity codes mean?

CMS grades every deficiency with a letter from A to L. Severity rises down the grid (A to C no actual harm with potential for minimal harm; D to F potential for more than minimal harm; G to I actual harm; J to L immediate jeopardy) and within each band the scope is Isolated, Pattern or Widespread. Every record carries the letter plus the decoded `severity` and `scope` text and an `isImmediateJeopardy` boolean.

#### Is this the CMS-2567 statement of deficiencies?

No. CMS does not publish the surveyor's facility-specific narrative in this dataset. What you get is the tag cited and CMS's standard definition of that tag. Request the 2567 from the state survey agency.

#### Does this include fire safety (life safety code) citations?

No. Every citation in this dataset is an F-tag health deficiency. Life safety citations (K and E tags) are a separate CMS dataset.

#### How far back does nursing home deficiency data go?

Three inspection cycles per facility. On 2026-08-23 the oldest survey date in the file was 2017-03-23 and the newest 2026-06-22. CMS does not publish older citations in this dataset, and this Actor does not archive them.

#### How is this different from Nursing Home Compare star ratings?

Star ratings are a summary score. This is the underlying citation-level record: every deficiency, its tag, its severity and its correction status, including citations CMS excludes from the rating calculation.

### 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 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 Revoked Providers List (CMS Revocations) Scraper](https://apify.com/jserle/medicare-revoked-providers)
- [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

## `states` (type: `array`):

Two-letter postal codes, matched exactly. Example: NY, NJ, CT. Leave blank for all states and territories.

## `ccns` (type: `array`):

Six-character CMS Certification Numbers, matched exactly, for tracking a specific facility or a portfolio of them. Example: 015009. Keep the leading zero.

## `providerNameContains` (type: `string`):

Case-insensitive substring matched against the facility name. Example: MANOR. Useful for tracking a chain across states.

## `surveyDateFrom` (type: `string`):

Keep citations from surveys on or after this date. ISO format, for example 2026-01-01.

## `surveyDateTo` (type: `string`):

Keep citations from surveys on or before this date. ISO format, for example 2026-06-30.

## `scopeSeverityCodes` (type: `array`):

Single letters A to L, matched exactly. In CMS's scope/severity grid, J, K and L are immediate jeopardy to resident health or safety; G, H and I are actual harm that is not immediate jeopardy. Each delivered record also carries the decoded severity and scope.

## `tagPrefix` (type: `string`):

A single letter, matched exactly. Every citation in this dataset is an F-tag (health deficiency); K and E tags are fire safety and live in a separate CMS dataset. Leave blank unless CMS starts publishing another prefix here.

## `tagNumbers` (type: `array`):

Four-digit tag numbers, matched exactly, without the prefix. Example: 0689 (accident hazards and supervision), 0600 (free from abuse and neglect), 0684 (quality of care).

## `inspectionCycles` (type: `array`):

1, 2 or 3, where 1 is the most recent cycle. Standard cycles are counted sequentially into the past and complaint cycles annually into the past.

## `surveyKind` (type: `string`):

Restrict to citations found on one kind of inspection. A citation can be flagged on more than one, and every record carries all three flags regardless of this filter.

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

How many citations to deliver, most recent survey first. You are charged per delivered record, so this is also your cost cap.

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

Attach a `raw` object holding the CMS columns under their original snake\_case names, exactly as the API returned them. Useful for auditing the normalization; roughly doubles item size.

## Actor input object example

```json
{
  "states": [],
  "surveyKind": "any",
  "maxResults": 100,
  "includeRaw": false
}
```

# Actor output Schema

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

One item per health deficiency citation delivered by this run.

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

Filters applied, matching citations reported by CMS, request count, delivered records 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 = {
    "states": [],
    "surveyKind": "any",
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("jserle/nursing-home-deficiency-citations").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 = {
    "states": [],
    "surveyKind": "any",
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("jserle/nursing-home-deficiency-citations").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 '{
  "states": [],
  "surveyKind": "any",
  "maxResults": 100
}' |
apify call jserle/nursing-home-deficiency-citations --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jserle/nursing-home-deficiency-citations"
        }
    }
}

```

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/XD1mM5T5kyzmIFbIX/builds/ldb6oiUNGpDrd9pl8/openapi.json
