CRA exam ratings scraper and analyzer — search FFIEC database, parse Performance Evaluations, identify CDFI partnership opportunities
Project description
cra-scraper 🏛️
CRA exam ratings scraper and analyzer.
Search the FFIEC CRA ratings database programmatically, parse Performance Evaluation PDFs from OCC, FDIC, and Federal Reserve, and identify banks that are prime CDFI partnership opportunities — using free public data from federal regulators.
Why cra-scraper?
The Community Reinvestment Act has been law for nearly 50 years and federal regulators publish exam results for every bank — but there's no programmatic way to access this data. Banks, CDFIs, fair lending researchers, and journalists all rely on manual PDF downloads from three different regulator websites. cra-scraper makes CRA exam data queryable in Python for the first time.
Installation
pip install cra-scraper
# For PE PDF parsing
pip install cra-scraper[pdf]
Quickstart
from crascraper import (
search_ratings, find_partnership_opportunities,
rating_distribution, build_history, find_downgrades,
summary_report,
)
# Search FFIEC ratings. Raises FFIECAccessError on failure (e.g. HTTP 403 —
# see note below); never returns placeholder/sample data.
ratings = search_ratings(bank_name="Federal")
# Compute rating distribution
dist = rating_distribution(ratings)
print(dist)
# Find banks with low ratings — CDFI partnership opportunities
opps = find_partnership_opportunities(ratings, state="IL")
print(opps)
# Track rating history per bank
histories = build_history(ratings)
for bank_id, hist in histories.items():
print(f"{hist.bank_name}: {hist.trend}")
# Identify downgrades
downgrades = find_downgrades(ratings)
print(downgrades)
# Generate a full Markdown summary report
report = summary_report(ratings)
print(report)
A note on cloud/datacenter environments
search_ratings() scrapes www.ffiec.gov, which sits behind Cloudflare.
Requests from cloud/datacenter IP ranges (Google Colab, CI runners, hosted
notebooks, most cloud VMs) are blocked with HTTP 403 at the edge. This is an
IP-reputation block, not something a User-Agent or header change can clear, and it
is not transient. When this happens the call raises FFIECAccessError with an
explanation — it does not return placeholder data. The scrape works from a
residential internet connection; run it from one to obtain the data.
Parse Performance Evaluation PDFs
from crascraper import parse_pe_pdf
pe = parse_pe_pdf("/path/to/performance_eval.pdf")
print(pe.bank_name)
print(pe.overall_rating)
print(pe.lending_test_rating)
print(pe.assessment_areas)
CRA Rating Categories
| Rating | Score | Meaning |
|---|---|---|
| Outstanding | 4 | Strong CRA performance |
| Satisfactory | 3 | Adequate CRA performance |
| Needs to Improve | 2 | Weak CRA performance |
| Substantial Noncompliance | 1 | Inadequate CRA performance |
Federal Regulators Covered
- OCC — Office of the Comptroller of the Currency (national banks)
- FRS — Federal Reserve System (state member banks)
- FDIC — Federal Deposit Insurance Corporation (state non-member banks)
Use Cases
- CDFIs identifying bank partnership opportunities (banks under regulatory pressure to improve community lending)
- Banks benchmarking their CRA performance against peers
- Researchers studying CRA effectiveness and rating trends over time
- Journalists investigating bank performance in low-income communities
- Regulators analyzing exam outcomes across asset sizes and regions
Data Sources
- FFIEC CRA Ratings Database — ffiec.gov/craratings
- OCC CRA Search — occ.gov
- FDIC CRAPES — crapes.fdic.gov
- Federal Reserve CRA — federalreserve.gov
All free public data — no API keys required.
Running Tests
PYTHONPATH=. pytest tests/ -v
28 tests across all modules.
License
MIT 2026 Jaypatel1511
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cra_scraper-0.1.1.tar.gz.
File metadata
- Download URL: cra_scraper-0.1.1.tar.gz
- Upload date:
- Size: 18.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30d29fc234b870ee7f73e7b6a356ab95f8d7913e809fa1f3c128fe2deca63f2d
|
|
| MD5 |
11164d98ae6b9af39dbe4810be9380ef
|
|
| BLAKE2b-256 |
9dc640d9be64bb9bef2219ac126ab6b8328cd32ef255990712d17dba1b6d81ab
|
Provenance
The following attestation bundles were made for cra_scraper-0.1.1.tar.gz:
Publisher:
release.yml on Jaypatel1511/cra-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cra_scraper-0.1.1.tar.gz -
Subject digest:
30d29fc234b870ee7f73e7b6a356ab95f8d7913e809fa1f3c128fe2deca63f2d - Sigstore transparency entry: 1942005236
- Sigstore integration time:
-
Permalink:
Jaypatel1511/cra-scraper@720f028eb7d28c0ebb5dd9f2398a02d511871056 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Jaypatel1511
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@720f028eb7d28c0ebb5dd9f2398a02d511871056 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cra_scraper-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cra_scraper-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e1ab684980f5a0cbbd2c4f03cd31d651b83eb03286bd7d5912b6fb2306f153f
|
|
| MD5 |
1ba52c43797d5a922f6b9ff973b1d673
|
|
| BLAKE2b-256 |
94fef17b1b80eeb73fe5ad0b06ad69c22ce59e195479b13136257b34dd32e294
|
Provenance
The following attestation bundles were made for cra_scraper-0.1.1-py3-none-any.whl:
Publisher:
release.yml on Jaypatel1511/cra-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cra_scraper-0.1.1-py3-none-any.whl -
Subject digest:
9e1ab684980f5a0cbbd2c4f03cd31d651b83eb03286bd7d5912b6fb2306f153f - Sigstore transparency entry: 1942005320
- Sigstore integration time:
-
Permalink:
Jaypatel1511/cra-scraper@720f028eb7d28c0ebb5dd9f2398a02d511871056 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Jaypatel1511
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@720f028eb7d28c0ebb5dd9f2398a02d511871056 -
Trigger Event:
push
-
Statement type: