---
title: "Immigration Enforcement in the First Nine Months of the Second Trump Administration"
image: /img/2025-03-21-ice-arrests.svg
author:
- name: "Graeme Blair"
url: "https://graemeblair.com"
affiliation: "Professor of Political Science, UCLA"
- name: "David Hausman"
url: "https://www.david-hausman.com"
affiliation: "Assistant Professor, UC Berkeley School of Law"
date: "January 27, 2026" # make sure to change date
format:
html:
code-tools: true
fig-cap-location: top
reference-location: margin
pdf:
knitr:
opts_chunk:
dev: "cairo_pdf"
execute:
out-width: "0.6\\linewidth"
fig-width: 6.5
fig-height: 4
linkcolor: black
urlcolor: black
citecolor: black
colorlinks: true
titlepage: false
filters:
- ../filters/report-cover.lua
fig-cap-location: top
fontsize: 11pt
documentclass: report
geometry: left=1.25in, right=1.25in, top=1.25in, bottom=1.25in
pdf-engine: lualatex
mainfont: Times New Roman
include-in-header:
text: |
\usepackage[normalem]{ulem}
\usepackage{xurl}
\makeatletter
\AtBeginDocument{%
\@ifpackageloaded{hyperref}{%
\let\oldhref\href
\renewcommand{\href}[2]{\oldhref{#1}{\uline{#2}}}%
}{}%
}
\makeatother
\usepackage[dvipsnames]{xcolor}
\definecolor{bgcolor}{HTML}{3C4D61}
\usepackage{setspace}
\setstretch{1.2}
\setlength{\parindent}{2em}
\newfontfamily\headingfont{Playfair Display}
\newfontfamily\titlefont{Playfair Display}
\usepackage{caption}
\DeclareCaptionFont{playfair}{\titlefont}
\captionsetup[figure]{
font={large,bf,playfair},
labelfont={large,bf,playfair}
}
\usepackage{titlesec}
\titleformat{\section}
{\headingfont\Large\bfseries}
{\thesection}{1em}{}
echo: false
warning: false
error: false
cache: true
appendix-cite-as: display
title-block-banner: true
abstract-title: "Executive Summary"
custom-titlepage:
partial: ../partials/report-cover.tex
abstract: |
The number of deportations from within the United States, away from the border, increased by a factor of 4.6 during the first nine months of the second Trump administration (the period for which we have detailed data). That increase reflects the following key trends: \
First, **ICE arrests quadrupled**, including both street arrests and transfers from criminal custody to ICE immigration custody. ICE **street arrests** (i.e. arrests not at jails) went up by over a **factor of eleven**. Street arrests at this order of magnitude are a new phenomenon. For both types of arrests, ICE was much less likely to target people with criminal convictions. These changes led to over a **sevenfold increase in arrests of people without criminal convictions**. \
Second, the quadrupling (4x) of arrests resulted in an **even larger rise (4.6x) in deportations** because of increased detention space and decreased releases. The administration roughly **tripled the number of detention beds** used for people arrested within the United States. That capacity increase was a result both of new funding (for new detention centers and more beds in existing detention centers) and of a decrease in arrests at the border. Once arrested, few were released. Release within 60 days of arrest, already rare in the last six months of the Biden administration (16%), became almost nonexistent (3%). The rate of deportation within two months of initial detention rose by about a quarter, from 55% to 69%; the declining release rate accounted for most of that increase. Perhaps because of the lower release rate, voluntary departures (which are rare compared to removals) increased by 21 times.
---
::: {.content-visible when-format="html"}
[Read report as a PDF](/analysis/immigration-enforcement-first-nine-months-trump.pdf){.btn-action-primary .btn-action .btn .btn-outline-primary .btn-sm role="button"}
:::
```{r}
#| cache: false
library(tidyverse)
label_months <- function(x) {
labs <- format(x, "%B")
is_jan <- !is.na(x) & month(x) == 1
labs[is_jan] <- paste0(labs[is_jan], "\n", format(x[is_jan], "%Y"))
first_ok <- which(!is.na(x))[1]
if (!is.na(first_ok)) {
labs[first_ok] <- paste0(
format(x[first_ok], "%B"),
"\n",
format(x[first_ok], "%Y")
)
}
labs
}
if (knitr::is_html_output()) {
knitr::opts_chunk$set(
dev = "svglite",
dev.args = list(
bg = "transparent",
system_fonts = list(sans = "Arial")
)
)
} else if (knitr::is_latex_output()) {
knitr::opts_chunk$set(
dev.args = list(family = "Arial")
)
}
knitr::opts_chunk$set()
theme_minimal_transparent <- function(sz = 13) {
theme_minimal(base_size = sz) +
theme(
plot.background = element_rect(fill = "transparent", color = NA),
panel.background = element_rect(fill = "transparent", color = NA),
legend.background = element_rect(fill = "transparent", color = NA),
legend.box.background = element_rect(fill = "transparent", color = NA),
legend.position = "bottom",
axis.title.y = element_text(color = "grey30", margin = margin(r = 15)),
axis.title.x = element_text(color = "grey30", margin = margin(t = 15))
)
}
```
```{r}
detention_stays <- arrow::read_feather(
"https://github.com/deportationdata/ice/raw/refs/heads/main/data/detention-stays-latest.feather"
)
detention_stints <- arrow::read_feather(
"https://github.com/deportationdata/ice/raw/refs/heads/main/data/detention-stints-latest.feather"
)
arrests <- arrow::read_feather(
"https://github.com/deportationdata/ice/raw/refs/heads/main/data/arrests-latest.feather"
)
detention_arrest_join <-
detention_stays |>
select(stay_ID, unique_identifier, stay_book_in_date_time) |>
left_join(
arrests |>
filter(!is.na(unique_identifier)) |>
arrange(unique_identifier, apprehension_date_time) |>
mutate(
new_episode = is.na(lag(apprehension_date_time)) |
difftime(
apprehension_date_time,
lag(apprehension_date_time),
units = "hours"
) >
24,
episode_id = cumsum(new_episode),
.by = "unique_identifier"
) |>
# keep the last arrest in each <=24h-connected episode
filter(row_number() == n(), .by = c("unique_identifier", "episode_id")) |>
# if any episodes still have exact timestamp duplicates, keep one
distinct(unique_identifier, apprehension_date_time, .keep_all = TRUE) |>
select(-new_episode, -episode_id) |>
select(
unique_identifier,
apprehension_date_time_arrest = apprehension_date_time,
apprehension_criminality,
apprehension_method,
file_original_arrest = file_original,
row_original_arrest = row_original,
sheet_original_arrest = sheet_original
),
by = "unique_identifier",
relationship = "many-to-many"
) |>
mutate(
time_diff = as.numeric(difftime(
stay_book_in_date_time,
apprehension_date_time_arrest,
units = "hours"
))
) |>
group_by(stay_ID) |>
filter(time_diff <= 24 * 10, time_diff >= 24 * -5) |>
slice_min(order_by = abs(time_diff), n = 1, with_ties = FALSE) |>
ungroup() |>
select(-time_diff, -unique_identifier, -stay_book_in_date_time)
detention_stays <-
detention_stays |>
mutate(
border_arrest = final_program %in%
c(
"Border Patrol",
"Inspections - Air",
"Inspections - Land",
"Inspections - Sea",
"Coast Guard"
)
)
detentions_with_arrests <-
detention_stays |>
left_join(
detention_arrest_join |> mutate(has_arrest = 1),
by = "stay_ID",
relationship = "one-to-one"
) |>
mutate(
has_arrest = if_else(is.na(has_arrest), 0L, has_arrest)
)
```
## Introduction
The story of immigration enforcement in the first year of the second Trump administration is a story of **a drastic increase in interior immigration enforcement**: enforcement that occurs within the United States, usually far from the border. Interior deportations surged to more than four and a half times their pre-inauguration level (see @fig-deportations).[^1]
The steep increase in ICE deportations reflects two other large-scale changes.
First, ICE began making more arrests of people without criminal convictions and more arrests at large in communities.^[The at large arrests principally target Latinos, according to journalists, advocates, and human rights observers. See for example, Human Rights Watch, [US: ICE Abuses in Los Angeles Set Stage for Other Cities](https://www.hrw.org/news/2025/11/04/us-ice-abuses-in-los-angeles-set-stage-for-other-cities).] For the two decades before 2025, ICE made very few such street arrests. Instead, ICE relied on transfers from jails and prisons for its interior enforcement. In 2025, the number of street arrests went up by **11 times** (see @fig-jails-street). Meanwhile, the number of transfers[^2] **doubled**, partly because ICE arrested more people without criminal convictions or with convictions for minor crimes.
::: {.content-visible when-format="html"}
Second, ICE increased the number of deportations following arrests by detaining more people and releasing fewer once detained.[^3] ICE roughly **tripled** the number of detention beds used for interior enforcement (see @fig-border-interior). It did so not only by spending more money on detention, but also because of a decline in arrivals at the border. That trend, which [mostly occurred](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6124006) in the last year of the Biden administration (see sidebar figure), freed up detention beds for people arrested within the United States. At the same time, as the administration increased the use of detention, detention has begun to lead to removal more often, with the chance of deportation within 60 days of detention increasing from **55 percent** to just over **69 percent**, a 25 percent relative increase. As the release rate decreased, the number of voluntary departures increased by more than **21 times**.
:::
::: {.content-visible when-format="pdf"}
Second, ICE increased the number of deportations following arrests by detaining more people and releasing fewer once detained.[^3] ICE roughly **tripled** the number of detention beds used for interior enforcement (see @fig-border-interior). It did so not only by spending more money on detention, but also because of a decline in arrivals at the border. That trend, which [mostly occurred](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6124006) in the last year of the Biden administration (see @fig-bp-arrests-pdf), freed up detention beds for people arrested within the United States. At the same time, as the administration increased the use of detention, detention has begun to lead to removal more often, with the chance of deportation within 60 days of detention increasing from **55 percent** to just over **69 percent**, a 25 percent increase. As the release rate decreased, the number of voluntary departures increased by more than **21 times**.
:::
::: {.content-visible when-format="html"}
```{r}
#| fig-cap: "Border Patrol Arrests"
#| label: bp-arrests
#| column: margin
bp_df <-
tribble(
~fiscal_year , ~OCT , ~NOV , ~DEC , ~JAN , ~FEB , ~MAR , ~APR , ~MAY , ~JUN , ~JUL , ~AUG , ~SEP ,
"2026" , 9846 , 9213 , NA , NA , NA , NA , NA , NA , NA , NA , NA , NA ,
"2025" , 58115 , 47534 , 48137 , 30127 , 9241 , 8193 , 10007 , 10359 , 8014 , 6168 , 8085 , 10203 ,
"2024" , 190454 , 192357 , 251178 , 125440 , 142104 , 139124 , 131078 , 121646 , 87606 , 59655 , 60684 , 55993 ,
"2023" , 206902 , 209496 , 224017 , 131720 , 131547 , 165068 , 185149 , 172423 , 100606 , 134064 , 182377 , 220323 ,
) |>
pivot_longer(-fiscal_year, names_to = "month", values_to = "bp_arrests") |>
filter(!is.na(bp_arrests)) |>
mutate(
fiscal_year = as.numeric(fiscal_year),
year = if_else(
month %in% c("OCT", "NOV", "DEC"),
fiscal_year - 1,
fiscal_year
)
) |>
mutate(date = ymd(str_c(year, "-", month, "-1")))
bp_df |>
filter(year >= 2023) |>
ggplot(aes(date, bp_arrests)) +
geom_line(size = 3) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
scale_y_continuous(
breaks = c(100000, 200000),
labels = scales::label_number(scale = 1e-3, suffix = "k")
) +
scale_x_date(
breaks = c(
as.Date("2023-01-01"),
as.Date("2024-01-01"),
as.Date("2025-01-01")
),
labels = c("2023", "2024", "2025")
) +
scale_color_viridis_d(name = NULL) +
labs(x = "Date of arrest", y = "Monthly arrests") +
theme_minimal_transparent(35)
```
:::
The increase in detention space and immigrants' decisions not to fight their cases from detention help explain why, even as ICE arrested people who would be more likely to win their cases, such as those without any criminal convictions, the deportation rate among arrestees shot up.
Despite the scale of these trends, the administration is not close to its goal of deporting one million people a year if that goal refers to interior deportations. At the most recent rate for which we have data (September/October 2025), the government would deport under 300,000 people this year.[^4] That number would be unprecedented in this century, but not close to the administration’s target.
In this report, we document these two patterns using individual-level data on arrests and detentions obtained from ICE through litigation over a Freedom of Information Act request filed by the Center for Immigration Law and Policy at UCLA, which was represented by Deportation Data Project attorneys. We draw on data from the second half of 2024 through October 15, 2025. We posted these datasets on the project website in December, promptly after receiving them from ICE.
## Interior Deportations Increased by Four and a Half Times
We know of no reliable count of the total number of deportations during the first year of the Trump administration.[^5] Instead of producing a total count, we focus on a key trend: the number of deportations over time following an ICE arrest and detention.[^6] @fig-deportations shows deportations following ICE arrest and detention over time.[^7] The number more than quadrupled:[^8] there were 4.6 times as many deportations following ICE arrest and detention in the last month of the data (September 15 -- October 14, 2025) as during the average month in the second half of 2024.
We arrive at this estimate of the change in the number of deportations based on two key analytical choices. First, we consider only deportations that started with an arrest by ICE inside the United States. By separating interior and border enforcement, two countervailing trends emerge: the rise in interior enforcement on the one hand and decline in border enforcement on the other. The decline in arrests at the Southwest border continued a trend that began under the Biden Administration. (Notably, [research by one of us](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6124006) demonstrates that federal border policy influences trends in immigrants' arrivals less than commonly thought.)
Second, we compare the last month of available data (mid-September to mid-October 2025) to the last half of 2024. The rate of deportations rose dramatically over the course of 2025, and so our choice leads to a comparison of recent enforcement policy with that under the final months of the Biden Administration.
The rest of this report explains how such a large increase in deportations occurred, tracing that increase at least partly to changes in arrests and detention.
```{r}
#| fig-cap: "Interior Deportations by ICE Increased by Four and a Half Times"
#| label: fig-deportations
plot_df <-
detentions_with_arrests |>
filter(stay_book_out_date >= as.Date("2024-07-01")) |>
mutate(
remove = stay_release_reason %in%
c("Removed", "Voluntary Return", "Voluntary departure")
) |>
mutate(
week = lubridate::round_date(stay_book_out_date, "week")
) |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
filter(remove == TRUE)
change_ratio <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_out_date) >= as.Date("2024-07-01") &
as.Date(stay_book_out_date) <= as.Date("2024-12-31") ~ "before",
as.Date(stay_book_out_date) >= as.Date("2025-09-14") &
as.Date(stay_book_out_date) <= as.Date("2025-10-14") ~ "current"
),
month = case_when(
time_period == "before" ~ month(stay_book_out_date),
time_period == "current" ~ 10
)
) |>
filter(!is.na(time_period)) |>
group_by(time_period, month) |>
summarize(total = n()) |>
summarize(avg_monthly = mean(total)) |>
pivot_wider(names_from = time_period, values_from = avg_monthly) |>
summarize(current / before)
plot_df |>
count(week) |>
filter(week < as.Date("2025-10-12")) |>
ggplot(aes(week, n)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 6000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 6000,
label = "Trump II",
hjust = 0,
size = 4
) +
geom_line(size = 0.8) +
scale_y_continuous(labels = scales::label_comma(), limits = c(0, NA)) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
labs(
x = "Date of book-out from detention for removal",
y = "Weekly removals"
) +
theme_minimal_transparent()
```
## More Arrests, Especially Street Arrests
The first reason the increase in deportations was possible was a quadrupling of ICE arrests resulting in detention. @fig-arrests illustrates the overall trend.[^9] ICE started making more of the arrests it has always made -- and also started making vastly more street arrests and arrest of people without criminal convictions.^[An early report of this pattern was published in the [Los Angeles Times](https://www.latimes.com/california/story/2025-06-24/detention-centers-swell-with-immigrants-with-no-criminal-record).]
<!-- Figure 2: Total ICE Arrests Resulting in Detention -->
```{r}
#| label: fig-arrests
#| fig.cap: "ICE Arrests Resulting in Detention Quadrupled"
plot_df <-
detentions_with_arrests |>
filter(stay_book_in_date_time >= as.Date("2024-07-01")) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week")
) |>
filter(has_arrest == TRUE, border_arrest == FALSE)
change_ratio <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_in_date_time) >= as.Date("2024-07-01") &
as.Date(stay_book_in_date_time) <= as.Date("2024-12-31") ~ "before",
as.Date(stay_book_in_date_time) >= as.Date("2025-09-14") &
as.Date(stay_book_in_date_time) <= as.Date("2025-10-14") ~ "current"
),
month = case_when(
time_period == "before" ~ month(stay_book_in_date_time),
time_period == "current" ~ 10
)
) |>
filter(!is.na(time_period)) |>
group_by(time_period, month) |>
summarize(total = n()) |>
summarize(avg_monthly = mean(total)) |>
pivot_wider(names_from = time_period, values_from = avg_monthly) |>
summarize(current / before)
plot_df |>
count(week) |>
filter(week < as.Date("2025-10-12")) |>
ggplot(aes(week, n)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 0.8) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 7200,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 7200,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma(), limits = c(0, NA)) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
labs(x = "Date of book-in to detention", y = "Weekly arrests") +
theme_minimal_transparent()
```
Before 2025, ICE arrests were mostly not arrests in the usual sense of the word. Instead, they were transfers of custody from jails or prisons. In such transfers, noncitizens who were initially arrested on criminal charges (typically unrelated to immigration law), are moved by ICE to immigration detention facilities, where they are held for civil violations of immigration law. In 2025, ICE quadrupled total arrests by (1) more than doubling the number of such transfers and (2) increasing arrests not in jails or prisons by more than a factor of ten. @fig-jails-street illustrates these two trends.[^10] The over tenfold increase from a low base explains why ICE street arrests seem like a new phenomenon.
```{r}
#| label: fig-jails-street
#| fig-cap: "Transfers from Jails and Prisons Doubled and Street Arrests Increased by 10x"
plot_df <-
detentions_with_arrests |>
filter(stay_book_in_date_time >= as.Date("2024-07-01")) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week"),
custodial = case_when(
apprehension_method %in%
c(
"CAP Federal Incarceration",
"CAP Local Incarceration",
"CAP State Incarceration",
"Criminal Alien Program",
"Custodial Arrest"
) ~ "Custodial arrests\n(Transfers from jail or prison)",
apprehension_method %in%
c(
"Non-Custodial Arrest",
"Located",
"Worksite Enforcement",
"Probation and Parole"
) ~ "Street Arrests"
# TRUE ~ "Non-custodial arrest\n(Street arrests, worksite raids)"
)
) |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
filter(!is.na(custodial))
change_ratio <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_in_date_time) >= as.Date("2024-07-01") &
as.Date(stay_book_in_date_time) <= as.Date("2024-12-31") ~ "before",
as.Date(stay_book_in_date_time) >= as.Date("2025-09-15") &
as.Date(stay_book_in_date_time) <= as.Date("2025-10-14") ~ "current"
),
month = case_when(
time_period == "before" ~ month(stay_book_in_date_time),
time_period == "current" ~ 10
)
) |>
filter(!is.na(time_period)) |>
group_by(custodial, time_period, month) |>
summarize(total = n()) |>
summarize(avg_monthly = mean(total)) |>
pivot_wider(names_from = time_period, values_from = avg_monthly) |>
summarize(current / before)
plot_df |>
count(week, custodial) |>
filter(week < as.Date("2025-10-12")) |>
ggplot(aes(week, n, color = custodial)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 0.8) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 4000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 4000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_color_viridis_d(name = NULL) +
scale_y_continuous(labels = scales::label_comma(), limits = c(0, NA)) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
labs(x = "Date of book-in to detention", y = "Weekly arrests") +
theme_minimal_transparent()
```
The new administration has also more than doubled transfers from jails and prisons to ICE custody. Under the Biden administration, ICE often declined to transfer a person from a local jail to immigration detention if the person did not meet one of the government’s enforcement priorities -- for example, if the noncitizen had not been convicted of certain crimes.[^11]
For both transfers and street arrests, the Trump administration’s decision to stop prioritizing arrests based on factors such as criminal convictions (or to prioritize less) resulted in another well-known trend: the huge increase in the number of arrests of noncitizens not convicted of any crime.
@fig-convictions shows trends in arrests by criminal conviction. Comparing the month before the inauguration to the last month in the data, arrests of people without convictions went up by seven times; arrests of people with nonviolent convictions doubled, and arrests of people with convictions for violent crimes increased by roughly 30%.^[[CBS News](https://www.cbsnews.com/news/ice-detentions-non-criminal-immigrants-violent-crime-convictions-analysis/) published an early analysis of the crimes noncitizens were charged with in the first months of the new administration.]
```{r}
#| label: fig-convictions
#| fig-cap: "Arrests of Noncitizens Without Criminal Convictions Up 7x"
plot_df <-
detentions_with_arrests |>
mutate(
msc_code = as.character(most_serious_conviction_code),
# keep only pure 4-digit numeric NCIC-style codes for the UCR logic
msc4 = if_else(str_detect(msc_code, "^[0-9]{4}$"), msc_code, NA_character_),
# Homicide (09xx) EXCLUDING negligent manslaughter (0909, 0910)
ucr_violent = (str_detect(msc4, "^09") & !msc4 %in% c("0909", "0910")) |
# Rape / Sexual Assault (11xx) EXCLUDING statutory rape - no force (1116)
(str_detect(msc4, "^11") & msc4 != "1116") |
# Robbery (12xx)
str_detect(msc4, "^12") |
# Aggravated assault ONLY: 1301–1312 plus 1314–1315
msc4 %in%
c(
sprintf("13%02d", 1:12),
"1314",
"1315"
),
conviction = case_when(
ucr_violent ~ "Violent crime",
!is.na(most_serious_conviction_code) ~ "Nonviolent crime",
TRUE ~ "None"
)
) |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
filter(stay_book_in_date_time >= as.Date("2024-07-01")) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week")
)
change_ratio <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_in_date_time) >= as.Date("2024-07-01") &
as.Date(stay_book_in_date_time) <= as.Date("2024-12-31") ~ "before",
as.Date(stay_book_in_date_time) >= as.Date("2025-09-15") &
as.Date(stay_book_in_date_time) <= as.Date("2025-10-14") ~ "current"
),
month = case_when(
time_period == "before" ~ month(stay_book_in_date_time),
time_period == "current" ~ 10
)
) |>
filter(!is.na(time_period)) |>
group_by(conviction, time_period, month) |>
summarize(total = n()) |>
summarize(avg_monthly = mean(total)) |>
pivot_wider(names_from = time_period, values_from = avg_monthly) |>
summarize(current / before)
plot_df |>
count(week, conviction) |>
filter(week < as.Date("2025-10-12")) |>
ggplot(aes(week, n, color = conviction)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 0.8) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 5000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 5000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma()) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
scale_color_viridis_d(name = "Convictions") +
labs(x = "Date of book-in to detention", y = "Weekly arrests") +
theme_minimal_transparent()
```
The change in targeted affected both street arrests and transfers from jails and prisons. @fig-convictions-street-transfers illustrates both, and highlights that the trend is more pronounced among street arrests.^[Note that the numbers in the left and right panels of Figure 5 don’t quite add up to the number in Figure 2 because we are unsure how to categorize some ICE arrests.]
```{r}
#| label: fig-convictions-street-transfers
#| fig-cap: "Arrests of Noncitizens without Criminal Convictions Increased among Street Arrests and Also Among Transfers from Jails"
label_months_short <- function(x) {
labs <- format(x, "%b.")
is_jan <- !is.na(x) & month(x) == 1
labs[is_jan] <- paste0(labs[is_jan], "\n", format(x[is_jan], "%Y"))
first_ok <- which(!is.na(x))[1]
if (!is.na(first_ok)) {
labs[first_ok] <- paste0(
format(x[first_ok], "%b."),
"\n",
format(x[first_ok], "%Y")
)
}
labs
}
plot_df <-
detentions_with_arrests |>
mutate(
custodial = case_when(
apprehension_method %in%
c(
"CAP Federal Incarceration",
"CAP Local Incarceration",
"CAP State Incarceration",
"Criminal Alien Program",
"Custodial Arrest"
) ~ "Custodial arrests\n(Transfers from jail or prison)",
TRUE ~ "Non-custodial arrest\n(Street arrests, worksite raids)"
),
msc_code = as.character(most_serious_conviction_code),
# keep only pure 4-digit numeric NCIC-style codes for the UCR logic
msc4 = if_else(str_detect(msc_code, "^[0-9]{4}$"), msc_code, NA_character_),
# Homicide (09xx) EXCLUDING negligent manslaughter (0909, 0910)
ucr_violent = (str_detect(msc4, "^09") & !msc4 %in% c("0909", "0910")) |
# Rape / Sexual Assault (11xx) EXCLUDING statutory rape - no force (1116)
(str_detect(msc4, "^11") & msc4 != "1116") |
# Robbery (12xx)
str_detect(msc4, "^12") |
# Aggravated assault ONLY: 1301–1312 plus 1314–1315
msc4 %in%
c(
sprintf("13%02d", 1:12),
"1314",
"1315"
),
conviction = case_when(
ucr_violent ~ "Violent crime",
!is.na(most_serious_conviction_code) ~ "Nonviolent crime",
TRUE ~ "None"
)
) |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
filter(stay_book_in_date_time >= as.Date("2024-07-01")) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week")
) |>
count(week, conviction, custodial) |>
filter(week < as.Date("2025-10-12"))
plot_df |>
ggplot(aes(week, n, color = conviction)) +
geom_line(size = 0.8) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 3800,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 3800,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma()) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months_short
) +
facet_grid(~custodial) +
scale_color_viridis_d(name = "Convictions") +
labs(x = "Week of book-in to detention", y = "Weekly arrests") +
theme_minimal_transparent()
```
## More Detentions, Fewer Releases
Deportations increased not only because more people were arrested but also because, first, ICE had more space to hold them, and second, the government changed the rules to prevent detainees from being released while fighting their cases.
The number of daily detention beds holding people arrested in the interior of the United States **more than tripled** over the course of 2025, increasing from a daily average of around 13,000 in the second half of 2024 to over 43,000 in the last month of data (mid-September to mid-October 2025). This was possible for two reasons. First, as widely reported, the total number of detention beds increased from around 40,000 in January 2025 to over 60,000 in October 2025,[^12] in large part because ICE received a huge infusion of cash from the One Big Beautiful Bill. @fig-new-facilities shows that those resources mostly resulted in more people being held in existing facilities; new facilities accounted for only about a third of the increase.
```{r }
#| label: fig-new-facilities
#| fig-cap: "Increase in ICE Detention Largely Comes from Expanding Use of Existing Facilities, One Third of Increase Comes from New Facilities"
plot_df <-
detention_stints |>
left_join(
detentions_with_arrests |> select(stay_ID, has_arrest, border_arrest),
by = "stay_ID"
) |>
as_tibble() |>
mutate(
new_facility = min(
pmin(book_in_date_time, book_out_date_time, na.rm = TRUE),
na.rm = TRUE
) >=
as.Date("2025-01-01"),
.by = "detention_facility_code"
) |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
mutate(
start_date = as_date(book_in_date_time),
end_date = as_date(book_out_date_time),
end_date = if_else(is.na(end_date), as_date("2025-10-15"), end_date)
) |>
# ensure end_date is not before start_date (recode to start_date if so)
mutate(end_date = pmax(start_date, end_date)) |>
rowwise() |>
mutate(date = list(seq(start_date, end_date, by = "day"))) |>
unnest(date) |>
ungroup() |>
group_by(stay_ID, date) |>
summarize(
in_new_facility = any(new_facility),
in_old_facility = any(!new_facility),
.groups = "drop"
) |>
mutate(
week = lubridate::round_date(date, "week")
)
plot_df |>
group_by(week) |>
summarize(
n_new = n_distinct(stay_ID[in_new_facility]),
n_old = n_distinct(stay_ID[in_old_facility]),
.groups = "drop"
) |>
pivot_longer(
cols = c("n_new", "n_old"),
names_to = "type",
values_to = "n"
) |>
mutate(
in_new_facility = case_when(
type == "n_new" ~ "Not used before 2025",
type == "n_old" ~ "Used before 2025"
)
) |>
filter(week >= as.Date("2025-01-20"), week < as.Date("2025-10-12")) |>
ggplot(aes(week, n, color = in_new_facility)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 0.8) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 45000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma()) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months,
limits = c(as.Date("2025-01-01"), as.Date("2025-10-15"))
) +
scale_color_viridis_d(name = NULL) +
labs(x = "Date of book-in to detention", y = "Weekly detainees") +
theme_minimal_transparent()
```
Less well known is that the huge increase in detention was also possible because arrests at the border declined. @fig-border-interior shows these countervailing trends. As arrests at the border fell -- both because fewer people were trying to cross the border and because the new administration began expelling nearly everyone who did -- there was more space in detention for people arrested with the United States. ICE rapidly filled that space.
A key note here is that the decrease in arrivals at the border mostly took place during the last year of the Biden administration. As one of us has [explained](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6124006) in other work, it is incorrect to suggest that the Trump administration is mostly responsible for the decline in arrivals, and there are reasons to believe that deterrence efforts at the border are less effective than commonly believed.
```{r}
#| label: fig-border-interior
#| fig-cap: "ICE Detention Bed Space Opened by Decreasing Border Arrests Filled by Arrestees from the Interior"
plot_df <-
detentions_with_arrests |>
mutate(
interior = case_when(
has_arrest == TRUE & border_arrest == FALSE ~ "Arrest in the interior",
TRUE ~ "Arrest near border"
)
) |>
mutate(
start_date = as_date(stay_book_in_date_time),
end_date = as_date(stay_book_out_date_time - seconds(1)),
end_date = if_else(is.na(end_date), as_date("2025-10-15"), end_date)
) |>
# ensure end_date is not before start_date (recode to start_date if so)
mutate(end_date = pmax(start_date, end_date)) |>
rowwise() |>
mutate(date = list(seq(start_date, end_date, by = "day"))) |>
unnest(date) |>
ungroup() |>
group_by(date, interior) |>
summarize(
n_detained = n(),
n_detained_at_midnight = sum(
as.Date(stay_book_in_date_time) <= date &
(is.na(stay_book_out_date_time) |
as.Date(stay_book_out_date_time) > date),
na.rm = TRUE
),
.groups = "drop"
)
plot_df |>
mutate(
week = lubridate::round_date(date, "week")
) |>
group_by(week, interior) |>
summarize(
n_detained_at_midnight = mean(n_detained_at_midnight),
.groups = "drop"
) |>
filter(week >= as.Date("2024-07-01"), week < as.Date("2025-10-12")) |>
ggplot(aes(week, n_detained_at_midnight, color = interior)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 0.8) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 45000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 45000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(
labels = scales::label_number(scale = 1e-3, suffix = "k")
) +
scale_y_continuous(labels = scales::label_comma(), limits = c(0, NA)) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
scale_color_viridis_d(name = NULL) +
labs(
x = "Date of book-in to detention",
y = "Average overnight detainees\nby week"
) +
theme_minimal_transparent()
```
Finally, the administration did not just increase the number of people in detention, it also made it harder for them to be released. Before this administration, ICE often released people from detention who were reasonably likely to win their case, and if ICE didn’t release them itself, an immigration judge often granted them release on bond. Both decisions were in the hands of the presidential administration.^[Unlike other federal judges, immigration judges are administrative judges who are employed by the Department of Justice and are bound by guidance from the Attorney General and the Board of Immigration Appeals, also a part of the Department of Justice.]
ICE now releases virtually no one before a final deportation decision, and the administration has also made it far more difficult for immigration judges to release people by granting bond. On July 8, ICE [issued](https://www.aila.org/library/ice-memo-interim-guidance-regarding-detention-authority-for-applications-for-admission) guidance suggesting that anyone who had entered the country without inspection (i.e. between ports of entry) was ineligible for bond, regardless of how long they had lived in the United States. On September 5, the Board of Immigration Appeals [reached](https://www.justice.gov/eoir/media/1413311/dl?inline) the same conclusion in a decision that bound immigration judges. Despite [hundreds](https://www.politico.com/news/2026/01/05/trump-administration-immigrants-mandatory-detention-00709494) of judicial opinions finding the policy illegal, ICE and immigration courts continue to apply it. One result has been a flood of habeas corpus petitions (cases filed in federal district court to seek noncitizens’ release from unlawful detention), many of which have succeeded--but a very small number on the scale of current detention.[^13]
As fewer people have been released from detention, more have been swiftly deported. @fig-release-reasons illustrates this trend; as the chance of release within 60 days of book-in has gone down from 16% to 3% (a relative decrease of 81%), the chance of deportation within 60 days has increased from 55% to 69% (a relative increase of over 25%).[^14]
```{r}
#| label: fig-release-reasons
#| fig-cap: "Chance of Release Down by Over 80%, Change of Deportation Up 25%"
plot_df <-
detentions_with_arrests |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
filter(
!(stay_release_reason %in% c("Died", "Escaped", "Transferred")),
is.na(stay_release_reason) |
!str_detect(stay_release_reason, "Marshal|ORR|Disposition|Withdraw")
) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week"),
stay_duration = as.numeric(
as.Date(stay_book_out_date_time) -
as.Date(stay_book_in_date_time)
),
class = case_when(
stay_release_reason %in%
c("Voluntary Return", "Voluntary departure", "Removed") &
stay_duration < 60 ~ "Removed within\n60 days",
stay_release_reason %in%
c(
"Bonded Out - Field Office",
"Order of Recognizance - Humanitarian",
"Order of Supervision - Humanitarian",
"Order of Supervision - No SLRRFF",
"Order of Supervision - Re-Release",
"Order of recognizance",
"Order of supervision",
"Paroled",
"Paroled - Fear Found",
"Paroled - Humanitarian",
"Paroled - Public Benefit",
"Bonded Out - IJ",
"Proceedings Terminated",
"Relief Granted by IJ"
) &
stay_duration < 60 ~ "Released within\n60 days",
is.na(stay_release_reason) |
stay_duration >= 60 ~ "Not released within\n60 days"
),
class = factor(
class,
levels = c(
"Not released within\n60 days",
"Released within\n60 days",
"Removed within\n60 days"
)
)
) |>
filter(
!is.na(class)
) |>
filter(
stay_book_in_date_time >= as.Date("2023-10-01"),
stay_book_in_date_time <= as.Date("2025-10-15") - 60
)
ratio_df <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_in_date_time) >= as.Date("2024-05-01") &
as.Date(stay_book_in_date_time) <= as.Date("2024-10-31") ~ "before",
as.Date(stay_book_in_date_time) >= as.Date("2025-07-15") &
as.Date(stay_book_in_date_time) <= as.Date("2025-08-14") ~ "current"
)
) |>
filter(!is.na(time_period)) |>
group_by(class, time_period) |>
summarize(total = n(), .groups = "drop") |>
mutate(prop = total / sum(total), .by = time_period) |>
arrange(time_period, class) |>
select(-total) |>
pivot_wider(names_from = time_period, values_from = prop) |>
summarize(current / before)
plot_df |>
count(week, class) |>
filter(week >= as.Date("2024-07-01"), week < as.Date("2025-10-12")) |>
mutate(prop = n / sum(n), .by = week) |>
ggplot(aes(week, prop, fill = class)) +
geom_area(position = "stack", alpha = 0.9) +
geom_vline(
xintercept = as.Date("2025-01-20"),
lty = "dashed",
col = "white"
) +
annotate(
"text",
x = as.Date("2025-01-10"),
y = 0.95,
label = "Biden",
hjust = 1,
size = 4,
col = "white"
) +
annotate(
"text",
x = as.Date("2025-01-30"),
y = 0.95,
label = "Trump II",
hjust = 0,
size = 4,
col = "white"
) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
scale_y_continuous(labels = scales::label_percent()) +
scale_fill_viridis_d(name = NULL) +
labs(
x = "Week of book-in to detention",
y = "Percent of detainees\nbooked into detention"
) +
theme_minimal_transparent()
```
Many factors, including the [purge](https://www.npr.org/2026/01/10/nx-s1-5672386/the-trump-administration-fired-nearly-100-immigration-judges-in-2025-whats-next) of immigration judges, may be contributing to these trends. One key possibility is that more people are giving up on their cases and accepting removal. One specific way to accept deportation from detention is to agree to so-called voluntary departure, which @fig-voluntary-departures shows increased more than twentyfold in 2025. The voluntary departure determination by an immigration judge allows a noncitizen to leave the country without being subject to a lengthy bar on applying for readmission. Not everyone who gives up on their case receives voluntary departure; a removal order may be the result as well, which means that either voluntary departure or removal may follow from the pressure created by immigration detention. There is no way to know from the data how many removal orders have followed from people giving up, but the combination of the increase in voluntary departures and the decline in releases suggests that giving up to avoid more detention is an important part of the story.
```{r}
#| label: fig-voluntary-departures
#| fig-cap: "Voluntary Departures Increased More than 21x"
plot_df <-
detentions_with_arrests |>
filter(has_arrest == TRUE, border_arrest == FALSE) |>
mutate(
week = lubridate::round_date(stay_book_in_date_time, "week"),
stay_duration = as.numeric(
difftime(
as.Date(stay_book_out_date_time),
as.Date(stay_book_in_date_time),
units = "days"
)
),
voluntary_departure = (str_detect(
case_status |> str_to_lower(),
"olunt|vd|vr"
) |
str_detect(case_category |> str_to_lower(), "olunt|vd|vr")) &
stay_duration <= 60
) |>
filter(
voluntary_departure == TRUE
)
ratio_df <-
plot_df |>
mutate(
time_period = case_when(
as.Date(stay_book_in_date_time) >= as.Date("2024-05-01") &
as.Date(stay_book_in_date_time) <= as.Date("2024-10-31") ~ "before",
as.Date(stay_book_in_date_time) >= as.Date("2025-07-14") &
as.Date(stay_book_in_date_time) <= as.Date("2025-08-14") ~ "current"
),
month = case_when(
time_period == "before" ~ month(stay_book_in_date_time),
time_period == "current" ~ 10
)
) |>
filter(!is.na(time_period)) |>
group_by(time_period, month) |>
summarize(total = n()) |>
summarize(avg_monthly = mean(total)) |>
pivot_wider(names_from = time_period, values_from = avg_monthly) |>
summarize(current / before)
plot_df |>
count(week) |>
filter(week >= as.Date("2024-06-01"), week < as.Date("2025-10-12") - 60) |>
ggplot(aes(week, n)) +
geom_line(size = 0.8) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 1000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 1000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma()) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
scale_color_manual(
values = c(
`TRUE` = "#D55E00",
`FALSE` = "#0072B2"
),
labels = c(
`TRUE` = "Violent conviction",
`FALSE` = "No violent conviction"
),
name = NULL # removes legend title
) +
labs(
x = "Date of book-in to detention",
y = "Weekly voluntary departures"
) +
theme_minimal_transparent()
```
## Conclusion
Focusing on immigration enforcement *within* the United States reveals the extent of the Trump administration’s crackdown: deportations following ICE arrests increased by more than four and a half times. ICE expanded street arrests so swiftly that they seem like an entirely new phenomenon and began arresting vastly more people who had no criminal convictions. ICE detained more people by expanding detention capacity and taking advantage of a decline in arrivals at the border to make more use of existing detention capacity for people arrested in the interior of the United States. Detention more often led to removal because ICE largely eliminated the possibility of release before a final decision.
## Methodology {.appendix}
Every step we took, beginning with the raw data, is documented in the code that we have posted. This section offers a less technical description of our approach.
To identify a set of deportations following ICE arrest and detention, we use two datasets from our latest (October 15, 2025) ICE data release.
We start with the arrests data and remove duplicates as well as rows that lack the unique identifiers that allow matching of the arrests and the detentions data.
We then join the arrests data with the detention stays data, treating any arrest that occurred up to ten days before a book-in to detention, as well as any arrest that took place less than five days after a book-in to detention, as linked to that book-in to detention. We adopt this approach because we believe that in some cases, arrest and/or book-in dates may be approximate, and we do not want to incorrectly exclude observations.
We do not include any detention book-ins that lack a corresponding arrest record. We recognize that this choice may lead us to exclude some interior detentions that started, for example, with an arrest by Homeland Security Investigations (our arrest data only includes arrests by ICE Enforcement and Removal Operations) or simply where the arrest was not recorded. We make this choice in order to build a comparable set of detentions over time, for which we think it is unlikely that the detentions started at the border.
We count deportations using the stay release reason in the detentions data, rather than using the removals table. We do this for two reasons. First, the latest removals dataset that we have published only covers the period through July 28, 2025. But second, since we’re focused on individuals who were arrested and detained by ICE, we believe that the stay release reason offers a good measure of the number of removals.
To identify custodial and noncustodial arrests, we use the apprehension method field in the arrests table, and we count arrests as custodial if they are categorized as “CAP Federal Incarceration,” “CAP State Incarceration,” “CAP Local Incarceration,” “Criminal Alien Program,” and “Custodial Arrest,” and as noncustodial or street arrests if they are categorized as “Non-Custodial Arrest,” “Located,” “Worksite Enforcement,” and “Probation and Parole.”
To classify convictions as violent or nonviolent, we use the most serious criminal charge field in the detentions table, and we cross-reference the named conviction with the FBI list of violent offenses, which include “murder and nonnegligent manslaughter, rape, robbery, and aggravated assault” (https://cde.ucr.cjis.gov/LATEST/webapp). Where no charge of any kind is listed, we treat the individual as having no conviction.
To identify voluntary departures, we use a combination of the case category, case status, and stay release reason fields; if any of those fields indicates a voluntary departure, we categorize the case as a voluntary departure.
To estimate how frequently detention results in release and removal, we look only at each individual's first sixty days of detention, and we ignore the last sixty days of book-ins so that we are looking at a consistent window over time and to avoid truncation bias.
\setlength{\parindent}{0em}
## Acknowledgments {.appendix}
We thank Dorothy Kronick, Phil Neff, and Amber Qureshi for comments and the UCLA Center for Immigration Law and Policy for their collaboration in obtaining the data.
## Disclosures {.appendix}
Blair consults for immigrants' rights organizations as an expert, including on litigation challenging ICE arrest and detention policies. Hausman worked for the American Civil Liberties Union Immigrants' Rights Project as an attorney from 2016 to 2019 and briefly as a volunteer attorney in early 2025. He continues to consult occasionally for the ACLU and other immigrants' rights organizations, including on litigation challenging the no-release policy described in this report. He is also a member of the academic advisory board for the Acacia Center.
## About the authors {.appendix}
[Graeme Blair](https://graemeblair.com) is a professor of political science at UCLA. He studies state violence and how to make social science more credible, ethical, and useful. His book, *Research Design in the Social Sciences* was published by Princeton University Press, and his book *Crime, insecurity, and community policing* was published by Cambridge University Press. He received a Ph.D. in politics from Princeton University and a B.A. in political science from Reed College. He received the Leamer-Rosenthal Prize in Open Social Science.
[David Hausman](https://david-hausman.com) is an assistant professor of law at Berkeley. He studies immigration enforcement, drawing on a background in quantitative methods and litigation experience at the ACLU. He has conducted data analysis as a consulting expert in numerous immigration cases. He has also published [scholarly](https://www.david-hausman.com/_files/ugd/a3c925_b5f5dcc8168644d4ab942c5264138230.pdf) [research](https://academic.oup.com/jleo/advance-article-abstract/doi/10.1093/jleo/ewac012/6767771?redirectedFrom=fulltext) [using](https://scholarship.law.upenn.edu/cgi/viewcontent.cgi?article=9525&context=penn_law_review) [immigration](https://www.pnas.org/content/early/2020/10/13/2014673117) enforcement datasets. He received his J.D. and Ph.D. in political science from Stanford University and clerked for Judge Stephen Williams on the D.C. Circuit Court of Appeals.
[^1]: Many of the findings here are mirrored in journalists' accounts. We have posted an incomplete list of them at [https://deportationdata.org/news.html](https://deportationdata.org/news.html). [The New York Times](https://www.nytimes.com/interactive/2026/01/18/us/trump-deportation-numbers-immigration-crackdown.html) published a recent detailed accounting.
[^2]: ICE refers to these transfers from jails and prisons as arrests. This recent [piece](https://www.washingtonpost.com/immigration/2025/12/28/ice-deportations-data-trump-arrests/) offers an account of the large rise in at-large arrests.
[^3]: A recent [report](https://www.americanimmigrationcouncil.org/wp-content/uploads/2026/01/immigration-detention-report.pdf) from the American Immigration Council documents similar trends with different emphases (and often more detail).
[^4]: In order to be confident that our measure is comparable over time, we make conservative decisions in determining which deportations are interior deportations, and it is possible that we underestimate the total number by up to 10-15%. If so, that would not change this qualitative conclusion.
[^5]: ICE and Customs and Border Protection (CBP) both produce datasets on removals, but they likely overlap to some degree, and since they are not connected, we have not developed a reliable way to estimate the size of the overlap. Austin Kocher has offered a detailed [discussion](https://austinkocher.substack.com/p/dhs-claims-603000-deportations-but) of these issues.
[^6]: To be more precise, we include only individuals who had an ICE arrest around the date of their book-in to ICE detention, and who were booked out of ICE detention for removal. We do not use ICE’s removals dataset both because we have doubts about its reliability and because we believe this is a meaningful measure of interior deportations over time.
[^7]: We include removals, voluntary departures, and (a small number of) voluntary returns as deportations here. We consider voluntary departures separately below.
[^8]: Notice that this does **not** mean that the annual total number of deportations in 2025 is five times larger than in 2024\. Instead, we are comparing the last month of data to the six months in the second half of 2024\. Although our individual-level data does not go beyond October 15, 2025, ICE’s summary statistics suggest that it has sustained or slightly increased the number of removals since that date. Since ICE does not distinguish between interior and border removals in those statistics, however, we cannot be certain.
[^9]: We focus on arrests that actually resulted in detention; it is possible for ICE to arrest a person and then decide not to book that person into detention.
[^10]: We exclude a small number of arrests that we could not categorize as custodial or street arrests.
[^11]: The memo laying out these enforcement priorities is available [here](https://www.ice.gov/doclib/news/guidelines-civilimmigrationlaw.pdf).
[^12]: ICE Detention Management spreadsheets.
[^13]: According to one [count](https://www.politico.com/news/2026/01/05/trump-administration-immigrants-mandatory-detention-00709494), there are now more than 100 lawsuits filed daily–but there are close to 1000 ICE arrests per day.
[^14]: A small number of these releases are actually victories in immigration court while detained, but that number does not contribute meaningfully to the trend.
::: {.content-visible when-format="pdf"}
\clearpage
## Appendix
\setcounter{figure}{0}
\renewcommand{\thefigure}{A}
```{r}
#| fig-cap: "Border Patrol Arrests"
#| label: fig-bp-arrests-pdf
#| fig-width: 5.5
#| fig-height: 3
bp_df <-
tribble(
~fiscal_year , ~OCT , ~NOV , ~DEC , ~JAN , ~FEB , ~MAR , ~APR , ~MAY , ~JUN , ~JUL , ~AUG , ~SEP ,
"2026" , 9846 , 9213 , NA , NA , NA , NA , NA , NA , NA , NA , NA , NA ,
"2025" , 58115 , 47534 , 48137 , 30127 , 9241 , 8193 , 10007 , 10359 , 8014 , 6168 , 8085 , 10203 ,
"2024" , 190454 , 192357 , 251178 , 125440 , 142104 , 139124 , 131078 , 121646 , 87606 , 59655 , 60684 , 55993 ,
"2023" , 206902 , 209496 , 224017 , 131720 , 131547 , 165068 , 185149 , 172423 , 100606 , 134064 , 182377 , 220323 ,
) |>
pivot_longer(-fiscal_year, names_to = "month", values_to = "bp_arrests") |>
filter(!is.na(bp_arrests)) |>
mutate(
fiscal_year = as.numeric(fiscal_year),
year = if_else(
month %in% c("OCT", "NOV", "DEC"),
fiscal_year - 1,
fiscal_year
)
) |>
mutate(date = ymd(str_c(year, "-", month, "-1")))
bp_df |>
filter(year >= 2023) |>
ggplot(aes(date, bp_arrests)) +
geom_vline(
color = "grey30",
xintercept = as.Date("2025-01-20"),
lty = "dashed"
) +
geom_line(size = 1) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-10"),
y = 250000,
label = "Biden",
hjust = 1,
size = 4
) +
annotate(
color = "grey30",
"text",
x = as.Date("2025-01-30"),
y = 250000,
label = "Trump II",
hjust = 0,
size = 4
) +
scale_y_continuous(labels = scales::label_comma(), limits = c(0, NA)) +
scale_x_date(
breaks = function(x) {
seq(
floor_date(min(x, na.rm = TRUE), "quarter"),
ceiling_date(max(x, na.rm = TRUE), "quarter"),
by = "quarter"
)
},
labels = label_months
) +
scale_x_date() +
scale_color_viridis_d(name = NULL) +
labs(x = "Date of arrest", y = "Monthly arrests") +
theme_minimal_transparent()
```
:::