acs-nativity: A Python Package for Analyzing Changes in the Foreign-Born Population

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 censusdis package (such as censusdis.states)

Installing acs-nativity automatically installs censusdis, so these constants are available once the package is installed.

Below are examples for several common geographies:

GeographyKeywordModule for ValueExample
United Statesus-df = get_nativity_timeseries(us="*")
Statesstatecensusdis.statesfrom censusdis.states import MN
df = get_nativity_timeseries(state=MN)
Countycountycensusdis.counties.from censusdis.states import NY
from censusdis.counties.new_york import NASSAU
df = get_nativity_timeseries(state=NY, county=NASSAU)
Cityplacecensusdis.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_msafrom 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.

Ari Lamstein

Ari Lamstein

I’m a software engineer who focuses on data projects.

I most recently worked as a Staff Data Science Engineer at a marketing analytics consultancy. While there I developed internal tools for our data scientists, ran workshops on data science and mentored data scientists on software engineering.

I have also created several open source projects.