# Methodology: How many physical therapists are there in the US? (2026 data)

Every figure on the page is an aggregate. No location-level row, address or phone number is published. Each block below gives the source, the exact query, the row counts and the minimum group size applied.

### Methodology: Active individual NPIs: physical therapists and physical therapy assistants

- **Asset:** NPPES September 2026 file, one de-identified row per NPI (entity type, practice state, enumeration year, update age, primary taxonomy) (sqlite, first-party data); owner Provyx.
- **Collection method:** CMS NPPES monthly full dissemination file (September 2026 release, V2; NPIs issued from 23 May 2005 to 12 September 2026), one de-identified row per NPI. Primary taxonomy = the taxonomy slot flagged primary, else slot 1, labelled with NUCC taxonomy 26.1; update age = time from the last-update date to 1 October 2026, in bands under 1 year, 1 to 3, 3 to 5, 5 to 10 and 10 years or more; never updated = the last-update date equals the enumeration date; a practice location outside the 50 states and DC is counted as 'non-US or blank'. Counts are Provyx aggregations of the public file; taxonomy codes are self-reported by providers.
- **As of:** 2026-09-13; cadence monthly; contribution type first-party data.
- **Rows:** 9798758 input; 350779 after filters and de-duplication.
- **Threshold:** a group is published only when it covers at least 10 source rows; 2 of 2 groups meet it.
- **Query engine:** SQLite, read-only

```sql
WITH filtered AS (
  SELECT "primary_classification"
  FROM "npi_facts"
  WHERE "entity" = ?
    AND "primary_classification" IN (?, ?)
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "primary_classification", COUNT(*) AS "providers", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "primary_classification"
HAVING COUNT(*) >= ?
```
Parameters: `["individual", "Physical Therapist", "Physical Therapy Assistant", 10]`

### Methodology: Physical therapists by primary taxonomy code

- **Asset:** NPPES September 2026 file, one de-identified row per NPI (entity type, practice state, enumeration year, update age, primary taxonomy) (sqlite, first-party data); owner Provyx.
- **Collection method:** CMS NPPES monthly full dissemination file (September 2026 release, V2; NPIs issued from 23 May 2005 to 12 September 2026), one de-identified row per NPI. Primary taxonomy = the taxonomy slot flagged primary, else slot 1, labelled with NUCC taxonomy 26.1; update age = time from the last-update date to 1 October 2026, in bands under 1 year, 1 to 3, 3 to 5, 5 to 10 and 10 years or more; never updated = the last-update date equals the enumeration date; a practice location outside the 50 states and DC is counted as 'non-US or blank'. Counts are Provyx aggregations of the public file; taxonomy codes are self-reported by providers.
- **As of:** 2026-09-13; cadence monthly; contribution type first-party data.
- **Rows:** 9798758 input; 289264 after filters and de-duplication.
- **Threshold:** a group is published only when it covers at least 10 source rows; 11 of 11 groups meet it.
- **Query engine:** SQLite, read-only

```sql
WITH filtered AS (
  SELECT "primary_code"
  FROM "npi_facts"
  WHERE "entity" = ?
    AND "primary_classification" = ?
),
rows AS (
  SELECT *,
    CASE "primary_code" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "code_label"
  FROM filtered
)
SELECT "primary_code", "code_label", COUNT(*) AS "providers", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "primary_code", "code_label"
HAVING COUNT(*) >= ?
```
Parameters: `["individual", "Physical Therapist", "225100000X", "Physical Therapist, general", "2251X0800X", "Orthopedic", "2251P0200X", "Pediatrics", "2251G0304X", "Geriatrics", "2251N0400X", "Neurology", "2251S0007X", "Sports", "2251H1200X", "Hand", "2251E1300X", "Electrophysiology, Clinical", "2251C2600X", "Cardiopulmonary", "2251E1200X", "Ergonomics", "2251H1300X", "Human Factors", "other physical therapy code", 10]`

### Methodology: Physical therapists by practice state (top 15)

- **Asset:** NPPES September 2026 file, one de-identified row per NPI (entity type, practice state, enumeration year, update age, primary taxonomy) (sqlite, first-party data); owner Provyx.
- **Collection method:** CMS NPPES monthly full dissemination file (September 2026 release, V2; NPIs issued from 23 May 2005 to 12 September 2026), one de-identified row per NPI. Primary taxonomy = the taxonomy slot flagged primary, else slot 1, labelled with NUCC taxonomy 26.1; update age = time from the last-update date to 1 October 2026, in bands under 1 year, 1 to 3, 3 to 5, 5 to 10 and 10 years or more; never updated = the last-update date equals the enumeration date; a practice location outside the 50 states and DC is counted as 'non-US or blank'. Counts are Provyx aggregations of the public file; taxonomy codes are self-reported by providers.
- **As of:** 2026-09-13; cadence monthly; contribution type first-party data.
- **Rows:** 9798758 input; 289264 after filters and de-duplication.
- **Threshold:** a group is published only when it covers at least 10 source rows; 59 of 61 groups meet it (2 below the threshold); the largest 15 are listed.
- **Query engine:** SQLite, read-only

```sql
WITH filtered AS (
  SELECT "practice_state"
  FROM "npi_facts"
  WHERE "entity" = ?
    AND "primary_classification" = ?
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "practice_state", COUNT(*) AS "providers", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "practice_state"
HAVING COUNT(*) >= ?
```
Parameters: `["individual", "Physical Therapist", 10]`

### Methodology: Physical therapist NPIs by enumeration year, 2005 to 2026

- **Asset:** NPPES September 2026 file, one de-identified row per NPI (entity type, practice state, enumeration year, update age, primary taxonomy) (sqlite, first-party data); owner Provyx.
- **Collection method:** CMS NPPES monthly full dissemination file (September 2026 release, V2; NPIs issued from 23 May 2005 to 12 September 2026), one de-identified row per NPI. Primary taxonomy = the taxonomy slot flagged primary, else slot 1, labelled with NUCC taxonomy 26.1; update age = time from the last-update date to 1 October 2026, in bands under 1 year, 1 to 3, 3 to 5, 5 to 10 and 10 years or more; never updated = the last-update date equals the enumeration date; a practice location outside the 50 states and DC is counted as 'non-US or blank'. Counts are Provyx aggregations of the public file; taxonomy codes are self-reported by providers.
- **As of:** 2026-09-13; cadence monthly; contribution type first-party data.
- **Rows:** 9798758 input; 289264 after filters and de-duplication.
- **Threshold:** a group is published only when it covers at least 10 source rows; 22 of 22 groups meet it.
- **Query engine:** SQLite, read-only

```sql
WITH filtered AS (
  SELECT "enumeration_year"
  FROM "npi_facts"
  WHERE "entity" = ?
    AND "primary_classification" = ?
),
rows AS (
  SELECT *,
    CASE "enumeration_year" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "era",
    CASE "enumeration_year" WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "year_note"
  FROM filtered
)
SELECT "enumeration_year", "era", "year_note", COUNT(*) AS "enumerated", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "enumeration_year", "era", "year_note"
HAVING COUNT(*) >= ?
```
Parameters: `["individual", "Physical Therapist", "2005", "first enumerated 2005 to 2015", "2006", "first enumerated 2005 to 2015", "2007", "first enumerated 2005 to 2015", "2008", "first enumerated 2005 to 2015", "2009", "first enumerated 2005 to 2015", "2010", "first enumerated 2005 to 2015", "2011", "first enumerated 2005 to 2015", "2012", "first enumerated 2005 to 2015", "2013", "first enumerated 2005 to 2015", "2014", "first enumerated 2005 to 2015", "2015", "first enumerated 2005 to 2015", "first enumerated 2016 to 2026", "2005", " (from 23 May)", "2026", " (records to 13 September)", "", 10]`

### Methodology: Time since the last update of active physical therapist NPI records

- **Asset:** NPPES September 2026 file, one de-identified row per NPI (entity type, practice state, enumeration year, update age, primary taxonomy) (sqlite, first-party data); owner Provyx.
- **Collection method:** CMS NPPES monthly full dissemination file (September 2026 release, V2; NPIs issued from 23 May 2005 to 12 September 2026), one de-identified row per NPI. Primary taxonomy = the taxonomy slot flagged primary, else slot 1, labelled with NUCC taxonomy 26.1; update age = time from the last-update date to 1 October 2026, in bands under 1 year, 1 to 3, 3 to 5, 5 to 10 and 10 years or more; never updated = the last-update date equals the enumeration date; a practice location outside the 50 states and DC is counted as 'non-US or blank'. Counts are Provyx aggregations of the public file; taxonomy codes are self-reported by providers.
- **As of:** 2026-09-13; cadence monthly; contribution type first-party data.
- **Rows:** 9798758 input; 289264 after filters and de-duplication.
- **Threshold:** a group is published only when it covers at least 10 source rows; 5 of 5 groups meet it.
- **Query engine:** SQLite, read-only

```sql
WITH filtered AS (
  SELECT "update_age"
  FROM "npi_facts"
  WHERE "entity" = ?
    AND "primary_classification" = ?
),
rows AS (
  SELECT *,
    CASE "update_age" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "age_label",
    CASE "update_age" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "age_entity",
    CASE "update_age" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "age_order",
    CASE "update_age" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "age_group"
  FROM filtered
)
SELECT "update_age", "age_label", "age_entity", "age_order", "age_group", COUNT(*) AS "records", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "update_age", "age_label", "age_entity", "age_order", "age_group"
HAVING COUNT(*) >= ?
```
Parameters: `["individual", "Physical Therapist", "<1 yr", "under 1 year", "1-3 yr", "1 to 3 years", "3-5 yr", "3 to 5 years", "5-10 yr", "5 to 10 years", "10+ yr", "10 years or more", "an unrecorded time", "<1 yr", "Under 1 year", "1-3 yr", "1 to 3 years", "3-5 yr", "3 to 5 years", "5-10 yr", "5 to 10 years", "10+ yr", "10 years or more", "Not recorded", "<1 yr", "1", "1-3 yr", "2", "3-5 yr", "3", "5-10 yr", "4", "10+ yr", "5", "6", "<1 yr", "last updated within 5 years of 1 October 2026", "1-3 yr", "last updated within 5 years of 1 October 2026", "3-5 yr", "last updated within 5 years of 1 October 2026", "5-10 yr", "last updated 5 or more years before 1 October 2026", "10+ yr", "last updated 5 or more years before 1 October 2026", "with no recorded update date", 10]`

