# Nursing Home Change of Ownership (CMS SNF CHOW) Scraper (`jserle/snf-change-of-ownership-tracker`) Actor

Nursing home change of ownership records from CMS: every skilled nursing facility CHOW since 2016 with buyer and seller names, CCN, NPI, PECOS ID, state and effective date in one row. Filter by state, date range, buyer, seller or CCN. 5,227 transfers. $0.05/record.

- **URL**: https://apify.com/jserle/snf-change-of-ownership-tracker.md
- **Developed by:** [JS Tech Solutions](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

$50.00 / 1,000 ownership transfer 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 Change of Ownership (CMS SNF CHOW) Scraper

Pulls every Medicare skilled nursing facility change of ownership (CHOW) since 1 January 2016 into clean JSON records with **both sides of the deal in one row**: the buyer's and the seller's legal business name, doing-business-as name, CMS Certification Number, NPI, PECOS Associate ID, enrollment state and provider type, plus the CHOW type and the effective date. Filter by state, effective-date range, buyer or seller name, or CCN.

CMS publishes this as a quarterly file behind a JSON API with upper-case, space-and-hyphen column names. 5,227 nursing home ownership transfers were published on 2026-08-23. A CHOW filing is a buying signal that shows up in a federal file before it shows up anywhere else: the operator has already closed, and the new owner is about to re-paper insurance, staffing, IT, food service, therapy contracts and debt.

### Who uses this data

- **SNF M\&A brokers and buy-side teams** watching who is acquiring in a state, at what pace, and who the repeat consolidators are (`buyerPecosAssociateId` groups a buyer's deals; the busiest buyer in the live file has 89).
- **Nursing home lenders, REITs and underwriters** who need the ownership history behind a CCN before they price a facility.
- **LTC vendors and competitor BD teams** working new-owner transition windows, where incumbent contracts are actually up for review.
- **Elder-law firms** establishing who owned a facility on a given date.
- **Researchers, journalists and state regulators** studying consolidation, private-equity roll-ups, and the shift of county-run homes into private hands.

### What you get

One dataset item per ownership transfer. This is a real record from the live file, trimmed of nothing:

```json
{
  "source": "https://data.cms.gov/data-api/v1/dataset/f557a6ed-95b3-4a22-8433-4175db2dec1c/data",
  "attribution": "Centers for Medicare & Medicaid Services (CMS)",
  "id": "O20260323002425|O20111206000434|2026-02-01",
  "effectiveDate": "2026-02-01",
  "chowTypeCode": "CH",
  "chowType": "CHANGE OF OWNERSHIP",
  "buyerOrganizationName": "GALENA HEALTHCARE LLC",
  "buyerDoingBusinessAsName": "TIMBER RIDGE HEALTH AND REHABILITATION",
  "buyerEnrollmentId": "O20260323002425",
  "buyerState": "WI",
  "buyerCcn": "525611",
  "buyerNpi": "1861365041",
  "buyerHasMultipleNpis": false,
  "buyerPecosAssociateId": "0648754119",
  "buyerProviderTypeCode": "00-18",
  "buyerProviderType": "PART A PROVIDER - SKILLED NURSING FACILITY",
  "buyerNpiLookupUrl": "https://npiregistry.cms.hhs.gov/provider-view/1861365041",
  "sellerOrganizationName": "COUNTY OF PORTAGE",
  "sellerDoingBusinessAsName": "PORTAGE COUNTY HEALTH CARE CENTER",
  "sellerEnrollmentId": "O20111206000434",
  "sellerState": "WI",
  "sellerCcn": "525611",
  "sellerNpi": "1003819491",
  "sellerHasMultipleNpis": false,
  "sellerPecosAssociateId": "7416843388",
  "sellerProviderTypeCode": "00-18",
  "sellerProviderType": "PART A PROVIDER - SKILLED NURSING FACILITY",
  "sellerNpiLookupUrl": "https://npiregistry.cms.hhs.gov/provider-view/1003819491",
  "fetchedAt": "2026-08-23T11:38:11.449Z"
}
```

`id` is the natural key of a transfer, `buyerEnrollmentId|sellerEnrollmentId|effectiveDate`, which was verified unique across all 5,227 live rows. `chowTypeCode` is `CH` (change of ownership), `AM` (acquisition/merger) or `CO` (consolidation) per the CMS reference table. `effectiveDate` is an ISO 8601 calendar date; the source publishes no time of day, so none is invented. Blank source cells arrive as `null`, never as empty strings, and `buyerHasMultipleNpis` / `sellerHasMultipleNpis` are `true`/`false`/`null` rather than `"Y"`/`"N"`. The two `*NpiLookupUrl` fields are constructed from the NPI and point at the NPPES registry; they are `null` when the source has no NPI. A run summary with row counts, request count and the delivered total is written to the `OUTPUT` key.

### Input

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

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `state` | string | - | Two-letter code, e.g. `TX`. Matches when **either** side is enrolled there. |
| `effectiveDateFrom` | ISO date | - | Effective date on or after this day. Data starts at `2016-01-01`. |
| `effectiveDateTo` | ISO date | - | Effective date on or before this day. |
| `buyerKeyword` | string | - | Case-insensitive substring over the buyer's legal name and DBA name. |
| `sellerKeyword` | string | - | Case-insensitive substring over the seller's legal name and DBA name. |
| `ccn` | string | - | Exact CMS Certification Number, matched on either side. The usual way to follow one facility through its ownership history. |
| `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 source columns under their CMS names. |

Filters combine with AND. Records are ordered newest effective date first, so `maxResults` always gives you the most recent transfers.

#### Example inputs

**Recent nursing home sales in one state** (broker deal flow, vendor transition prospecting):

```json
{
  "state": "TX",
  "effectiveDateFrom": "2025-01-01",
  "maxResults": 200
}
```

**Ownership history of one facility** (lender or underwriter diligence):

```json
{
  "ccn": "525611",
  "maxResults": 50
}
```

**Every acquisition by one buyer** (tracking a consolidator):

```json
{
  "buyerKeyword": "Galena",
  "maxResults": 200
}
```

### Pricing

**$0.05 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 $5.00. Filters are applied before delivery, so a narrow search costs less than a broad one, and a search that matches nothing costs nothing.

### Data source, refresh and licence

Data comes from the **Centers for Medicare & Medicaid Services (CMS)**, from the "Skilled Nursing Facility Change of Ownership" dataset on data.cms.gov:

- Dataset landing page: [Skilled Nursing Facility Change of Ownership](https://data.cms.gov/provider-characteristics/hospitals-and-other-facilities/skilled-nursing-facility-change-of-ownership)
- API read by this Actor: `https://data.cms.gov/data-api/v1/dataset/f557a6ed-95b3-4a22-8433-4175db2dec1c/data`
- Data dictionary: [SNF\_CHOW\_Data\_Dictionary.pdf](https://data.cms.gov/sites/default/files/2026-07/SNF_CHOW_Data_Dictionary.pdf). Data guidance: [SNF\_CHOW\_Data\_Guidance.pdf](https://data.cms.gov/sites/default/files/2026-07/SNF_CHOW_Data_Guidance.pdf)

**Refresh:** CMS publishes this dataset **quarterly** (`accrualPeriodicity: R/P3M` in the catalogue). The snapshot read on 2026-08-23 was last modified 2026-07-27 and covered the quarter ending 2026-06-30. Filings also lag their own effective dates: on that snapshot the newest effective date present was 2026-02-01. Schedule the Actor quarterly and you track the publisher's own cadence; running it daily will not produce fresher data.

**Licence:** CMS's own catalogue entry ([data.cms.gov/data.json](https://data.cms.gov/data.json)) records this dataset as `accessLevel: public`, `accessRights: Open`, under the licence <https://www.usa.gov/government-works>.

**Attribution:** Centers for Medicare & Medicaid Services (CMS). This Actor is **not affiliated with or endorsed by the Centers for Medicare & Medicaid Services or the U.S. Department of Health and Human Services**.

`https://data.cms.gov/robots.txt` allows the `/data-api/v1/dataset/...` path this Actor reads and publishes `crawl-delay: 10`. A normal run makes exactly ONE request, so the delay rarely applies; it is honoured before any additional page. The Actor sends a descriptive User-Agent (`jserle-apify-actor/snf-change-of-ownership-tracker`), opens no parallel connections, and caches nothing between runs.

### Limitations

- **No addresses, no purchase price, no facility bed count.** The file carries 23 columns and none of them is a street address or a deal value. The `*NpiLookupUrl` fields let you resolve a party's address through the separate NPPES registry.
- **Organizations only, not the people behind them.** For the individual and organizational owners disclosed on an enrollment, CMS publishes a separate [SNF Change of Ownership - Owner Information](https://data.cms.gov/provider-characteristics/hospitals-and-other-facilities/skilled-nursing-facility-change-of-ownership-owner-information) dataset, which this Actor does not read.
- **One NPI per party.** Where a party holds several NPIs, CMS shows one and sets the multiple-NPI flag; the data dictionary states the rest are published in a separate Additional NPIs file. The flag is delivered so you know when to look further.
- **SNF buyers, mixed sellers.** Every buyer in the live file is enrolled as a skilled nursing facility, but a handful of sellers are not (critical access hospital, FQHC, rural health clinic and others). Both provider types are delivered so you can tell.
- **Skilled nursing facilities only.** Hospital ownership changes are a different CMS dataset and are not included here.
- **Fields are as published.** CMS leaves the doing-business-as name blank on a meaningful minority of rows (432 buyers and 558 sellers of 5,227 on 2026-08-23). Those arrive as `null`.
- **The run fails rather than half-succeeds.** Every run reads the whole dataset and applies your filters locally, so an upstream change can never quietly hand you a short result. If the API stops returning JSON rows, returns an implausibly small unfiltered result, changes its column set in either direction **on any row**, cuts the read short, or normalizes to zero records on an unfiltered run, the run exits non-zero having pushed nothing and charged nothing. A filter that legitimately matches no transfer is a clean, free, empty run instead.

### FAQ

#### How do I find out who owns a nursing home, or who bought it?

Run with the facility's `ccn`. Every transfer CMS has recorded for that CCN since 2016 comes back newest first, with the buyer's and seller's legal names, DBA names, NPIs and PECOS IDs on each row. The buyer on the newest row is the most recent owner CMS has recorded in this file.

#### What is a CHOW in Medicare terms?

A change of ownership of a Medicare-enrolled provider, reported to CMS through PECOS. `chowTypeCode` is `CH` for a change of ownership, `AM` for an acquisition or merger, or `CO` for a consolidation.

#### How do I track nursing home acquisitions by state?

Set `state` and an `effectiveDateFrom`. The state filter matches when either the buyer or the seller is enrolled there, so a cross-state acquirer still shows up.

#### Does the data include the purchase price or the facility address?

No. CMS publishes neither. Use the `*NpiLookupUrl` links to resolve an address through the NPPES registry.

#### How current is the nursing home change of ownership data?

CMS publishes quarterly. The snapshot read on 2026-08-23 was last modified 2026-07-27, and its newest effective date was 2026-02-01, so filings lag their effective dates by months.

#### Does it cover hospitals or home health agencies?

No. This is the skilled nursing facility file only. Hospital ownership changes are a separate CMS dataset.

### 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)
- [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

## `state` (type: `string`):

Two-letter enrollment state code, for example TX. Matches a transfer when EITHER the buyer or the seller is enrolled in that state; the two differ on a small number of cross-border deals.

## `effectiveDateFrom` (type: `string`):

ISO date, for example 2024-01-01. Keeps transfers whose effective date is on or after this day. The dataset starts at 2016-01-01.

## `effectiveDateTo` (type: `string`):

ISO date, for example 2026-12-31. Keeps transfers whose effective date is on or before this day.

## `buyerKeyword` (type: `string`):

Case-insensitive substring matched against the buyer's legal business name and its doing-business-as name. Example: healthcare

## `sellerKeyword` (type: `string`):

Case-insensitive substring matched against the seller's legal business name and its doing-business-as name. Example: county

## `ccn` (type: `string`):

Exact CMS Certification Number (formerly OSCAR number), for example 525611. Matches a transfer when either side carries that CCN, which is the usual way to follow one facility through its ownership history.

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

How many records to deliver, newest effective date first. You are charged per delivered record, so this is also your cost cap.

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

Attach a `raw` object holding the source columns under their CMS names, whitespace-trimmed. Useful for auditing the normalization; roughly doubles item size.

## Actor input object example

```json
{
  "state": "TX",
  "maxResults": 100,
  "includeRaw": false
}
```

# Actor output Schema

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

One item per ownership transfer delivered by this run, newest effective date first.

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

Source URL, request count, row counts, 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 = {
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("jserle/snf-change-of-ownership-tracker").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/snf-change-of-ownership-tracker").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/snf-change-of-ownership-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jserle/snf-change-of-ownership-tracker"
        }
    }
}

```

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/Rb8C1ufAnoBQac9Tl/builds/4gOdEsUE9vfMOgiDY/openapi.json
