Nonprofit & IRS 990 Lookup API — EIN, Financials, NTEE avatar

Nonprofit & IRS 990 Lookup API — EIN, Financials, NTEE

Pricing

from $0.48 / 1,000 organization with 990 financials

Go to Apify Store
Nonprofit & IRS 990 Lookup API — EIN, Financials, NTEE

Nonprofit & IRS 990 Lookup API — EIN, Financials, NTEE

Search US nonprofits by name, state, NTEE or 501(c) code, or look up EINs, and get IRS Form 990 financials — revenue, expenses, assets, net assets, officer pay totals — with a multi-year history and decoded IRS codes. No API key. From $0.80 per 1,000 organizations.

Pricing

from $0.48 / 1,000 organization with 990 financials

Rating

0.0

(0)

Developer

Insight Solutions

Insight Solutions

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 hours ago

Last modified

Share

Search or look up US tax-exempt organisations and get their IRS Form 990 financials, with no API key. Give it names, keywords or EINs — optionally narrowed by state, NTEE category or 501(c) subsection — and get one row per organisation: who they are (EIN, name, address, NTEE code and category, 501(c) subsection, ruling year, foundation type, deductibility), what their latest 990 says (total revenue, expenses, assets, liabilities, net assets, contributions, program service revenue, investment income, officer compensation total, salaries), and a compact multi-year financialHistory.

The data is the IRS's own — the Exempt Organizations Business Master File and the annual 990 e-file extracts — as republished by ProPublica's Nonprofit Explorer API. Every IRS code comes back decoded next to its raw value, and every number names the IRS extract field it was read from, so an accountant can check it against the return.

No login. No cookie. No headless browser. No API key of anyone's. Organisation-level only: no officer, director or contact names are ever returned (see Privacy).

At a glance

Input — this is the Store prefill; paste it and run:

{ "queries": ["housing"], "states": ["CA"], "maxResults": 10, "includeFinancials": true,
"yearsOfHistory": 3, "filingRows": false, "maxConcurrency": 4, "maxRunSecs": 240,
"proxyConfiguration": { "useApifyProxy": true } }

Output — one organization row per organisation. The fields you will use most are ein, name, state, nteeCode, subsectionLabel, totalRevenue, totalExpenses, totalAssets, netAssets, latestFilingYear, revenueGrowth1y and financialHistory (full list under Output reference). An EIN ProPublica does not know, a search with no matches or a request that failed comes back as a free diagnostic row (ok: false, errorType, error) instead of a charge.

Price — $0.80 per 1,000 organizations with full 990 financials (+ $0.001 per run); listings, filing-year rows and organizations that have never filed a 990 with data (financialsAvailable: false — churches, most tiny groups) $0.20 per 1,000; diagnostics and empty runs free; no API key, no browser, limited permissions, works over the Apify MCP server and with x402.

From code — client.actor("insight.solutions/nonprofit-990-api").call(run_input={…}) with apify-client, or POST https://api.apify.com/v2/acts/insight.solutions~nonprofit-990-api/run-sync-get-dataset-items.


What you get

One row per organisation. This is a real row — the American National Red Cross, looked up by EIN — with filingsAvailableYears shortened:

{
"ok": true,
"rowType": "organization",
"input": "53-0196605",
"source": "propublica-nonprofit-explorer",
"sourceUrl": "https://projects.propublica.org/nonprofits/api/v2/organizations/530196605.json",
"ein": "53-0196605",
"einRaw": "530196605",
"name": "American National Red Cross",
"city": "Washington",
"state": "DC",
"zip": "20006-5310",
"address": "431 18TH ST NW",
"nteeCode": "P210",
"nteeMajorGroup": "Human Services",
"nteeCategory": 5,
"subsectionCode": 3,
"subsectionLabel": "501(c)(3)",
"profileUrl": "https://projects.propublica.org/nonprofits/organizations/530196605",
"matchedQueries": ["EIN 53-0196605"],
"rulingDate": "1938-12-01",
"rulingYear": 1938,
"foundationCode": 15,
"foundationType": "publicly supported charity (170(b)(1)(A)(vi))",
"contributionsDeductible": true,
"organizationType": "corporation",
"exemptStatus": "unconditional exemption",
"accountingPeriodMonth": 6,
"bmfTaxPeriod": "2025-06",
"bmfRevenueAmount": 3916983933,
"bmfDataSource": "current_2026_09_16",
"latestFilingYear": 2023,
"latestFilingPeriod": "2023-06",
"latestFormType": "990",
"latestFilingPdfUrl": "https://projects.propublica.org/nonprofits/download-filing?path=download990pdf_03_2024_prefixes_41-54%2F530196605_202306_990_2024031222316430.pdf",
"filingsWithDataCount": 13,
"financialsAvailable": true,
"filingsAvailableYears": [2024, 2023, 2022, 2021, "…", 2001],
"totalRevenue": 3217077611,
"totalExpenses": 2971106889,
"totalAssets": 4028321133,
"totalLiabilities": 1008326202,
"netAssets": 3019994931,
"surplus": 245970722,
"contributions": 919126379,
"programServiceRevenue": 2167924872,
"investmentIncome": 76827242,
"officerCompensationTotal": 5947262,
"otherSalariesAndWages": 1182370329,
"payrollTaxes": 87718348,
"professionalFundraisingFees": 452216,
"fundraisingNet": -849629,
"unrelatedBusinessIncome": true,
"revenueGrowth1y": 0.011,
"financialHistory": [
{ "year": 2024, "period": "2024-06", "formType": "990", "formTypeCode": 0,
"totalRevenue": null, "totalExpenses": null, "…": "…",
"pdfUrl": "https://projects.propublica.org/nonprofits/download-filing?path=IRS%2F530196605_202406_990_2025051223427881.pdf" },
{ "year": 2023, "period": "2023-06", "formType": "990", "formTypeCode": 0,
"totalRevenue": 3217077611, "totalExpenses": 2971106889, "totalAssets": 4028321133,
"totalLiabilities": 1008326202, "netAssets": 3019994931, "contributions": 919126379,
"programServiceRevenue": 2167924872, "investmentIncome": 76827242,
"officerCompensationTotal": 5947262, "otherSalariesAndWages": 1182370329, "pdfUrl": "…" },
{ "year": 2022, "period": "2022-06", "formType": "990", "formTypeCode": 0,
"totalRevenue": 3182229338, "totalExpenses": 3048182336, "totalAssets": 3872181875,
"totalLiabilities": 1171891777, "netAssets": 2700290098, "contributions": 1060031161,
"programServiceRevenue": 2018755758, "investmentIncome": 48466117,
"officerCompensationTotal": 5758532, "otherSalariesAndWages": 1119398026,
"pdfUrl": "https://projects.propublica.org/nonprofits/download-filing?path=IRS%2F530196605_202206_990_2023060221351871.pdf" }
],
"scrapedAt": "2026-09-28T17:05:12.000Z"
}

Notice that the newest year on file (2024) is a PDF only — its numbers are null and its link is there — so latestFilingYear is 2023, the newest year the IRS extract covers. That is normal; see the FAQ.

An organisation that has never filed a 990 with data — most churches, many tiny groups — still comes back as an organization row with its Business Master File identity, decoded codes and any PDF-only years, but every financial column is null. That row says financialsAvailable: false and is billed at the listing price, not the organisation price.

Two cheaper row types share the same columns:

  • listing (includeFinancials: false) — a search result with the identity fields only: ein, name, city, state, nteeCode, nteeMajorGroup, nteeCategory, subsectionCode, subsectionLabel, searchScore, rank.
  • filing (filingRows: true) — one row per filing year with data, with that year's headline numbers and the complete IRS extract in extract (all 68 fields of a Form 990), linked to its organisation by parentEin.

Three dataset views ship with it: Organizations, Financial history (filing rows) and Diagnostics.


Quick start

Look up specific organisations by EIN — any spelling works:

{ "eins": ["53-0196605", "363673599", "94 6174066"], "yearsOfHistory": 10 }

Find every large food bank in two states, with ten years of filings as rows:

{
"queries": ["food bank"],
"states": ["CA", "TX"],
"minRevenue": 5000000,
"yearsOfHistory": 10,
"filingRows": true,
"maxResults": 200
}

A cheap prospect list — identity only, no financials — of every 501(c)(3) in Wyoming classed as Environment and Animals:

{ "states": ["WY"], "nteeCategories": [3], "subsectionCodes": [3], "includeFinancials": false, "maxResults": 0 }

Input

FieldTypeDefaultWhat it does
queriesstring[][]Names or keywords. Each is one search, trimmed and de-duplicated ignoring case.
einsstring[][]Direct lookups. 53-0196605, 530196605 and 53 0196605 all work; eight digits are left-padded with 0. Anything that is not 8–9 digits becomes a free invalid-ein row and is never requested. Always fetches the financials.
statesstring[][]Two-letter state / territory codes or full names. One search per query × state; with no query, one browse per state. A value that is not a US state or territory is refused with a free invalid-input row — it never silently widens the search to the whole country.
nteeCategoriesinteger[][]ProPublica's NTEE major categories, 1–10 (see How the codes are read). One search per value.
subsectionCodesinteger[][]501(c) subsection: 3, 4, 5, 6, 7, 8, 19 … One search per value.
maxResultsinteger100Per search combination. Results come 25 to a page. 0 = everything the API will page to, bounded by maxRunSecs.
includeFinancialsbooleantrueFetch each search hit's full record → organization rows. false → listing rows, identity only, a quarter of the price.
yearsOfHistoryinteger5How many most-recent filing years go into financialHistory (and into filing rows). 1–30.
filingRowsbooleanfalseAlso return one filing row per filing year with data, inside yearsOfHistory.
minRevenue / maxRevenueinteger—A band on the latest 990's total revenue (the Business Master File figure when no 990 has data). Organisations outside it are never written and never charged; one with no revenue figure at all is outside any band. Turns includeFinancials on.
maxConcurrencyinteger4Requests in flight. Each slot has its own proxy session and waits 250 ms between its own requests.
maxRunSecsinteger240Time budget, 30–3600 s. Searches may use 60% of it when financials still have to be fetched.
proxyConfigurationobject{ "useApifyProxy": true }Datacenter proxy by default; the API also answers with no proxy.

The number of searches is queries × states × NTEE categories × subsection codes (each empty list counts as one). One run makes at most 50; beyond that the rest are listed in one free input-cap row. An organisation found by several searches — or by a search and an EIN lookup — is fetched once, pushed once, billed once, and its matchedQueries names every search that found it.

A run with nothing to look up at all (no query, no valid EIN, no usable filter) finishes FAILED before any request, with a row explaining each refused entry.


Output reference

Every row has every column; a column that does not apply to a row type is null. The second column names the IRS source field (Business Master File column or 990 extract key) or says how the value is derived.

Envelope (every row)

ColumnSourceMeaning
ok—true on paid rows, false on diagnostics.
rowType—organization, listing, filing or diagnostic.
input—The search combination (housing — state CA) or EIN (53-0196605) that produced the row.
source—Always propublica-nonprofit-explorer.
sourceUrl—The API URL that produced the row.
scrapedAt—When the row was produced, UTC.
error, errorType—On a diagnostic row, what went wrong and what to do (see below).

Identity (organization, listing; filing carries ein, einRaw, name, state)

ColumnSourceMeaning
einBMF EIN53-0196605.
einRawBMF EIN530196605 — nine digits, leading zeros kept; join on this.
nameBMF NAMEOrganisation name.
city, stateBMF CITY, STATE
zip, addressBMF ZIP, STREETOrganisation rows only.
nteeCodeBMF NTEE_CDE.g. P210.
nteeMajorGroupderivedLabel of the code's first letter.
nteeCategoryderivedProPublica's 1–10 category for that letter.
subsectionCodeBMF SUBSECTIONE.g. 3.
subsectionLabelderivedE.g. 501(c)(3).
profileUrl—The organisation's page on Nonprofit Explorer.
matchedQueries—Every search / EIN lookup in this run that found it.
searchScore, ranksearch scoreRelevance score and 1-based position in the search that first found it; null on EIN lookups.

Business Master File record (organization)

ColumnSourceMeaning
rulingDate, rulingYearBMF RULINGWhen the IRS recognised the exemption.
foundationCode, foundationTypeBMF FOUNDATIONCode and its label.
contributionsDeductibleBMF DEDUCTIBILITYtrue / false / null.
organizationTypeBMF ORGANIZATIONcorporation, trust, cooperative, partnership, association.
exemptStatusCode, exemptStatusBMF STATUSCode and its label.
affiliationCodeBMF AFFILIATIONCentral, independent or group member.
accountingPeriodMonthBMF ACCT_PDMonth the fiscal year ends.
bmfTaxPeriodBMF TAX_PERIODLatest return on the BMF, YYYY-MM.
bmfAssetAmount, bmfIncomeAmount, bmfRevenueAmountBMF ASSET_AMT, INCOME_AMT, REVENUE_AMTUSD.
bmfDataSourceProPublica data_sourceThe BMF release the record came from, e.g. current_2026_09_16.
updatedAtProPublica updated_atWhen ProPublica last updated the record (on a filing row: the extract's updated).

The latest 990 with data (organization) and each year (filing)

ColumnSourceMeaning
latestFilingYear, latestFilingPeriodextract tax_prd_yr, tax_prdNewest year with extract data.
latestFormType, latestFormTypeCodeextract formtype990 (0), 990EZ (1), 990PF (2).
latestFilingPdfUrlextract pdf_urlThe return itself.
filingsWithDataCount—Years of extract data on file.
financialsAvailable—true when at least one filing with data exists; false when none does (every financial column is then null). Decides the price: true bills organization, false bills listing.
filingsAvailableYearstax_prd_yr of both listsEvery year with a filing, data or PDF-only, newest first.
totalRevenuetotrevenuePart I line 12.
totalExpensestotfuncexpnsTotal functional expenses.
totalAssetstotassetsendEnd of year.
totalLiabilitiestotliabendEnd of year.
netAssetstotnetassetendNet assets / fund balances, end of year.
surplusderivedtotalRevenue − totalExpenses.
contributionstotcntrbgftsContributions, gifts and grants.
programServiceRevenuetotprgmrevnue
investmentIncomeinvstmntinc
officerCompensationTotalcompnsatncurrofcrOne organisation-level total; nobody is named.
otherSalariesAndWagesothrsalwages
payrollTaxespayrolltx
professionalFundraisingFeesprofndraising
fundraisingNetnetincfndrsngNet income from fundraising events.
unrelatedBusinessIncomeunrelbusinccdY → true, N → false.
revenueGrowth1yderivedLatest revenue ÷ previous year-with-data's − 1, four decimals.
financialHistoryboth filing listsUp to yearsOfHistory years, newest first: { year, period, formType, formTypeCode, totalRevenue, totalExpenses, totalAssets, totalLiabilities, netAssets, contributions, programServiceRevenue, investmentIncome, officerCompensationTotal, otherSalariesAndWages, pdfUrl }.

Filing rows only

ColumnSourceMeaning
parentEin—The organisation this year belongs to.
year, periodtax_prd_yr, tax_prd
formType, formTypeCodeformtype
pdfUrlpdf_url
extractthe whole extractEvery IRS field for that year, verbatim — 68 keys for a Form 990.

Diagnostics (always free)

invalid-ein · invalid-input (a state, NTEE or subsection value that is not one; or nothing to do) · not-found (ProPublica answered with its "Unknown Organization" placeholder) · no-results (a search matched nothing) · input-cap · rate-limited (HTTP 429 twice, from two proxy sessions) · blocked (HTTP 403 twice) · http (any other failed status, with the URL) · timeout · deadline (the time budget ran out; names what was not fetched) · budget (your maximum charge was reached) · upstream-format (a 200 whose body is not the documented shape — the row names the missing key) · actor-error.


How the codes are read

NTEE. The first letter is the major group — A Arts, Culture & Humanities; B Education; C Environment; D Animal-Related; E Health Care; F Mental Health & Crisis Intervention; G Voluntary Health Associations & Medical Disciplines; H Medical Research; I Crime & Legal-Related; J Employment; K Food, Agriculture & Nutrition; L Housing & Shelter; M Public Safety, Disaster Preparedness & Relief; N Recreation & Sports; O Youth Development; P Human Services; Q International, Foreign Affairs & National Security; R Civil Rights, Social Action & Advocacy; S Community Improvement & Capacity Building; T Philanthropy, Voluntarism & Grantmaking Foundations; U Science & Technology; V Social Science; W Public & Societal Benefit; X Religion-Related; Y Mutual & Membership Benefit; Z Unknown. ProPublica groups those letters into ten categories, which is what the nteeCategories input filters on and nteeCategory reports: 1 A · 2 B · 3 C, D · 4 E–H · 5 I–P · 6 Q · 7 R–W · 8 X · 9 Y · 10 Z. An organisation with no NTEE code has all three columns null.

Subsection. subsectionCode 1–29 reads as 501(c)(1)–501(c)(29): 3 is a public charity or private foundation, 4 social welfare, 5 labor and agricultural, 6 business league, 7 social club, 8 fraternal, 19 veterans. 40, 50, 60, 70 and 71 read as 501(d), (e), (f), (k) and (n); 92 as 4947(a)(1). Any other code is kept with a null label rather than a guessed one.

Foundation code. 0 not a 501(c)(3) · 2 private operating foundation (excise-tax exempt) · 3 private operating foundation · 4 private non-operating foundation · 9 suspense · 10 church · 11 school · 12 hospital or medical research organization · 13 organization operated for the benefit of a college or university · 14 governmental unit · 15 publicly supported charity (170(b)(1)(A)(vi)) · 16 publicly supported charity (509(a)(2)) · 17 supporting organization (509(a)(3)) · 18 public safety testing organization (509(a)(4)) · 21–24 supporting organization Type I, II, III functionally integrated, III not functionally integrated.

Deductibility. 1 → contributionsDeductible: true; 2 → false; 4 (deductible by treaty) → true; anything else → null.


What you are never charged for

  • Every diagnostic row — an invalid EIN, an EIN ProPublica does not know, a search with no matches, a refused or failed request, the time budget or your charge limit running out.
  • Organisations outside your minRevenue / maxRevenue band. The band is applied before the row is written, so they are never billed.
  • The organisation price, when there is no 990 to sell. An organisation that has never filed a 990 with data — churches, most tiny groups — costs the listing price even with includeFinancials: true. Its row says financialsAvailable: false.
  • An organisation found by several of your searches: it is fetched once and billed once.
  • The search requests themselves, and the detail request behind an organization row — it is inside the row price.
  • A run that returns nothing. A run whose input was usable but produced no row — every EIN unknown, every search empty, every organisation outside the band, the API down — finishes SUCCEEDED with zero results, a status message that says so ("0 results. N diagnostic row(s) explain why … Nothing was charged."), and bills nothing, start fee included. A run finishes FAILED only when there was nothing usable to attempt, or the Actor itself hit an error.

Pricing

EventFREEBRONZESILVERGOLD
Run started$0.001$0.001$0.001$0.001
Organization with 990 financials$0.0008$0.0008$0.00064$0.00048
Organization (search listing only)$0.0002$0.0002$0.00016$0.00012
Filing-year row$0.0002$0.0002$0.00016$0.00012

$0.80 per 1,000 organizations with full financials, $0.20 per 1,000 listings or filing-year rows, on the FREE tier. An organization row is billed at the organisation price only when at least one filing with data exists; one with no 990 extract (financialsAvailable: false) is billed as a listing. 100 organisations with five filing rows each: 100 × $0.0008 + 500 × $0.0002 + $0.001 = $0.181. A church search returning 100 organisations, 70 of them with no 990 extract: 30 × $0.0008 + 70 × $0.0002 + $0.001 = $0.039.

The run honours your maximum total charge (ACTOR_MAX_TOTAL_CHARGE_USD): it never starts a fetch the budget cannot pay for, leaves a free budget row, keeps everything already delivered and finishes successfully.


Use it from an AI agent, or from code

One JSON object in, one flat array out. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server (mcp.apify.com) and with x402 agentic payments.

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/nonprofit-990-api").call(
run_input={"eins": ["53-0196605"], "yearsOfHistory": 10}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["name"], row["latestFilingYear"], row["totalRevenue"])
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~nonprofit-990-api/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
-H 'content-type: application/json' \
-d '{"queries": ["food bank"], "states": ["TX"], "maxResults": 25}'

The Integrations tab pushes results to a webhook, Google Sheets, Slack, Zapier, Make, Snowflake or BigQuery.


FAQ

Why is the newest year sometimes a PDF with no numbers? ProPublica lists two kinds of filing: years for which the IRS has published the 990 e-file extract (numbers), and years for which only the scanned or rendered PDF is available. The newest return usually appears as a PDF months before its extract lands. That year is in filingsAvailableYears and financialHistory (with its pdfUrl and null numbers); the headline numbers and latest* columns come from the newest year with data.

Why did an organisation come back with every financial column null — and what did it cost? ProPublica holds no 990 extract for it: churches are not required to file a 990, and many tiny groups file only the 990-N e-postcard or a return that exists only as a PDF. An organisation that has never filed a 990 with data — churches, most tiny groups — costs the listing price even with includeFinancials: true. The row keeps rowType: "organization" with its identity, codes and any PDF-only years, and says financialsAvailable: false, so the price it incurred is visible on the row.

Why does a search with no results show up as a 404? Because that is how ProPublica's search answers zero results: HTTP 404 with an ordinary JSON body saying total_results: 0. The Actor reads that as "no matches" and writes one free no-results row; any other 404 is reported as an http row.

Is this the IRS's own data? Yes — the IRS Exempt Organizations Business Master File (identity, codes, ruling date, BMF financial amounts) and the IRS annual extract of 990 e-file data (the numbers), via ProPublica's republication of both.

How fresh is it? As fresh as ProPublica's last load. The stamp of the Business Master File release each record came from is copied into bmfDataSource (e.g. current_2026_09_16), and updatedAt says when ProPublica last touched the record.

Why is officerCompensationTotal a total and not a list? This Actor is organisation-level by design. The 990 extract reports officer compensation as one aggregate line, and that is what is returned. The organisation record's "in care of" field (careofname, often a person's name) and sort_name are never read or returned.

An EIN I know exists came back not-found. ProPublica answers an EIN it has no record for with a placeholder ("Unknown Organization", id 0). Newly recognised organisations can take a BMF cycle to appear; check the IRS's own search at apps.irs.gov/app/eos.


Limitations

  • 990-EZ and 990-PF extracts are smaller and use partly different field names. Every headline column whose source key is absent is null (never zero), and filing rows carry the whole extract verbatim so nothing is lost.
  • No officer, director or contact names, by design — organisation-level data only.
  • Search depth. ProPublica caps deep paging; a search stops cleanly at the first empty page even when total_results promises more.
  • One row per tax year. When an organisation has several returns for one year, the one with data wins, then the latest tax period.
  • The upstream format may change. A response that is not the documented shape is reported as a free upstream-format row naming the missing key, rather than a guess.

Privacy

Every output field is copied by name from an allow-list; no upstream object is passed through except the 990 financial extract on filing rows, which holds only financial lines, the tax period and the EIN. The careofname and sort_name fields of the organisation record are never read. The test suite walks every key of every row and fails if either appears, or if a name from the captured records does.

Data source and attribution

Data provided by ProPublica's Nonprofit Explorer API (https://projects.propublica.org/nonprofits/api), which republishes the IRS Exempt Organizations Business Master File and the IRS annual 990 extracts. Every row names its source in source and sourceUrl.

Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

Video, audio & social

News, documents & the web

Business, finance & jobs

Apps & games