HUD Affordable Housing Explorer: LIHTC + Multifamily + Public
Pricing
from $3.30 / 1,000 results
HUD Affordable Housing Explorer: LIHTC + Multifamily + Public
Search HUD LIHTC, FHA-insured multifamily, and public housing layers as one unified property feed. Filter by state, city, program, and minimum units; each row has units, low-income units, owner/manager, lat/lon, and an Opportunity Zone flag. Lead lists for LIHTC investors, developers, lenders.
Pricing
from $3.30 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
4 days ago
Last modified
Share
HUD Affordable Housing Explorer — LIHTC, Multifamily, Public Housing + Opportunity Zones
One unified property list across three HUD programs at once, with a designated Qualified Opportunity Zone flag computed by point-in-polygon. Keyless, straight from HUD's own eGIS ArcGIS services.
| Program | What it is | Live count |
|---|---|---|
| LIHTC | Low-Income Housing Tax Credit properties | 50,566 |
| HUD_INSURED | FHA-insured multifamily properties | 17,582 |
| PUBLIC_HOUSING | Public housing developments | 6,211 |
| Opportunity Zones | Treasury-designated QOZ census tracts | 8,765 |
Counts measured live on 2026-08-01 and re-measured on every run — see
data_vintage.
What makes this different
- Three programs, one row shape. LIHTC, FHA-insured multifamily and public housing normally live in three incompatible datasets. Here they share a single schema, so a portfolio screen is one query.
- Nothing is asserted that was not checked.
opportunity_zoneis three-valued:true,false, ornullwhen it could not be tested. Every row names which HUD layers answered (lihtc_status,hud_insured_status,public_housing_status) and whether the result set is complete (result_complete). - Truncation is disclosed, not silent. Every row carries
records_available_in_scope— the exact number of records your filter matched — next torecords_returnedandresults_truncated. - HUD republishes these layers annually. Before anything is billed, the run asserts each layer's name, its column set and its record count against values measured live, plus a positive canary and a negative control on the QOZ layer. If HUD swaps a layer for a different vintage, the run fails loudly instead of quietly answering from stale designations.
Who this is for
- Affordable-housing developers and syndicators — comparable LIHTC deals in a market, with allocation amount, credit type, bond financing, QCT/DDA basis boost and unit mix.
- CRE acquisition teams — FHA-insured multifamily with REAC inspection scores, loan maturity, watch-list and default flags.
- Housing policy and research — subsidised stock per state or city with resident demographics and occupancy.
- Opportunity Zone investors — properties inside designated QOZ tracts, with the tract GEOID and Treasury rural flag.
- AI agents — one call per state; three-valued flags and per-layer status so the agent can tell "no" from "not checked".
Example input
{"states": ["CO"],"programs": ["LIHTC", "HUD_INSURED", "PUBLIC_HOUSING"],"city": "","minUnits": 0,"includeOpportunityZoneFlag": true,"onlyOpportunityZone": false,"maxResults": 500}
city matches as a prefix, case-insensitively. minUnits and
onlyOpportunityZone are applied after fetching, so the run pulls a buffer
beyond maxResults when either is set.
Output — every field
The property
| Field | Meaning |
|---|---|
program | LIHTC, HUD_INSURED, or PUBLIC_HOUSING. |
source_id | HUD's own identifier: LIHTC HUD_ID, FHA property ID, or public-housing development code. |
property_name | Project or property name. |
address, city, state, zip, county | Location as HUD publishes it. |
standardized_address | HUD's USPS-standardized street address. |
census_tract_geoid | 11-digit census tract GEOID from HUD's own geocoding columns. |
msa_name, cbsa_name | Metro area. |
latitude, longitude | WGS84 coordinate, where HUD publishes one. |
units_total | Total units. |
units_low_income | Income-restricted / assisted units. |
units_occupied, units_vacant, occupancy_pct | Occupancy detail. |
unit_mix | Bedroom mix (LIHTC in counts, Public Housing in percentages). |
year_placed_in_service | Year the property entered service. |
owner_or_manager | Owner or management agent. HUD leaves the LIHTC COMPANY column empty for all 50,566 LIHTC properties nationwide, so this is populated on HUD Insured and Public Housing rows only — use contact_name for LIHTC. |
contact_name, contact_phone, contact_email | Published contact for the property. |
program_detail | Free-text program summary. |
Opportunity Zone
| Field | Meaning |
|---|---|
opportunity_zone | Three-valued. true = inside a designated QOZ tract. false = tested against the loaded QOZ layer and outside one. null = NOT tested. |
opportunity_zone_status | Why: ok, unavailable (the layer did not answer), no_polygons_returned, no_coordinate_published (HUD publishes no lat/lon for this property), or not_requested. |
oz_tract_geoid | GEOID10 of the QOZ tract. |
oz_is_rural | Treasury rural flag on that tract. |
LIHTC detail
| Field | Meaning |
|---|---|
year_allocated | Year the tax credits were allocated (distinct from placed-in-service). |
allocation_amount_usd | Annual credit allocation. |
is_bond_financed | Tax-exempt bond financed, i.e. the 4% credit rather than the competitive 9%. |
credit_type | HUD's credit-type code. |
construction_type | New construction, acquisition and rehab, or both. |
nonprofit_sponsor | A nonprofit is the project sponsor. |
target_population | Family, Elderly, Disabled, Homeless. |
in_qualified_census_tract | In a HUD Qualified Census Tract (30% basis boost). |
in_difficult_development_area | In a HUD Difficult Development Area (30% basis boost). |
HUD Insured Multifamily detail
| Field | Meaning |
|---|---|
reac_last_inspection_score | Most recent REAC physical-inspection score, 0-100. Below 60 triggers HUD enforcement. |
reac_last_inspection_date | Date of that inspection. |
has_section_8 | Active Section 8 contract. |
is_subsidized | Carries HUD subsidy. |
is_section_202_811 | Section 202 (elderly) or Section 811 (disabled). |
is_in_default | The FHA-insured mortgage is in default or delinquent. |
on_watch_list | HUD has placed the property on its watch list. |
loan_maturity_date | Maturity of the insured mortgage. |
original_loan_amount_usd | Original insured mortgage amount. |
contract_expiration_date | When the primary HUD assistance contract expires — the date the affordability restriction can lapse. Populated on 4,903 of 17,582 properties. |
Public Housing detail
| Field | Meaning |
|---|---|
pha_code | Public Housing Authority participant code. |
pha_total_units | Total units that PHA operates. |
scattered_site | A scattered-site development rather than a single building. |
Residents
| Field | Meaning |
|---|---|
pct_elderly | Residents aged 62+. |
pct_disabled | Residents reported with a disability. |
pct_minority | Residents reported as a racial or ethnic minority. |
avg_household_income_usd | Average annual household income. |
avg_rent_per_month_usd | Average monthly tenant-paid rent. |
Provenance — read these before trusting a result set
| Field | Meaning |
|---|---|
lihtc_status, hud_insured_status, public_housing_status | Per-layer outcome: ok, partial, unavailable, or null (not requested). |
programs_queried | Every program this run should have consulted. |
programs_ok | The ones that answered. |
programs_failed | The ones that did not. null when all answered. |
result_complete | true only when every requested layer answered. |
records_available_in_scope | Exact count matching your state/city filter, before minUnits / onlyOpportunityZone and before maxResults. |
records_returned | Rows actually returned. |
results_truncated | true when fewer rows came back than matched the scope. |
data_vintage | The record and column counts measured on each HUD layer at run time. A change between runs means HUD republished a layer. |
checked_at | UTC ISO-8601 timestamp of the run. |
Inputs that populate the sparser columns
| Columns | Verified live input |
|---|---|
contract_expiration_date | {"states":["NY"],"programs":["HUD_INSURED"],"maxResults":500} — HUD publishes it on 4,903 of 17,582 properties (281 in NY, 47 in CO). |
reac_last_inspection_score, loan_maturity_date, has_section_8, contact_email | Any run including HUD_INSURED. |
in_qualified_census_tract, allocation_amount_usd, unit_mix | Any run including LIHTC. |
pha_code, units_occupied, scattered_site | Any run including PUBLIC_HOUSING. |
programs_failed | Populated only when a HUD layer fails. null on a healthy run is the good outcome. |
How it works
- Live drift assertions run first, before anything billable. Each layer's name, column set and record count is checked against values measured on 2026-08-01, and the QOZ layer additionally gets a positive canary and a negative control (a state code that must match nothing — this catches a silently-ignored filter). Any failure fails the run and bills nothing.
- Each program is queried separately with an exact
returnCountOnlycount so truncation can be disclosed, then paged. - The program groups are round-robin merged so a capped run stays representative of every program rather than being monopolised by LIHTC, which has the most rows.
- Designated QOZ tract polygons for the selected states are loaded and each
property is tested by point-in-polygon. If the layer did not answer, or HUD
publishes no coordinate for a property,
opportunity_zoneisnull. - Filters are applied, results capped, and the billing gate runs before anything is written. If every layer failed, or nothing matched, the run fails with a message naming the cause.
Use as an MCP tool
Available through mcp.apify.com. One call per state. An agent should treat
opportunity_zone: null as unknown (never as "not in an Opportunity Zone"),
and check result_complete before concluding a market has no assisted housing.
Pricing
Pay-per-result: one property row = one billed result. A failed run emits nothing and costs nothing beyond the platform's Actor-start event. Volume tiers apply automatically on paid Apify plans.
FAQ
Why is owner_or_manager empty on LIHTC rows? Because HUD leaves the
COMPANY column empty for every one of the 50,566 LIHTC properties it
publishes — verified live. contact_name and contact_phone carry the LIHTC
allocation contact instead.
Why is opportunity_zone null on some rows? Because the property could not
be tested — usually because HUD publishes no coordinate for it. Read
opportunity_zone_status. A null is not a negative finding.
Why did the run fail instead of returning zero rows? Because a zero that comes from a failed layer, an over-tight filter or an outage is indistinguishable from a genuine "no such housing here". The failure message names the cause and nothing is billed.
How do I get everything in a state? Raise maxResults. Compare
records_returned with records_available_in_scope to see what you are
missing.
Is the Opportunity Zone flag legal advice? No. It is a point-in-polygon screen against HUD's published QOZ tract layer. Confirm with the tract's official designation before relying on it.
Related actors
- hud-qct-lihtc-boost-screener — Qualified Census Tract / DDA basis-boost check for an arbitrary coordinate.
- nyc-landlord-registry-lead-list, distressed-property-signal-stacker — owner contact and distress signals for NYC multifamily.
- fdic-sod-deposit-market-share-rollup — the lending market around a metro.