Next free-source hunt
We check for new free data every weekday.
Datasets / Money Flows
cdr.ffiec.gov/

FFIEC Call Reports Bulk Data

Freeauth: noneProvider terms#money-flows#historical-data#time-series#flows#risk✓ verified Nov 1, 2026

FFIEC Call Reports Bulk Data

FFIEC Central Data Repository bulk Call Report files for all commercial banks, offered as tab-delimited, Excel-compatible data or XBRL. Single-period files and four-period balance-sheet, income-statement and past-due products include institution reporting values and require no key or account.

Coverage

The selector exposes quarterly single-period Call Reports from March 2001 through March 2026 on the checked date, plus four-period products. The page reported Call data updated 15 October 2026; no download rate limit is stated.

Verdict

A quarterly U.S. commercial-bank balance-sheet, income, asset-quality and funding signal for comparing institutions and banking-system conditions. Filing data arrive with reporting lag and can be amended, while field definitions and reporting populations can change by period. XBRL has received only limited instance-validation testing according to FFIEC, so the tab-delimited product is the simpler ingestion path. The public web service is a separate account-gated route; this entry covers the keyless bulk downloads.

Get the free weekly email

Free weekly email of newly verified free data. Unsubscribe by emailing us.

Use in your agent

Load the latest FFIEC Call Report bulk file into Parquet. Checked against the provider's documentation on Nov 1, 2026.

Raw skill file (/skills/ffiec-call-reports-bulk.md)Also in our MCP server: call get_ingestion_skill with {"slug": "ffiec-call-reports-bulk"}.

Access

  • No account or key is required for the interactive bulk-download form.
  • The example reproduces the form's ASP.NET postbacks and selects the latest single-period tab-delimited file.

Request

bash
curl 'https://cdr.ffiec.gov/public/PWS/DownloadBulkData.aspx'

Format

ZIP archive containing a tab-delimited Call Report file for one reporting period; the checked file had 4,336 rows and 12 columns.

Load into pandas and Parquet

Needs Python 3 with requests, pandas and pyarrow.

python
"""Latest FFIEC single-period Call Report bulk file -> pandas -> Parquet."""
import html
import io
import re
import zipfile
import requests
import pandas as pd

URL = "https://cdr.ffiec.gov/public/PWS/DownloadBulkData.aspx"
HEADERS = {"User-Agent": "SignalLabCheck/1.0"}
session = requests.Session()

def hidden_fields(text):
    pairs = re.findall(
        r'<input[^>]+type="hidden"[^>]+name="([^"]+)"[^>]+value="([^"]*)"',
        text,
    )
    return {html.unescape(name): html.unescape(value) for name, value in pairs}

text = session.get(URL, headers=HEADERS, timeout=30).text
data = hidden_fields(text)
data.update({
    "__EVENTTARGET": "ctl00$MainContentHolder$ListBox1",
    "ctl00$MainContentHolder$ListBox1": "ReportingSeriesSinglePeriod",
})
text = session.post(URL, headers=HEADERS, data=data, timeout=30).text
period_block = re.search(r'<select[^>]+id="DatesDropDownList".*?</select>', text, re.S).group()
period_id, period_label = re.search(r'<option value="([^"]+)">([^<]+)', period_block).groups()
data = hidden_fields(text)
data.update({
    "__EVENTTARGET": "ctl00$MainContentHolder$DatesDropDownList",
    "ctl00$MainContentHolder$ListBox1": "ReportingSeriesSinglePeriod",
    "ctl00$MainContentHolder$DatesDropDownList": period_id,
})
text = session.post(URL, headers=HEADERS, data=data, timeout=30).text
data = hidden_fields(text)
data.update({
    "__EVENTTARGET": "ctl00$MainContentHolder$TSVRadioButton",
    "ctl00$MainContentHolder$ListBox1": "ReportingSeriesSinglePeriod",
    "ctl00$MainContentHolder$DatesDropDownList": period_id,
    "ctl00$MainContentHolder$FormatType": "TSVRadioButton",
})
text = session.post(URL, headers=HEADERS, data=data, timeout=30).text
data = hidden_fields(text)
data.update({
    "ctl00$MainContentHolder$ListBox1": "ReportingSeriesSinglePeriod",
    "ctl00$MainContentHolder$DatesDropDownList": period_id,
    "ctl00$MainContentHolder$FormatType": "TSVRadioButton",
    "ctl00$MainContentHolder$TabStrip1$Download_0": "Download",
})
r = session.post(URL, headers=HEADERS, data=data, timeout=120)
r.raise_for_status()
with zipfile.ZipFile(io.BytesIO(r.content)) as archive:
    filename = archive.namelist()[0]
    df = pd.read_csv(io.BytesIO(archive.read(filename)), sep="\t", low_memory=False)
df.to_parquet("ffiec_call_report_latest.parquet", index=False)
print(len(df), "rows", len(df.columns), "columns", filename)

Run by us on 2026-11-01 (python 3.13.5 | pandas 3.1.0 | pyarrow 26.0.0 | requests 2.34.2). Result: 4336 rows 12 columns FFIEC CDR Call Bulk POR 03312026.txt

Limits

  • Rate limit: Not stated.
  • Single-period Call Report choices run from March 2001 through the latest available quarter on the checked page.
  • The checked March 2026 ZIP was about 5.5 MB.

Quirks

  • The download page is an ASP.NET form; preserve hidden state fields across product, period, format and download postbacks.
  • Product and period IDs are internal values, so discover the first current period option instead of hard-coding it.
  • FFIEC says the XBRL option has received limited instance-validation testing.

Terms and attribution

  • The checked FFIEC legal notice does not assign a standard data license.
  • FFIEC disclaims warranties and responsibility for accuracy, correctness and completeness.

Sources

Information and education only. Not financial, investment, legal or tax advice. Listings can be inaccurate, incomplete or out of date and are provided "as is". Free tiers, limits and licenses belong to each provider and can change, so check the provider's own terms before you rely on them. Terms & Disclaimer