# CRA LMI Census Tract Screener: FFIEC Income Level by Address (`willed_nursery/cra-lmi-tract-screener`) Actor

Paste addresses, lat/lon or tract GEOIDs; get FFIEC CRA tract income level (low/moderate/middle/upper), LMI flag, tract MFI %, MSA/MD and minority %. Built from public Census, OMB and HMDA data. No API key. Pay only for classified rows.

- **URL**: https://apify.com/willed_nursery/cra-lmi-tract-screener.md
- **Developed by:** [Joel Sumner](https://apify.com/willed_nursery) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 classified tracts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## CRA LMI Census Tract Screener: FFIEC income level by address, lat/lon or tract

Paste US addresses, coordinates, or 11-digit tract GEOIDs. You get **one row per input** with the **FFIEC CRA tract income level** (Low / Moderate / Middle / Upper), an **LMI flag**, tract median family income as a % of the MSA/MD (or statewide non-MSA) MFI, the MSA/MD code and name, the minority % of the tract population and a majority-minority flag.

**Who it's for:** community banks, credit unions, CDFIs, mortgage and small-business lenders, fintech underwriting, and CRA/fair-lending consultants who need to tag loan files, branch sites or marketing lists by LMI tract. Also useful in AI-agent and Apify pipelines where signing up for another API key is a hassle.

### Why use it

- **No API key and no signup.** Addresses go through the free US Census Bureau batch geocoder. Everything else is built into the Actor.
- **Follows the FFIEC rule**, including FFIEC's truncation to 2 decimals (49.996% counts as **Low**, not 50%).
- **QA'd against FFIEC.** All 85,396 US + DC + PR tracts were checked against an FFIEC 2025 reference. **99.998% of income levels agree.** Both tracts that disagree are flagged `boundary_ambiguous`.
- **Transparent confidence:** `exact` (54,852 tracts), `interval` (30,515 tracts in MSAs redrawn by OMB in 2023; the area MFI is pinned to a few dollars), or `boundary_ambiguous` (29 tracts; check these on the FFIEC geocoder).
- **Pay only for classified rows.** No-match addresses, nonresidential tracts with unknown income, and invalid inputs come back as **free** rows that say why.

### Input

| Field | Example |
|---|---|
| `addresses` | `350 5th Ave, New York, NY 10118` |
| `coordinates` | `34.0522,-118.2437` |
| `tractGeoids` | `06037576403` |
You can mix the three types. A run accepts up to 10,000 inputs.

### Output (example)

```json
{"input":"06037576403","status":"classified","tract_geoid":"06037576403","income_level":"Low","income_level_code":1,"is_lmi":true,
 "tract_mfi_pct":49.99,"tract_mfi":40156,"area_mfi":80317,"msa_md_code":"31084","msa_md_name":"Los Angeles-Long Beach-Glendale, CA",
 "minority_pct":90.93,"majority_minority":true,"tract_population":4830,"confidence":"exact"}
```

`status` is one of `classified` (charged), `income_unknown`, `no_match`, `invalid_coordinates`, `invalid_geoid`, `tract_not_covered` or `geocoder_error` (all free).

### Data sources (all official, public domain)

- Tract median family income: ACS 2016–2020 5-year Summary File, table B19113 (US Census Bureau). FFIEC uses this same vintage for its 2022–2026 files.
- MSA/MD delineation: OMB Bulletin 23-01 (July 2023), from the Census `list1_2023.xlsx`.
- MSA/MD and statewide non-MSA denominators, minority %, population: CFPB/FFIEC HMDA 2025 public loan-level data, using its tract fields. These pin the denominators of areas that OMB redrew after 2020.
- Geocoding: US Census Bureau Geocoder (`Public_AR_Current` / `Current_Current`).
  The data basis is FFIEC 2025. FFIEC states that its 2026 tract list, including income levels, is identical to 2025.

### Limits

- This version does **not** include CRA distressed/underserved flags or Opportunity Zones (the OZ map changes on Jan 1, 2027).
- Territories other than Puerto Rico are not covered, because ACS 5-year tract income isn't published for them.
- The data needs a refresh when FFIEC publishes its 2027 file with new ACS income.
- This Actor is **not legal or compliance advice.** Confirm exam-critical rows on the [FFIEC Geocoding System](https://geomap.ffiec.gov/).
- Rows with `confidence: boundary_ambiguous` sit on an income-level boundary; in QA 2 of these 29 tracts differed from FFIEC. Always verify them on the FFIEC Geocoding System.
- Tract minority % and the majority-minority flag are provided for CRA/HMDA geographic and fair-lending analysis only. Do not use them (or any tract demographics) as a factor in individual credit decisions.

### Disclaimer, data vintage and privacy

- **Not an official FFIEC, CFPB or Census Bureau product.** This Actor is independent and is not affiliated with, endorsed by or certified by the FFIEC, its member agencies, the CFPB or the US Census Bureau. It independently reproduces the published FFIEC tract income-level rule from public data.
- **Data vintage:** FFIEC 2025 tract income levels (FFIEC states its 2026 list is identical), ACS 2016–2020 5-year tract income, OMB Bulletin 23-01 (July 2023) delineations, CFPB HMDA 2025 public data. Every output row carries a `data_vintage` field.
- This product uses the Census Bureau Data API (Census Geocoder) but is not endorsed or certified by the Census Bureau.
- **Privacy:** address and coordinate inputs are sent to the public US Census Bureau Geocoder to find the census tract; tract GEOID inputs are looked up entirely inside the Actor. Do not send borrower names or other personal data; only the address line is needed. Your inputs and results are stored only in your own Apify run storage.

### Pricing

Pay per event: **$0.002 per classified row**, plus Apify's standard Actor start event. Rows that aren't classified are free.

# Actor input Schema

## `addresses` (type: `array`):

Street, city, state ZIP on one line. Geocoded with the free US Census Bureau batch geocoder. Max 10,000 inputs per run (all types combined).

## `coordinates` (type: `array`):

Latitude,longitude in decimal degrees, e.g. 41.8789,-87.6359.

## `tractGeoids` (type: `array`):

2020-vintage 11-digit tract GEOID (state+county+tract). Connecticut uses the 2022 planning-region county codes. No geocoding needed.

## Actor input object example

```json
{
  "addresses": [
    "350 5th Ave, New York, NY 10118",
    "233 S Wacker Dr, Chicago, IL 60606",
    "1600 Pennsylvania Ave NW, Washington, DC 20500"
  ],
  "coordinates": [
    "34.0522,-118.2437"
  ],
  "tractGeoids": [
    "06037576403",
    "48201312300"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "addresses": [
        "350 5th Ave, New York, NY 10118",
        "233 S Wacker Dr, Chicago, IL 60606",
        "1600 Pennsylvania Ave NW, Washington, DC 20500"
    ],
    "coordinates": [
        "34.0522,-118.2437"
    ],
    "tractGeoids": [
        "06037576403",
        "48201312300"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("willed_nursery/cra-lmi-tract-screener").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "addresses": [
        "350 5th Ave, New York, NY 10118",
        "233 S Wacker Dr, Chicago, IL 60606",
        "1600 Pennsylvania Ave NW, Washington, DC 20500",
    ],
    "coordinates": ["34.0522,-118.2437"],
    "tractGeoids": [
        "06037576403",
        "48201312300",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("willed_nursery/cra-lmi-tract-screener").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "addresses": [
    "350 5th Ave, New York, NY 10118",
    "233 S Wacker Dr, Chicago, IL 60606",
    "1600 Pennsylvania Ave NW, Washington, DC 20500"
  ],
  "coordinates": [
    "34.0522,-118.2437"
  ],
  "tractGeoids": [
    "06037576403",
    "48201312300"
  ]
}' |
apify call willed_nursery/cra-lmi-tract-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,willed_nursery/cra-lmi-tract-screener"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bEDSGhf5dMzbaoCft/builds/WI0MSQceuIzFgYtz1/openapi.json
