# HMDA Mortgage Lending Data - Loan-Level Records (`j0401/hmda-mortgage-lending`) Actor

The CFPB's public HMDA loan-level register (2018-2025): lender LEI, county, census tract, loan amount, interest rate, action taken, loan type and purpose, race, ethnicity, sex, denial reasons and tract demographics. One state or county slice per query; search or aggregate by a chosen dimension.

- **URL**: https://apify.com/j0401/hmda-mortgage-lending.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 hmda mortgage lending records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## HMDA Mortgage Lending Data - Loan-Level Records

Every loan application record in the public HMDA register, 2018-2025: **12,043,253 records for 2024 alone** across all 50 states, DC and the territories HMDA covers. One state or county slice per query. Search by lender, state, county, census tract, action taken, loan type or purpose, race, ethnicity, sex, denial reason, amount or rate - or roll the slice up by a chosen dimension.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold**

Pay only for the records you receive. A 50-record search costs $0.0025 at the entry tier.

### What is in a record

One row per application record, with the HMDA decision, loan, cost, property, borrower-profile and tract fields:

- **Geography** - state, county FIPS, 11-digit census tract, MSA/MD
- **Lender** - 20-character LEI
- **Decision** - action taken (originated, approved not accepted, denied, withdrawn, incomplete, purchased, preapproval outcomes), denial reasons 1-4, preapproval
- **Loan** - type (conventional / FHA / VA / USDA), purpose (purchase, improvement, refinance, cash-out), lien status, amount, LTV, interest rate, rate spread, HOEPA status, term, intro rate period, negative amortization, interest-only, balloon, other non-amortizing features
- **Costs** - total loan costs, points and fees, origination charges, discount points, lender credits
- **Property** - value, construction method, occupancy type, total units, manufactured-home flags, multifamily affordable units
- **Borrower profile** - derived race, ethnicity and sex (including joint and not-available categories), age band, age above 62, income, debt-to-income band, credit score model and AUS results 1-5
- **Tract context** - tract population, minority population percent, MSA median family income, tract-to-MSA income percentage, owner-occupied units, 1-4 family homes, median housing age

No applicant names and no street addresses: geography stops at census tract.

### Search

```json
{
  "year": 2024,
  "state": "TX",
  "county": "48201",
  "actionTaken": "1",
  "loanType": "1",
  "maxResults": 500
}
```

Returns originated conventional loans in Harris County, Texas for 2024.

Filters the export applies directly: `actionTaken`, `loanType`, `loanPurpose`, `constructionMethod`, `totalUnits`. Additional filters applied to the stream: `lenderId` (exact LEI), `censusTract`, `race`, `ethnicity`, `sex`, `denialReason`, `minAmount`, `maxAmount`, `minInterestRate`, `maxInterestRate`.

`totalMatched` is the authoritative count when the query covers a whole state-year with no extra filters. For narrower queries it reports the matched count when the slice was read to the end, and is left blank when the run stopped at `maxResults` before the end.

### Aggregate

Set `mode: "aggregate"` and pick a `groupBy`:

```json
{
  "year": 2024,
  "state": "CA",
  "mode": "aggregate",
  "groupBy": "race",
  "actionTaken": "1"
}
```

Returns one row per group with `groupCount` and `groupAmount` (total loan dollars) plus `totalMatched`. Dimensions: `actionTaken`, `loanType`, `loanPurpose`, `race`, `ethnicity`, `sex`, `stateCode`, `countyCode`, `lenderLei`, `denialReason1`, `applicantAge`, `dwellingCategory`, `purchaserType`, `constructionMethod`, `totalUnits`, `activityYear`.

A rollup that would exceed 5,000 groups fails loudly instead of returning a truncated list.

### Coverage and freshness

2018 through 2025, published by the CFPB from the HMDA data submitted by lenders each spring.

| Year | Records (national) |
|---|---|
| 2024 | 12,043,253 |

Counts are checked against a stable per-year floor before any download; a collapsed or restructured export fails the run instead of returning partial data.

### Notes

- The export selects a state or a county slice. For multi-state work, run one query per state.
- Coded filters use HMDA codes: action taken 1-8, loan type 1-4, loan purpose 1 / 2 / 31 / 32 / 4 / 5, construction method 1-2.
- Amount and interest-rate bounds are applied while streaming, so a very selective query still reads the state slice once. Keep `maxResults` modest for narrow filters.

# Actor input Schema

## `year` (type: `integer`):

HMDA activity year, 2018-2025.

## `state` (type: `string`):

Two-letter USPS state code. Required: the API only exports a state or county slice. The default query uses Delaware.

## `county` (type: `string`):

Optional 5-digit FIPS county code (e.g. "48201" for Harris County, TX). Overrides state as the slice selector.

## `mode` (type: `string`):

search = matching loan records. aggregate = one row per group. Leave blank: aggregate when groupBy is set, otherwise search.

## `groupBy` (type: `string`):

Dimension for mode=aggregate. Defaults to loanPurpose.

## `maxResults` (type: `integer`):

Records to deliver in search mode (default 50, max 25000).

## `actionTaken` (type: `string`):

1 originated, 2 approved not accepted, 3 denied, 4 withdrawn, 5 incomplete, 6 purchased loan, 7 preapproval denied, 8 preapproval approved not accepted.

## `loanType` (type: `string`):

1 Conventional, 2 FHA, 3 VA, 4 USDA/RHS.

## `loanPurpose` (type: `string`):

1 home purchase, 2 home improvement, 31 refinancing, 32 cash-out refinancing, 4 other, 5 not applicable.

## `constructionMethod` (type: `string`):

1 site-built, 2 manufactured home.

## `totalUnits` (type: `string`):

One or more of 1, 2, 3, 4, 5-24, 25-49, 50-99, 100-149, >149 (comma separated).

## `lenderId` (type: `string`):

Exact 20-character lender LEI, e.g. "254900NZOY3XB2DNSZ34". Applied while streaming.

## `censusTract` (type: `string`):

11-digit census tract code. Applied while streaming.

## `race` (type: `string`):

Exact derived race label, e.g. "Black or African American", "White", "Asian", "Joint", "Race Not Available".

## `ethnicity` (type: `string`):

Exact derived ethnicity label, e.g. "Hispanic or Latino", "Not Hispanic or Latino".

## `sex` (type: `string`):

Exact derived sex label: "Male", "Female", "Joint", "Sex Not Available".

## `denialReason` (type: `string`):

Denial reason code 1-10 (matched against denial_reason 1-4).

## `minAmount` (type: `number`):

Minimum loan amount in dollars (0 = no minimum).

## `maxAmount` (type: `number`):

Maximum loan amount in dollars (0 = no maximum).

## `minInterestRate` (type: `number`):

Minimum interest rate percent (0 = no minimum).

## `maxInterestRate` (type: `number`):

Maximum interest rate percent (0 = no maximum).

## Actor input object example

```json
{
  "year": 2024,
  "state": "DE",
  "maxResults": 50,
  "minAmount": 0,
  "maxAmount": 0,
  "minInterestRate": 0,
  "maxInterestRate": 0
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

HMDA loan records or aggregate rows - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/hmda-mortgage-lending").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/hmda-mortgage-lending").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 '{}' |
apify call j0401/hmda-mortgage-lending --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/hmda-mortgage-lending"
        }
    }
}
```

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/vBi7uRkL8l3cuQRtM/builds/biahzv5cK4VEDvNVh/openapi.json
