Technical writing

HUD LIHTC Database: Mapping 35 Years of Low-Income Housing Tax Credit Projects

· 16 min read· AI Analytics
Federal DataHUDAffordable HousingHousing Policy

The United States has a roughly 7.3 million-unit shortage of affordable rental housing for extremely low-income households. The single largest federal program addressing that shortage is not a direct spending program — it is a tax credit. The Low-Income Housing Tax Credit has financed more than 50,000 developments and 3.5 million affordable units since 1987, and HUD publishes the complete project-level database. Almost nobody outside housing policy circles uses it.

The HUD LIHTC database is among the most complete longitudinal records of subsidized affordable housing production in the country. It covers every project allocated credits from 1987 through the present, with fields for location, credit type, unit count, allocation year, project type, and the housing agency that awarded the credits. Researchers have used it to study neighborhood change, the geography of affordable housing production, the effects of Qualified Allocation Plan design, and how LIHTC interacts with gentrification. The data is free, bulk-downloadable, and documented. The analytical surface is enormous.

This article covers the LIHTC program mechanics, the HUD database structure and known limitations, the distinction between 9% and 4% credits, how state housing finance agencies shape what gets built where, and Python code to produce a state-level per-capita analysis of units placed in service since 2010.

What LIHTC is

The Low-Income Housing Tax Credit was created by the Tax Reform Act of 1986 and codified at Internal Revenue Code Section 42. Congress's theory was straightforward: the federal government would offer tax credits to private developers who agreed to build or rehabilitate affordable rental housing, the developers would sell those credits to corporate investors who needed to reduce their tax liability, and the resulting equity would subsidize below-market rents. The program was designed to leverage private capital rather than appropriate direct federal spending — which made it politically durable through decades of budget austerity that decimated direct housing programs.

LIHTC is now the largest affordable housing production program in the United States, generating more than $10 billion in annual tax credits. The US has approximately 44 million rental units; LIHTC has funded roughly 8% of total rental stock but a dramatically higher share of new affordable construction. In any given year, LIHTC accounts for the majority of new affordable units built with federal assistance.

The affordability commitment is structured in two phases. The initial compliance period is 15 years, during which the project must maintain income and rent restrictions or the developer faces credit recapture. The extended use period adds another 15 years. The practical minimum affordability commitment is therefore 30 years from the date placed in service. Many projects make longer commitments voluntarily — some state QAPs award additional points for extended use periods of 40, 50, or 60 years — but the 30-year floor is the federal statutory minimum.

How the program works mechanically

A LIHTC project begins when a developer applies to a state Housing Finance Agency for a credit allocation. If awarded, the developer receives authority to claim a stream of annual tax credits over 10 years. The developer then “syndicates” those credits to institutional investors — banks seeking Community Reinvestment Act credit, insurance companies, and other corporations with large federal tax liability — who pay upfront equity in exchange for the right to claim the credits.

The price investors pay per dollar of credit determines how much equity is available to capitalize construction. When investor demand is strong, credit prices rise and projects pencil out with less debt. When demand is weak — as during the 2008 financial crisis, when bank tax liability collapsed — credit prices fall and fewer projects can be financed at the same subsidy level. The LIHTC market is therefore sensitive to the corporate tax rate and to the financial health of the large institutional buyers who absorb most of the supply.

Units must be rented to households earning 50% or 60% of Area Median Income (AMI) or less, with rents capped at 30% of the applicable income limit. A project can mix income tiers: some units at 40% AMI, others at 60% AMI, with corresponding rent caps. The income limit reported in the HUD database reflects the deepest income targeting in the project — a project with any units at 50% AMI will appear as 50% AMI even if most units are at 60%.

The 9% credit vs. the 4% credit

LIHTC comes in two forms, and the distinction matters enormously for understanding what the database contains.

The 9% credit is the high-value, competitive form. Congress caps aggregate 9% credit allocations at $3.13 per capita per state annually (with a minimum floor of approximately $3.6 million for small states), indexed to inflation. In 2024 the nationwide cap was roughly $1 billion. Every state HFA runs an annual competitive round, scores applications against its Qualified Allocation Plan criteria, and awards credits to the highest-scoring projects until the annual cap is exhausted. The ratio of applications to awards is typically 3-to-1 or higher in competitive states. A 9% credit project is generally new construction on bare land or substantial rehabilitation that effectively rebuilds the structure.

The 4% credit is the lower-value, non-competitive form. It is available in essentially unlimited quantity but requires that at least 50% of the project's aggregate basis be financed by tax-exempt private activity bonds. The bond volume cap — a separate per-state limit on tax-exempt bond issuance — is the binding constraint on 4% deals, not a LIHTC cap. Because the 4% credit is worth less per dollar (roughly 30 cents versus 70 cents per dollar of eligible basis), it requires more debt and often more gap financing to close. The 4% credit is commonly used for acquisition-rehabilitation projects: buying an existing market-rate or assisted property and rehabbing it to extend or create affordability.

The 2021 American Rescue Plan temporarily increased the 4% credit to 5% for projects with bond financing commitments made between 2021 and 2026, improving the economics of bond-financed deals. This change boosted 4% project production in the database substantially in the 2021-2025 allocation years.

The HUD LIHTC database

HUD publishes the national LIHTC database at huduser.gov/portal/datasets/lihtc.html. The database is maintained under HUD contract by Novogradac and Abt Associates, who compile state HFA reports, reconcile discrepancies, and geocode project addresses. It is updated annually; the current release as of mid-2024 covers allocations through approximately 2022, with a one-to-two-year lag between credit allocation and database inclusion that reflects the time required to collect and validate data from all 57 state and territory HFAs.

Database fields

Each record in the database represents a single LIHTC project. Key fields:

PROJECT         Project name (as reported by the HFA)
HUD_ID          HUD project identifier (not stable across releases)
PROJ_ADD        Street address
PROJ_CTY        City
PROJ_ST         State (2-letter abbreviation)
PROJ_ZIP        ZIP code
FIPS2010        11-digit census tract FIPS code (2010 boundaries)
FIPS2020        11-digit census tract FIPS code (2020 boundaries)
COUNTY          County name
FIPS_ST         State FIPS code (2 digits)
FIPS_CTY        County FIPS code (5 digits)
HUD_REG         HUD region number (1-10)

YR_ALLOC        Year tax credits were allocated by the HFA
YR_PIS          Year placed in service (first units occupied)
                -- NOTE: YR_PIS is often 1-3 years after YR_ALLOC

N_UNITS         Total residential units in the project
LI_UNITS        Low-income units (subject to income/rent restrictions)
                -- LI_UNITS <= N_UNITS (market-rate units in mixed projects
                   are counted in N_UNITS but not LI_UNITS)

CREDIT_PCT      Credit type: 0.70 (9% credit) or 0.30 (4% credit)
                -- Encoding varies by release (see code note below)

TYPE            Project type:
                1 = New construction
                2 = Substantial rehabilitation
                3 = Both new construction and rehab
                4 = Acquisition only (rare, grandfathered)

TRGPOP          Target population:
                F = Family
                E = Elderly (62+ or 55+, depending on project)
                H = Homeless
                S = Special needs / supportive housing
                O = Other

TRGT_POP        Same as TRGPOP in some releases; check which is populated

LIHTC_AMT       Tax credit dollar amount allocated ($)
                -- Annual credit amount; total 10-year stream = 10x this value
                -- Not reported by all states; blank for ~20% of records

ALLOCAGCY       Name of the state housing finance agency that allocated credits

HAC_MET         Whether the project met the "difficult development area" or
                "qualified census tract" criteria (affects credit basis)

METRO           Metro area indicator and CBSA code

Known data limitations

The HUD database has several documented gaps that affect analysis:

  • Geocoding gaps. Approximately 5–8% of records lack a valid census tract code, particularly for older projects (1987–1995) and for rural addresses that were not captured in the reference geocoder. Tract-level analysis should handle null FIPS2010 values explicitly rather than silently dropping them.
  • Missing credit amounts. The LIHTC_AMT field is blank for roughly 20% of records, concentrated in states that report only unit counts to HUD. Any per-dollar analysis must account for this missingness.
  • State reporting variation. HFAs are not legally required to report all fields to HUD; the database depends on voluntary cooperation. Some states consistently omit target population or project type. Florida and Texas have historically had higher-than-average missing field rates.
  • Allocation vs. placed-in-service lag. A project allocated credits in 2018 might not appear with a YR_PIS date until 2020 or 2021. Analysis by placed-in-service year is more relevant for housing stock questions; analysis by allocation year better reflects HFA policy decisions and annual QAP design.
  • No unit-level data. The database records project-level aggregates. It does not contain unit-level rent amounts, bedroom mix, or individual tenant income data. Tenant-level data is collected by HFAs during compliance monitoring but is not published.

State Housing Finance Agencies and Qualified Allocation Plans

Every state (plus the District of Columbia, Puerto Rico, and several territories) has a Housing Finance Agency that receives an annual 9% credit allocation and distributes it through a competitive scoring process governed by a Qualified Allocation Plan. The QAP is the central policy instrument shaping where affordable housing gets built and who it serves.

IRC Section 42 requires QAPs to give preference to projects serving the lowest incomes, in areas of greatest need, with longer affordability commitments. Beyond those federal minimums, states have wide discretion. The practical effect is that QAPs reflect each state's theory of affordable housing policy, and those theories vary dramatically.

Scoring criteria common across state QAPs include location in high-opportunity areas (defined by school quality, employment access, and low poverty rates), proximity to transit, targeting of households below 30% or 40% AMI rather than the 60% maximum, rural vs. urban set-asides, service-enriched housing for homeless or special-needs populations, developer experience and track record, green building certification, and local government contribution of land or gap financing.

The opportunity area criteria — points for locating in high-income neighborhoods with good schools — are among the most consequential and contested QAP design choices. Their intent is to deconcentrate poverty: instead of siting affordable housing in already-low-income neighborhoods (as public housing was historically), LIHTC would put low-income families in areas with better outcomes. In practice, opportunity area criteria make it harder to build in lower-income neighborhoods where land is cheap and community opposition is lower, and they benefit wealthier suburbs at the expense of cities that need affordable housing in already-dense areas.

The HUD LIHTC database's census tract codes enable direct empirical study of this tension: joining tract codes to ACS data on income and poverty rate produces the income distribution of LIHTC project siting by state, which can be compared across states with different QAP opportunity-area criteria.

LIHTC, gentrification, and displacement

The relationship between LIHTC and gentrification is more complex than either critics or defenders of the program tend to acknowledge. Two opposing dynamics operate simultaneously.

In high-cost cities — New York, San Francisco, Seattle — LIHTC provides the only mechanism available to preserve existing affordable housing units that would otherwise be converted to market-rate use as leases expire or buildings are sold. Acquisition-rehabilitation deals using the 4% credit have kept hundreds of thousands of units affordable in gentrifying neighborhoods. Without LIHTC, the displacement rate in these markets would be substantially higher.

The opposite dynamic operates in low-income neighborhoods where new LIHTC construction has been identified as a catalyst for gentrification. Studies of LIHTC placement in Chicago, Atlanta, and Baltimore have found that new affordable housing developments in very low-income neighborhoods attracted market-rate development and retail investment that raised surrounding property values and, eventually, rents — displacing existing tenants who were not in the LIHTC units themselves. The program created affordable housing in one building while making the surrounding neighborhood less affordable.

The QAP's opportunity area preferences push new construction toward high-income neighborhoods where this gentrification dynamic is less likely (because property values are already high), but they also make it harder to serve the existing low-income residents who are most exposed to displacement risk. The trade-off does not have a clean resolution, and the HUD database provides the empirical foundation to study it: tract-level LIHTC unit counts joined to longitudinal ACS data on income, poverty, and housing cost.

The National Housing Preservation Database

The HUD LIHTC database covers one program. Researchers who need a complete picture of federally assisted housing — all programs, all subsidy types — should use the National Housing Preservation Database (NHPD), published by the Public and Affordable Housing Research Corporation (PAHRC).

The NHPD integrates LIHTC data with HUD project-based Section 8 contracts, USDA Rural Development multifamily housing programs, the HOME Investment Partnerships Program, and HUD's Section 202 (elderly) and Section 811 (disabled) programs. Each record includes a preservation risk score based on the remaining term of each subsidy contract and the likelihood that the owner would exit the program at contract expiration.

The NHPD is the right starting point for preservation gap analysis — identifying units at risk of converting to market rate as their LIHTC compliance periods expire. A substantial wave of projects placed in service in the early-to-mid 1990s reached their initial 15-year compliance period by 2005–2010, and the extended use periods for those projects expire in 2020–2025, creating a preservation cliff visible in the LIHTC database by looking at the distribution of YR_PIS values plus 30 years.

How researchers use LIHTC data

Several research applications have been particularly productive:

Affordability gap analysis

Comparing LIHTC units per capita to housing cost burden rates from the ACS (percent of renters paying more than 30% of income on housing) produces a rough measure of program adequacy by geography. States with high cost burden and low LIHTC production per capita are underserved relative to need. The B25070 ACS table provides gross rent as a percentage of household income at the tract level.

LIHTC vs. Section 8 geography

Project-based Section 8 (PBS8) housing was concentrated in urban core neighborhoods because that is where HUD site-and-service contracts were executed in the 1970s and 1980s. LIHTC projects, shaped by QAP opportunity area criteria, skew toward suburbs and higher-income tracts in most states. Mapping both programs simultaneously reveals whether the combined federal subsidized housing stock serves geographically diverse populations or whether program transition from PBS8 to LIHTC has shifted federal housing assistance away from urban low-income communities.

CRA examination outcomes

Banks invest in LIHTC equity syndicates partly because the investments generate Community Reinvestment Act credit during OCC, Federal Reserve, or FDIC examinations. CRA examination ratings and area delineations are public. Joining LIHTC investment activity (available in syndication disclosures filed with HFAs) to CRA examination ratings by institution tests whether LIHTC investment activity correlates with CRA rating outcomes — and whether banks concentrate LIHTC investment in their CRA assessment areas or invest nationally to minimize geographic obligation.

Neighborhood change studies

The census tract identifier in the LIHTC database enables longitudinal analysis by joining the same tract across multiple ACS release years. Studies of LIHTC neighborhood effects typically compare ACS tract-level demographics and income data from five years before project placed-in-service to five years after, using comparison tracts matched on pre-period characteristics. The results are heterogeneous — LIHTC effects on surrounding neighborhoods depend heavily on whether the project is new construction or rehab, whether it is in a low- or high-income neighborhood, and the scale of the development relative to the tract.

Code: units per capita by state and credit type, 2010–2023

The following script downloads the HUD LIHTC database, filters to projects placed in service 2010–2023, groups by state and credit type (4% vs. 9%), and computes low-income units per 1,000 residents using ACS population data. A note on the credit type encoding: HUD has used at least three different encodings across release years (numeric 70/30, decimal 0.70/0.30, and string “70 %”/“30 %”). The code handles all three.

import pandas as pd
import requests

# ---------------------------------------------------------------
# Step 1: Download the HUD LIHTC database CSV
# Available at: https://www.huduser.gov/portal/datasets/lihtc.html
# The file is updated annually; direct download link varies by year.
# As of 2024 the current release is lihtcpub.zip (~30 MB unzipped).
# ---------------------------------------------------------------
url = 'https://www.huduser.gov/portal/datasets/lihtc/lihtcpub.zip'
import urllib.request, zipfile, io

print('Downloading HUD LIHTC database...')
with urllib.request.urlopen(url) as resp:
    zf = zipfile.ZipFile(io.BytesIO(resp.read()))
    csv_name = [n for n in zf.namelist() if n.endswith('.csv')][0]
    df = pd.read_csv(zf.open(csv_name), encoding='latin-1', low_memory=False)

print(f'Total records: {len(df):,}')
print(df.dtypes[['PROJ_ADD', 'PROJ_ST', 'YR_PIS', 'LI_UNITS', 'N_UNITS',
                  'CREDIT_PCT', 'TYPE', 'PROJECT']].to_string())

# ---------------------------------------------------------------
# Step 2: Filter to projects placed in service 2010-2023
# YR_PIS = year placed in service
# ---------------------------------------------------------------
pis = df[
    df['YR_PIS'].between(2010, 2023)
].copy()

print(f'Projects placed in service 2010-2023: {len(pis):,}')

# ---------------------------------------------------------------
# Step 3: Classify credit type (4% vs 9%)
# CREDIT_PCT values: '0.70' or '0.70 %' = 9% (new construction / sub rehab)
#                   '0.30' or '0.30 %' = 4% (rehabilitation / bond-financed)
# HUD encodes as numeric 70 / 30 in some releases, string in others.
# Coerce to numeric then classify.
# ---------------------------------------------------------------
pis['credit_pct_num'] = pd.to_numeric(
    pis['CREDIT_PCT'].astype(str).str.replace('%', '').str.strip(),
    errors='coerce'
)
# Both 70 and 0.70 appear across releases depending on encoding
pis['credit_type'] = pis['credit_pct_num'].apply(
    lambda x: '9pct' if (x is not None and (x >= 60 or (0.6 <= x <= 1.0))) else '4pct'
)

# ---------------------------------------------------------------
# Step 4: Fetch Census population by state for per-capita denominator
# ACS 5-year 2022 estimates, B01001_001E = total population
# ---------------------------------------------------------------
def fetch_state_population():
    r = requests.get(
        'https://api.census.gov/data/2022/acs/acs5',
        params={
            'get': 'NAME,B01001_001E',
            'for': 'state:*',
        },
        timeout=30,
    )
    rows = r.json()
    headers = rows[0]
    data = rows[1:]
    pop = pd.DataFrame(data, columns=headers)
    pop['population'] = pd.to_numeric(pop['B01001_001E'])
    # FIPS state code -> 2-letter abbreviation mapping via Census name field
    # We join on state FIPS, so keep the numeric code and NAME for reference
    pop['state_fips'] = pop['state'].str.zfill(2)
    return pop[['NAME', 'state_fips', 'population']]

print('Fetching Census state population data...')
pop_df = fetch_state_population()

# ---------------------------------------------------------------
# Step 5: FIPS state code to 2-letter abbreviation crosswalk
# HUD stores state as 2-letter PROJ_ST; Census uses numeric FIPS.
# Build a crosswalk from a bundled lookup.
# ---------------------------------------------------------------
fips_to_abbr = {
    '01': 'AL', '02': 'AK', '04': 'AZ', '05': 'AR', '06': 'CA',
    '08': 'CO', '09': 'CT', '10': 'DE', '11': 'DC', '12': 'FL',
    '13': 'GA', '15': 'HI', '16': 'ID', '17': 'IL', '18': 'IN',
    '19': 'IA', '20': 'KS', '21': 'KY', '22': 'LA', '23': 'ME',
    '24': 'MD', '25': 'MA', '26': 'MI', '27': 'MN', '28': 'MS',
    '29': 'MO', '30': 'MT', '31': 'NE', '32': 'NV', '33': 'NH',
    '34': 'NJ', '35': 'NM', '36': 'NY', '37': 'NC', '38': 'ND',
    '39': 'OH', '40': 'OK', '41': 'OR', '42': 'PA', '44': 'RI',
    '45': 'SC', '46': 'SD', '47': 'TN', '48': 'TX', '49': 'UT',
    '50': 'VT', '51': 'VA', '53': 'WA', '54': 'WV', '55': 'WI',
    '56': 'WY',
}
pop_df['state_abbr'] = pop_df['state_fips'].map(fips_to_abbr)

# ---------------------------------------------------------------
# Step 6: Group by state and credit type; compute total LI units
# LI_UNITS = low-income units (units with rent and income restrictions)
# N_UNITS = total units in the project
# ---------------------------------------------------------------
pis['LI_UNITS_num'] = pd.to_numeric(pis['LI_UNITS'], errors='coerce')

grouped = (
    pis
    .groupby(['PROJ_ST', 'credit_type'])['LI_UNITS_num']
    .sum()
    .reset_index()
    .rename(columns={'PROJ_ST': 'state_abbr', 'LI_UNITS_num': 'li_units'})
)

# Pivot to wide format: one row per state
pivot = grouped.pivot_table(
    index='state_abbr',
    columns='credit_type',
    values='li_units',
    fill_value=0,
).reset_index()
pivot.columns.name = None
pivot = pivot.rename(columns={'4pct': 'units_4pct', '9pct': 'units_9pct'})
pivot['total_li_units'] = pivot['units_4pct'] + pivot['units_9pct']

# ---------------------------------------------------------------
# Step 7: Merge population; compute units per 1,000 residents
# ---------------------------------------------------------------
result = pivot.merge(
    pop_df[['state_abbr', 'NAME', 'population']],
    on='state_abbr',
    how='left'
)
result['li_units_per_1k'] = (result['total_li_units'] / result['population']) * 1000
result = result.sort_values('li_units_per_1k', ascending=False)

print()
print('Low-income LIHTC units placed in service 2010-2023, per 1,000 residents:')
print(result[['NAME', 'units_4pct', 'units_9pct', 'total_li_units', 'li_units_per_1k']]
      .to_string(index=False, float_format=lambda x: '{:.2f}'.format(x)))

Expected output shape: states with the highest 9% credit production per capita tend to be smaller states (Vermont, Maine, North Dakota) where the per-capita floor on the annual allocation creates a structurally higher per-resident credit volume. Large states (California, Texas, Florida) have lower per-capita 9% production despite having large absolute allocations, because their populations are vast relative to the annual cap. The 4% credit distribution skews toward states with active bond markets and strong urban rehab pipelines.

Cross-reference opportunities

The LIHTC database produces its strongest analytical results when read alongside other federal datasets:

HUD fair housing complaints

HUD's Fair Housing and Equal Opportunity office complaint data reveals where housing discrimination is alleged to occur. Joining LIHTC project locations to fair housing complaint geographies tests whether areas with high LIHTC density show elevated complaint rates — which could reflect higher tenant awareness of fair housing rights in subsidized housing, or could reflect management practices at LIHTC projects that generate complaints.

Census ACS housing variables

ACS table B25003 (housing tenure) and table B25070(gross rent as percentage of income) provide the denominator for per-capita analysis and the outcome variable for affordability gap studies. ACS table B25024 (units in structure) reveals whether LIHTC is adding multifamily supply in markets dominated by single-family rental housing.

HMDA mortgage lending data

HMDA tracks mortgage originations by census tract; LIHTC tracks affordable rental unit production by census tract. The two programs serve different ends of the housing market — HMDA the homeownership market, LIHTC the rental market — but their tract-level intensities reveal how federal housing policy allocates resources across income levels and tenure types. Tracts with high HMDA origination volume and low LIHTC density are markets where federal housing policy is effectively serving homeowners but not renters.

Related writing

Mapping housing discrimination: using HUD FHEO complaint data to find fair housing violations — The structure of HUD's Fair Housing and Equal Opportunity complaint database and what 50,000+ complaints reveal about where housing discrimination concentrates.

The mortgage map: using HMDA loan-level data to find lending disparities — How to acquire and analyze HMDA loan-level data from the CFPB bulk download to surface redlining, reverse redlining, and lender-level racial denial rate disparities.

The demographic backbone: using Census ACS data to contextualize every other federal dataset — ACS 5-year tract-level estimates as the denominator for LIHTC per-capita analysis, housing cost burden rates, and every other federal housing dataset.