DEV Community

Devil Scrapes
Devil Scrapes

Posted on

The FDIC's API returns data.data, and ASSET is in thousands

Quick answer

The FDIC's BankFind Suite API is public, keyless, and will answer this from your terminal right now:

GET https://api.fdic.gov/banks/institutions
    ?filters=STNAME:Texas%20AND%20ACTIVE:1
    &fields=CERT,NAME,CITY,STALP,ACTIVE,ASSET
    &limit=100
Enter fullscreen mode Exit fullscreen mode

That is the FDIC Bank Data Scraper — one flat row per FDIC-insured institution, filtered by state, active status, minimum assets, or a name fragment.

The API is free and well-maintained. What it is not is flat, and the shape it returns is where everybody writes the same 80 lines of glue.

data.data is not a typo 🪆

Every record comes back double-wrapped:

{
  "meta": { "total": 421, "parameters": {} },
  "data": [
    { "data": { "CERT": "10327", "NAME": "Citizens State Bank", "ASSET": 73820 },
      "score": 1 }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The outer data is the array. Each element has its own data object holding the actual record, alongside a score field that is search-relevance metadata, not bank data. So the path to a bank's name is data[i].data.NAME, and a client written against the obvious data[i].NAME gets undefined for every field while the request itself looks perfectly successful.

That is the annoying failure: not an error, just a dataset full of nulls. We unwrap it once and hand you cert, name, city, state, active, total_assets_thousands at the top level.

While you are in there: ASSET is in thousands of dollars. A bank showing 73820 has $73.8 million in assets, not $73,820. We name the field total_assets_thousands rather than assets, because a unit that lives only in the documentation eventually ends up wrong in somebody's model.

The paging is real but undocumented 📄

There is no cursor and no next link. You page with offset and limit, and the only way to know when to stop is meta.total from the first response — which means your first request has to be the one that tells you how big the job is.

There is also no full-text search. filters is a structured expression language (STNAME:Texas AND ACTIVE:1), not a search box. Anything resembling "find banks with 'First National' in the name" is a client-side filter you write yourself over a broader query. We do that for you and expose it as a plain name_contains input.

Verified against the source, not against ourselves 🔍

A row existing is not evidence the row is right. Our smoke test takes a record out of the dataset and re-fetches it independently: FDIC certificate 10327 comes back as Citizens State Bank of Luling, assets 73,820 (thousands). Matched at the source before we shipped it.

We check this deliberately, because a scraper that returns confidently-wrong data is worse than one that returns nothing — an empty run is obviously broken, and a plausible wrong row is not.

One bad financials lookup should not cost you the run 🛟

Enable include_financials and the Actor makes a second call per institution for its most recent quarterly figures. Some certificates have no financials on file, and some of those calls simply fail.

If that is fatal, one gap in a list of four hundred banks destroys the whole run — and the customer still pays the start fee. We skip the financials for that institution with a logged warning and land the institution row anyway.

This is the single most common defect shape we find in our own fleet: a recoverable per-item error taking down an entire run. It is the first thing worth checking in anything you build against a paged API.

A zero-match search also finishes as a success with a clear status message. A filter combination that matches nothing is a correct answer to a narrow question, not a failure.

What a row looks like

cert, name, city, state, active, total_assets_thousands, plus the institution metadata FDIC carries — and, optionally, a sibling financials row per institution. Typed and validated, with real nulls where the FDIC has no value rather than empty strings.

Who this is for 🎯

  • Fintech and banking-as-a-service — build a partner-bank shortlist by state and asset size.
  • Compliance — an institution list with certificate numbers that reconcile against FDIC's own records.
  • Sales and BD — community banks under an asset ceiling, by geography.
  • Analysts — a clean base table of insured institutions for a market map.

The honest limitations 🚧

  • Institutions and their headline financials. Not full call-report detail — that is a different FDIC dataset.
  • name_contains filters client-side over a structured query, so a very broad name search means a broader fetch underneath.
  • Assets are as-reported in thousands, on the FDIC's quarterly cadence — not real time.

Pricing

$0.20 per run plus $0.002 per row — $2.20 per 1,000. Pay for rows that land.

FDIC Bank Data Scraper on Apify


Built by Devil Scrapes. We unwrap the envelope, walk the undocumented paging, keep the units honest, and never let one missing record kill your run.

Top comments (0)