President Trump has made reducing illegal immigration and increasing deportations central goals of his second administration (1, 2). This is causing many people to ask: how are these policies changing the country’s population?
To help answer that, I built a new open-source Python package called acs-nativity. It provides a simple interface for accessing and visualizing data on the size of the native-born and foreign-born populations. The data comes from American Community Survey (ACS) 1-year estimates and is available from 2005 onward. The package supports multiple geographies: nationwide, all states, all metropolitan statistical areas (MSAs), and all counties and places (i.e., towns or cities) with populations of 65,000 or more.
Because it pulls data directly from the Census API, the package will automatically work with the 2025 ACS estimates as soon as they’re released in September. That release will cover the first year of Trump’s second administration, making it possible to compare recent changes against nearly two decades of historical data.
Installation
You can install acs-nativity with pip:
pip install acs-nativity
Example Workflow
The example below walks you through getting historic nativity data for the entire country, graphing it as a time series, and graphing the year-over-year changes.
Getting Data
The code below retrieves nativity data for the entire country for all available ACS 1‑year estimates (2005–2024):
from acs_nativity import (
get_nativity_timeseries,
plot_nativity_timeseries,
plot_nativity_change,
)
df = get_nativity_timeseries(us="*")
df.head(1)
The parameter us="*" tells get_nativity_timeseries() to return data for the entire country. The output of that code is:
Name Year Total Native Foreign-born Percent Foreign-born United States 2005 288378137 252688295 35689842 12.376057
The output returns the same columns for every geography: Name, Year, Total, Native, Foreign-born, and Percent Foreign-born.
Graphing Time Series
To plot the dataframe as a time series, call plot_nativity_timeseries() and specify the column you want to chart. Most chart details (e.g., title and axis labels) are handled automatically, and annotations show when presidential administrations changed.
fig = plot_nativity_timeseries(df, column="Foreign-born") fig.show()
Note: In Jupyter notebooks, you can simply call plot_nativity_timeseries() as the last line of a cell and the figure will render automatically. In a Python REPL or script, assign the figure to a variable and call .show().
The code above generates the following graph:
This graph shows that the foreign-born population has increased steadily since 2005, with a particularly large increase during the Biden administration.
Graphing Year-over-Year Change
Sometimes it’s helpful to show year-over-year changes instead of raw values. To do that, call plot_nativity_change() with a dataframe and a column:
fig = plot_nativity_change(df, column="Foreign-born") fig.show()
Note: In Jupyter notebooks, you can simply call plot_nativity_change() as the last line of a cell and the figure will render automatically. In a Python REPL or script, assign the figure to a variable and call .show().
The code above generates this graph:
This chart makes it clear that the only year when the foreign-born population decreased was 2008.
Choosing a Geography
get_nativity_timeseries() can provide data for several geographies covered by the ACS 1-year estimates. This includes the nation, all states, the District of Columbia, all metropolitan statistical areas, and all counties and places (i.e., towns or cities) with populations of 65,000 or more.
To specify a geography, supply a keyword argument where:
- the keyword identifies the geography type (such as
state) - the value is a constant imported from a module in the
censusdispackage (such ascensusdis.states)
Installing acs-nativity automatically installs censusdis, so these constants are available once the package is installed.
Below are examples for several common geographies:
| Geography | Keyword | Module for Value | Example |
|---|---|---|---|
| United States | us | - | df = get_nativity_timeseries(us="*") |
| States | state | censusdis.states | from censusdis.states import MN df = get_nativity_timeseries(state=MN) |
| County | county | censusdis.counties. | from censusdis.states import NY from censusdis.counties.new_york import NASSAU df = get_nativity_timeseries(state=NY, county=NASSAU) |
| City | place | censusdis.places. | from censusdis.states import IL from censusdis.places.illinois import CHICAGO_CITY df = get_nativity_timeseries(state=IL, place=CHICAGO_CITY) |
| Metropolitan Statistical Area (MSA) | (See note below) | censusdis.msa_msa | from censusdis.msa_msa import EL_PASO_TX_METRO_AREA df = get_nativity_timeseries( metropolitan_statistical_area_micropolitan_statistical_area= EL_PASO_TX_METRO_AREA ) |
Note: The keyword for MSAs is metropolitan_statistical_area_micropolitan_statistical_area, which is too long to display cleanly inside the table.
Getting the Latest Data
By default, get_nativity_timeseries() returns data for 2005–2024. These years were chosen because:
- 2005 is the first year of ACS 1‑year estimates
- 2024 is the most recent year available at the time this package was published
The last year of data is controlled by the end_year parameter, which defaults to 2024.
The Census Bureau is expected to release the 2025 ACS 1‑year estimates in September 2026. When that happens, you can retrieve the new data by setting end_year=2025. For example:
df = get_nativity_timeseries(end_year=2025, us="*")
After the new data is published, the above code will get nativity data for the entire US from 2005-2025.
Related Work
If you’re interested in exploring similar projects I’ve worked on, here are three that connect closely to the ideas behind acs-nativity and show how this package grew out of earlier work.
- Using Python to Measure Immigration Trends. My first immigration‑related project, and the origin of the core ideas behind
acs‑nativity. I wrote a small module to stitch together multiple years of ACS data into a single DataFrame and added functions to visualize the results, using immigration trends in my hometown as a case study. - censusdis v1.4.0 is now on PyPI. A follow‑up post describing how I contributed that code to
censusdis, the package I use to access the Census API. The piece focuses on the tools and conventions used in modern Python package development (linting, testing, CI, type annotations, dependency management) and how those practices differ from writing ad hoc analytical code. - A Python App for Analyzing Immigration Enforcement Data. An introduction to my Streamlit app that visualizes immigration enforcement statistics, including ICE detentions and Border Patrol encounters. This post stands on its own, but it also kicked off a short series exploring enforcement trends in more depth.
What’s Next
If you try out the package, I’d love to hear what you build with it. Whether you’re analyzing national trends or exploring changes in your own community, I’m always interested in seeing how people use public data in creative ways. If you’d like to share feedback or results, you can reach me through the contact form on this site.

