Open data · Hugging Face
IRS 990 Parsed
The IRS published the filings. I turned them into tables you can actually query — and joined the other public files that share the same streets.
The IRS puts nonprofit tax returns on the internet as a mountain of XML. That is technically public. It is not usable. You cannot grep a ZIP of misery. You cannot ask “who else files from this address?” You cannot join a 990 officer to a Medicare NPI, a DOT census pin, an OFAC name, or an FEC committee street without first building a warehouse.
So I built one. Then I published it.
piercewetter3/irs-990-parsed is a relational extract of Form 990 / 990-EZ / 990-PF, plus the colocated public files we actually join for address research. Generated 2026-08-17. 34 tables. ~459 million rows. CC0 — derived from U.S. government records. Parquet. DuckDB will eat it for breakfast.
Fun with Geography is the browse layer: maps, clusters, the “wait, that building?” moment. This dataset is the warehouse those maps are sitting on. If the maps make you angry, take the tables home and prove it.
Why you should care
- Follow the money, not the press release. Schedule I grants, officer pay, highest-paid contractors — in tables, not PDFs.
- Same street, different costume. A 990 filer, a Medicare biller, a trucking census pin, an OFAC name, and an FEC committee can share a mailbox. The IRS will not tell you that.
Addresseswill. - Medicare is not a side quest. NPPES plus T-MSIS spend (line grain ~230M, plus cheap rollups). If your “charity” is also a billing NPI, that is the story.
- Sanctions and politics are first-class. OFAC SDN names/IDs/programs. FEC committees with a real line 1 — not just city/ZIP blobs.
- No login, no API key, no “researcher access.” Download Parquet. Query locally. Cite the primary.
If you are a journalist, this is a week of FOIAs you do not have to wait for. If you are a data person, it is a weekend project instead of a year. If you are a citizen who got tired of being told to “trust the experts,” it is the source documents, already parsed.
What is in it
| Table | Rows | What |
|---|---|---|
Addresses |
94,102,876 | Normalized streets for every owner type |
Charities |
3,625,588 | Parsed 990 / 990-EZ / 990-PF filer years |
Grants |
26,216,672 | Grants paid (Schedule I / PF) |
Officers |
4,430,012 | Officer / key-employee compensation |
Contractors |
1,096,522 | Highest-paid independent contractors |
BMF |
1,952,238 | IRS EO Business Master File, streets included |
medicare_providers |
9,606,683 | NPPES provider enumeration |
medicare_provider_spending |
230,154,264 | T-MSIS line grain (use the rollups for totals) |
dot_carriers |
4,454,157 | FMCSA motor-carrier census |
fec_committees |
6,980 | Committees with a real street |
fec_individual_contributions |
29,104,378 | City/state/ZIP grain (no street) |
sanctioned_entities |
19,199 | OFAC SDN |
Plus geocoding, grant-match name tables, HCPCS, NPPES codebooks, and the XML ingest index. Full inventory is on the dataset card. Ops/scratch tables stay local.
Addresses is polymorphic: owner_id + address_type. Types include charity, officer, contractor, grant, medicare, dot_carrier, ofac_sanction, and fec_committee. That is the join key the maps use.
How to open it
Tables with ≥ 2 million rows are a directory of ~256 MB ZSTD shards (Grants/*.parquet). Smaller tables are a single Name.parquet.
INSTALL parquet; LOAD parquet;
SELECT * FROM 'Charities.parquet' LIMIT 5;
SELECT COUNT(*) FROM 'medicare_provider_spending/*.parquet';
Or from Python: datasets.load_dataset("piercewetter3/irs-990-parsed", …). Prefer the named parquet files / globs over Hub’s auto “default” viewer — that viewer is a convenience, not the schema.
Ground rules
- CC0 / public domain. The filings were already yours. I just made them queryable.
- The IRS can be wrong. Filers lie, transpose digits, and reuse addresses. Irish True first, then Lawyer True. Check the XML.
- FEC streets are rare. Contributor / spend / op-exp rows are city+state+ZIP. Only
fec_committeeshas a real line 1. - Medicare line grain is huge. Use
medicare_provider_rollupormedicare_provider_hcpcsunless you meant to scan 230 million rows.
The dump is live and still landing on the Hub as shards replace the older single-file tables. The card and manifest.json are the source of truth for counts.
If this saves you a year, say so on X. If you find a lie in the parse, I want that more.