RADAR Banner

RTC Fact Sheet: 2025 State of Evictions

Code
library(DBI)
library(RPostgres)
library(flextable)
library(sf)
library(tidyverse)

# Ensure that the Quarto render and RStudio read the same environment vars
readRenviron(".Renviron")

con <- dbConnect(
  RPostgres::Postgres(),
  dbname = Sys.getenv("PG_DBNAME"),
  host     = Sys.getenv("PG_HOST"),
  port     = Sys.getenv("PG_PORT"),
  user     = Sys.getenv("PG_USER"),
  password = Sys.getenv("PG_PASSWORD")
  )

The following analyses were performed in support of Right to Counsel’s annual State of Evictions fact sheet.

Cumulative Eviction Filings

Number of eviction filings from January 1, 2020 - December 31, 2025

Code
SELECT
  COUNT(DISTINCT indexnumberid)::integer
FROM oca_index
WHERE fileddate >= MAKE_DATE(2020,1,1) 
  AND fileddate <= MAKE_DATE(2025,12,31)
  AND classification IN ('Holdover', 'Non-Payment')
  AND (propertytype = 'Residential' OR propertytype IS NULL);

In New York State, there were 849,449 eviction-oriented (holdover and non-payment) filings from January 1, 2020 to December 31, 2025.

Please note that this analysis excludes commercial evictions within New York City. Unfortunately, outside of NYC, excluding commercial from residential eviction filings and executions is not possible given the current data.

Annual eviction filings

Code
SELECT
    EXTRACT(YEAR FROM fileddate) AS filed_year,
    COUNT(DISTINCT indexnumberid)::integer
FROM oca_index
WHERE fileddate >= MAKE_DATE(2020,1,1) 
  AND fileddate <= MAKE_DATE(2025,12,31)
  AND classification IN ('Holdover', 'Non-Payment')
  AND (propertytype = 'Residential' OR propertytype IS NULL)
GROUP BY filed_year;

The number of eviction-related (holdover and non-payment) eviction filings per year is:

Code
eviction_count_annual_table <- eviction_count_annual_df |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  set_header_labels(
    filed_year = "Year",
    count = "Eviction Filings"
  ) |> 
  colformat_num(j=1,
                big.mark = "") |> 
  align(j=1,
        align = "left",
        part = "all")

eviction_count_annual_table

Year

Eviction Filings

2020

100,546

2021

60,491

2022

165,470

2023

187,034

2024

171,311

2025

164,597

Which areas are hardest hit?

By court, January 1, 2020 - December 31, 2025:

Code
SELECT
    court,
    COUNT(DISTINCT indexnumberid)::integer
FROM oca_index
WHERE fileddate >= MAKE_DATE(2020,1,1) 
  AND fileddate <= MAKE_DATE(2025,12,31)
  AND classification IN ('Holdover', 'Non-Payment')
  AND (propertytype = 'Residential' OR propertytype IS NULL)
GROUP BY court
ORDER BY count DESC
LIMIT 10;
Code
eviction_count_courts_table <- eviction_count_courts_df |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  set_header_labels(
    court = "Court",
    count = "Eviction Filings"
  )

eviction_count_courts_table

Court

Eviction Filings

Bronx County Civil Court

213,610

Kings County Civil Court

158,862

New York County Civil Court

100,066

Queens County Civil Court

97,647

Buffalo City Court

37,842

Rochester City Court

27,383

Nassau County District Court - 1st District

19,373

Yonkers City Court

17,666

Suffolk County District Court - 6th District

14,801

Syracuse City Court

14,481

By court, January 1, 2025 - December 31, 2025:

Code
SELECT
    court,
    COUNT(DISTINCT indexnumberid)::integer
FROM oca_index
WHERE fileddate >= MAKE_DATE(2025,1,1) 
  AND fileddate <= MAKE_DATE(2025,12,31)
  AND classification IN ('Holdover', 'Non-Payment')
  AND (propertytype = 'Residential' OR propertytype IS NULL)
GROUP BY court
ORDER BY count DESC
LIMIT 10;
Code
eviction_count_courts_25_table <- eviction_count_courts_25_df |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  set_header_labels(
    court = "Court",
    count = "Eviction Filings"
  )

eviction_count_courts_25_table

Court

Eviction Filings

Bronx County Civil Court

40,462

Kings County Civil Court

31,167

New York County Civil Court

19,480

Queens County Civil Court

18,691

Buffalo City Court

7,597

Rochester City Court

5,566

Nassau County District Court - 1st District

3,432

Yonkers City Court

3,419

Suffolk County District Court - 6th District

2,803

Richmond County Civil Court

2,798

By NYS Assembly District: January 1, 2020 - December 31, 2025

Code
oca_index_5year_geom <- st_read(con, query = "
SELECT DISTINCT(i.indexnumberid),
    ST_Transform(a.geom, 2263) AS geom
FROM oca_index i
JOIN oca_addresses a ON i.indexnumberid = a.indexnumberid
WHERE i.fileddate >= MAKE_DATE(2020,1,1) 
    AND i.fileddate <= MAKE_DATE(2025,12,31)
    AND i.classification IN ('Holdover', 'Non-Payment')
    AND (i.propertytype = 'Residential' OR i.propertytype IS NULL)
    AND a.geom IS NOT NULL")

In the following filing counts by area, note that only 827,239 eviction filings (97.39%) have a location

Code
bb <- read_sf("https://services5.arcgis.com/GfwWNkhOj9bNBqoJ/arcgis/rest/services/NYC_Borough_Boundary/FeatureServer/0/query?where=1=1&outFields=*&outSR=4326&f=pgeojson") |> 
  st_transform(2263) |> 
  st_make_valid() |> 
  st_union()

nysad <- read_sf("https://services6.arcgis.com/EbVsqZ18sv1kVJ3k/ArcGIS/rest/services/NYS_Assembly_Districts/FeatureServer/0/query?where=0%3D0&outFields=*&f=geojson") |> 
  st_transform(2263)

nyss <- read_sf("https://services6.arcgis.com/EbVsqZ18sv1kVJ3k/ArcGIS/rest/services/NYS_Senate_Districts/FeatureServer/0/query?where=0%3D0&outFields=*&f=geojson") |> 
  st_transform(2263)

nysad_downstate <- st_filter(nysad, bb, .predicate = st_intersects)

nysad_upstate <- st_filter(nysad, bb, .predicate = st_disjoint)

nyss_downstate <- st_filter(nyss, bb, .predicate = st_intersects)
  
nyss_upstate <- st_filter(nyss, bb, .predicate = st_disjoint)

Upstate Assembly Districts (Not intersecting with NYC Borough boundaries)

Code
nysad_upstate_5year <- oca_index_5year_geom |> 
  st_join(nysad_upstate |> 
              select(District),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(District) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nysad_upstate_5year_table <- nysad_upstate_5year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all")

nysad_upstate_5year_table

District

Eviction Filings

137

16,191

141

14,663

109

12,172

108

11,169

129

8,523

90

7,688

111

7,469

149

7,308

119

7,269

104

7,097

Downstate Assembly Districts (Intersecting with NYC Borough boundaries)

Code
nysad_downstate_5year <- oca_index_5year_geom |> 
  st_join(nysad_downstate |> 
              select(District),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(District) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nysad_downstate_5year_table <- nysad_downstate_5year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all")

nysad_downstate_5year_table

District

Eviction Filings

86

30,156

77

29,285

78

25,627

84

24,290

79

22,698

70

19,673

72

18,520

71

17,216

43

16,938

85

16,896

By NYS Assembly District: January 1, 2025 - December 31, 2025

Code
oca_index_1year_geom <- st_read(con, query = "
SELECT DISTINCT(i.indexnumberid),
    ST_Transform(a.geom, 2263) AS geom
FROM oca_index i
JOIN oca_addresses a ON i.indexnumberid = a.indexnumberid
WHERE i.fileddate >= MAKE_DATE(2025,1,1) 
    AND i.fileddate <= MAKE_DATE(2025,12,31)
    AND i.classification IN ('Holdover', 'Non-Payment')
    AND (i.propertytype = 'Residential' OR i.propertytype IS NULL)
    AND a.geom IS NOT NULL")

Upstate Assembly Districts (Not intersecting with NYC Borough boundaries)

Code
nysad_upstate_1year <- oca_index_1year_geom |> 
  st_join(nysad_upstate |> 
              select(District),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(District) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nysad_upstate_1year_table <- nysad_upstate_1year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all")

nysad_upstate_1year_table

District

Eviction Filings

137

3,257

141

2,733

109

2,314

108

2,276

129

1,662

119

1,502

111

1,478

149

1,455

90

1,424

104

1,216

Downstate Assembly Districts (Intersecting with NYC Borough boundaries)

Code
nysad_downstate_1year <- oca_index_1year_geom |> 
  st_join(nysad_downstate |> 
              select(District),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(District) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nysad_downstate_1year_table <- nysad_downstate_1year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all")

nysad_downstate_1year_table

District

Eviction Filings

77

5,540

86

5,498

78

4,796

84

4,732

79

4,052

70

3,972

72

3,680

60

3,492

71

3,287

55

3,282

By NYS Senate District, January 1, 2020 - December 31, 2025

Upstate Senate Districts (Not intersecting with NYC Borough boundaries)

Code
nyss_upstate_5year <- oca_index_5year_geom |> 
  st_join(nyss_upstate |> 
              select(DISTRICT),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(DISTRICT) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nyss_upstate_5year_table <- nyss_upstate_5year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all") |> 
  set_header_labels(
    DISTRICT = "District"
  )

nyss_upstate_5year_table

District

Eviction Filings

63

25,129

48

15,389

56

15,288

46

13,440

3

11,848

43

11,252

55

10,726

61

10,032

6

9,358

44

8,900

Downstate Senate Districts (Intersecting with NYC Borough boundaries)

Code
nyss_downstate_5year <- oca_index_5year_geom |> 
  st_join(nyss_downstate |> 
              select(DISTRICT),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(DISTRICT) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nyss_downstate_5year_table <- nyss_downstate_5year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all") |> 
  set_header_labels(
    DISTRICT = "District"
  )

nyss_downstate_5year_table

District

Eviction Filings

32

59,743

33

52,048

31

47,214

29

43,663

30

38,461

20

30,843

19

30,346

36

28,840

34

24,362

21

24,203

By NYS Senate District, January 1, 2025 - December 31, 2025

Upstate Senate Districts (Not intersecting with NYC Borough boundaries)

Code
nyss_upstate_1year <- oca_index_1year_geom |> 
  st_join(nyss_upstate |> 
              select(DISTRICT),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(DISTRICT) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nyss_upstate_1year_table <- nyss_upstate_1year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all") |> 
  set_header_labels(
    DISTRICT = "District"
  )

nyss_upstate_1year_table

District

Eviction Filings

63

4,732

56

3,059

48

2,959

46

2,600

43

2,289

55

2,216

3

2,198

61

2,081

44

1,749

6

1,639

Downstate Senate Districts (Intersecting with NYC Borough boundaries)

Code
nyss_downstate_1year <- oca_index_1year_geom |> 
  st_join(nyss_downstate |> 
              select(DISTRICT),
            left = FALSE) |> 
  st_drop_geometry() |> 
  group_by(DISTRICT) |> 
  summarize(`Eviction Filings` = n()) |> 
  arrange(desc(`Eviction Filings`)) |> 
  head(10)

nyss_downstate_1year_table <- nyss_downstate_1year |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all") |> 
  set_header_labels(
    DISTRICT = "District"
  )

nyss_downstate_1year_table

District

Eviction Filings

32

10,743

33

9,563

31

9,093

29

8,683

30

7,613

19

6,161

36

5,837

20

5,554

34

4,877

25

4,775

Executed Evictions in 2025

Code
SELECT
  DISTINCT i.indexnumberid,
  w.executiondate
FROM oca_index i
JOIN oca_warrants w ON i.indexnumberid = w.indexnumberid
WHERE w.executiondate >= MAKE_DATE(2025,1,1) 
  AND w.executiondate <= MAKE_DATE(2025,12,31)
  AND i.classification IN ('Holdover', 'Non-Payment')
  AND (i.propertytype = 'Residential' OR i.propertytype IS NULL)
  AND w.executiondate IS NOT NULL
Code
executed_evictions_25_geom <- st_read(con, query = "
WITH executed_evictions_25 AS (
    SELECT
      DISTINCT i.indexnumberid,
      w.executiondate
    FROM oca_index i
    JOIN oca_warrants w ON i.indexnumberid = w.indexnumberid
    WHERE w.executiondate >= MAKE_DATE(2025,1,1) 
      AND w.executiondate <= MAKE_DATE(2025,12,31)
      AND i.classification IN ('Holdover', 'Non-Payment')
      AND (i.propertytype = 'Residential' OR i.propertytype IS NULL)
      AND w.executiondate IS NOT NULL
)
SELECT e.*,
    ST_TRANSFORM(a.geom, 2263)
FROM executed_evictions_25 e
JOIN oca_addresses a on e.indexnumberid = a.indexnumberid
WHERE a.geom IS NOT NULL;")

Note: Of the 14,187 evictions executed statewide in 2025, only 13,993 have a location associated with them (98.63%)

Code
nys_counties <- read_sf("https://services6.arcgis.com/EbVsqZ18sv1kVJ3k/ArcGIS/rest/services/NYS_Civil_Boundaries/FeatureServer/2/query?where=0%3D0&outFields=*&f=geojson") |> 
  st_transform(2263)

executed_evictions_25_byCty <- executed_evictions_25_geom |> 
  st_join(nys_counties |> 
            select(NAME)) |> 
  st_drop_geometry() |> 
  group_by(NAME) |> 
  summarize(`Executed Evictions` = n()) |> 
  arrange(desc(`Executed Evictions`)) |> 
  head(10)

executed_evictions_25_byCty_table <- executed_evictions_25_byCty |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  align(j=1,
        align = "left",
        part = "all") |> 
  set_header_labels(
    NAME = "County"
  )

executed_evictions_25_byCty_table

County

Executed Evictions

Bronx

4,636

Kings

3,621

New York

2,063

Queens

1,991

Richmond

516

Schenectady

507

Niagara

126

Orange

117

Montgomery

97

Genesee

78

Evictions During the Winter Months (November 1 - April 15)

Eviction filings

Code
WITH eviction_filings_with_season AS(
    SELECT
        DISTINCT indexnumberid,
        EXTRACT(YEAR FROM fileddate) AS filed_year,
        CASE 
            WHEN EXTRACT(MONTH FROM fileddate) >= 11 THEN TRUE
            WHEN EXTRACT(MONTH FROM fileddate) < 4 THEN TRUE
            WHEN EXTRACT(MONTH FROM fileddate) = 4 
                 AND EXTRACT(DAY FROM fileddate) <= 15 THEN TRUE
            ELSE FALSE
        END AS winter_season
    FROM oca_index
    WHERE fileddate >= MAKE_DATE(2020,1,1) 
      AND fileddate <= MAKE_DATE(2025,12,31)
      AND classification IN ('Holdover', 'Non-Payment')
      AND (propertytype = 'Residential' OR propertytype IS NULL)
)
SELECT
    filed_year,
    COUNT(indexnumberid) AS all_filings,
    SUM(winter_season::int) AS winter_filings,
    100* ROUND(SUM(winter_season::int)::numeric/COUNT(indexnumberid),3) AS winter_filing_pct
FROM eviction_filings_with_season
GROUP BY filed_year
ORDER BY filed_year;
Code
winter_filings_table <- winter_filings |> 
  # Convert from Postgres int64
  mutate(
    all_filings = as.numeric(all_filings),
    winter_filings = as.numeric(winter_filings)
  ) |> 
  flextable() |> 
  set_table_properties(width = 1, layout = "autofit") |> 
  set_header_labels(
    filed_year = "Year",
    all_filings = "Annual Filings",
    winter_filings = "Winter Filings",
    winter_filing_pct = "Winter Filing Percentage (%)"
  ) |> 
  colformat_num(j=1,
                big.mark = "") |> 
  colformat_int(j=2:3,
                big.mark = ",") |> 
  align(j=1,
      align = "left",
      part = "all")

winter_filings_table

Year

Annual Filings

Winter Filings

Winter Filing Percentage (%)

2020

100,546

72,093

71.7

2021

60,491

22,836

37.8

2022

165,470

71,283

43.1

2023

187,034

83,965

44.9

2024

171,311

78,773

46.0

2025

164,597

74,950

45.5

Executed evictions

Code
WITH eviction_exc_with_season AS(
    SELECT
        DISTINCT i.indexnumberid,
        EXTRACT(YEAR FROM w.executiondate) AS executed_year,
        CASE 
            WHEN EXTRACT(MONTH FROM w.executiondate) >= 11 THEN TRUE
            WHEN EXTRACT(MONTH FROM w.executiondate) < 4 THEN TRUE
            WHEN EXTRACT(MONTH FROM w.executiondate) = 4 
                 AND EXTRACT(DAY FROM w.executiondate) <= 15 THEN TRUE
            ELSE FALSE
        END AS winter_season
    FROM oca_index i
    JOIN oca_warrants w on i.indexnumberid=w.indexnumberid
    WHERE w.executiondate >= MAKE_DATE(2020,1,1) 
      AND w.executiondate <= MAKE_DATE(2025,12,31)
      AND i.classification IN ('Holdover', 'Non-Payment')
      AND (i.propertytype = 'Residential' OR i.propertytype IS NULL)
)
SELECT
    executed_year,
    COUNT(indexnumberid) AS all_executions,
    SUM(winter_season::int) AS winter_executions,
    100* ROUND(SUM(winter_season::int)::numeric/COUNT(indexnumberid),3) AS winter_execution_pct
FROM eviction_exc_with_season
GROUP BY executed_year
ORDER BY executed_year; 
Code
winter_executions_table <- winter_executions |> 
  mutate(all_executions = as.numeric(all_executions),
         winter_executions = as.numeric(winter_executions)
        ) |>
  flextable() |>
  set_table_properties(width = 1, layout = "autofit") |> 
  set_header_labels(
    executed_year = "Year",
    all_executions = "Annual Executions",
    winter_executions = "Winter Executions",
    winter_execution_pct = "Winter Execution Percentage (%)"
  ) |> 
  colformat_num(j=1,
                big.mark = "") |> 
  colformat_int(j=2:3,
                big.mark = ",") |> 
  align(j=1,
      align = "left",
      part = "all")
  
winter_executions_table 

Year

Annual Executions

Winter Executions

Winter Execution Percentage (%)

2020

2,147

2,140

99.7

2021

220

81

36.8

2022

4,462

1,727

38.7

2023

11,863

4,686

39.5

2024

13,334

5,696

42.7

2025

14,160

6,028

42.6