ProPublica API: Get nonprofit financials
Looks up a US nonprofit by name, EIN or Nonprofit Explorer link and returns its recent Form 990 filing years with revenue, expenses, assets, liabilities, top reported pay and PDF links.
Unofficial. Not affiliated with or endorsed by ProPublica.
Inputs
Values from the run on Oct 23, 2026, shown under Output.
- State optional
state Optional two-letter state to distinguish similar names, for example CA.
Not set
- Max Years optional
max_years Maximum number of filing years, newest first, for example 5.
5 (default)
Whole number from 1 to 20.
- Organization, required
organization The nonprofit name, EIN (for example 20-0049703), or its Nonprofit Explorer link.
Wikimedia Foundation
Input as JSON
{ "organization": "Wikimedia Foundation"}Output
{ "ein": "20-0049703", "city": "San Francisco", "name": "Wikimedia Foundation Org", "state": "CA", "filings": [ { "tax_year": 2025, "filing_pdf_link": null, "filing_page_link": "https://projects.propublica.org/nonprofits/organizations/200049703#filing2025" , "total_assets_usd": 310794417, "total_revenue_usd": 205389744, "total_expenses_usd": 189748442, "total_liabilities_usd": 14244387, "highest_paid_executive_name": "Maryana Iskander", "highest_paid_executive_pay_usd": 553360 }, { "tax_year": 2024, "filing_pdf_link": "https://projects.propublica.org/nonprofits/download-filing?path=IRS%2F200049703_202406_990_2025051223428459.pdf" , "filing_page_link": "https://projects.propublica.org/nonprofits/organizations/200049703#filing2024" , "total_assets_usd": 286759938, "total_revenue_usd": 185418243, "total_expenses_usd": 178588294, "total_liabilities_usd": 15204548, "highest_paid_executive_name": "Maryana Iskander", "highest_paid_executive_pay_usd": 494079 }, { "tax_year": 2023, "filing_pdf_link": null, "filing_page_link": "https://projects.propublica.org/nonprofits/organizations/200049703#filing2023" , "total_assets_usd": 274123369, "total_revenue_usd": 180199672, "total_expenses_usd": 168305333, "total_liabilities_usd": 19152033, "highest_paid_executive_name": "Maryana Iskander", "highest_paid_executive_pay_usd": 534468 } ], "nonprofit_explorer_link": "https://projects.propublica.org/nonprofits/organizations/200049703" }Code
curl https://api.fous.com/v1/runs \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"method":"projects.propublica.org/get_nonprofit_financials","input":{"organization":"Wikimedia Foundation"}}' # Save as fous.py, then run: python3 fous.pyimport json, os, timefrom urllib.error import HTTPErrorfrom urllib.request import Request, urlopenAPI = "https://api.fous.com/v1/runs" KEY = os.environ["FOUS_API_KEY"]HEADERS = { "Authorization": f"Bearer {KEY}", "Content-Type": "application/json" ,}def call(url, body=None): data = json.dumps(body).encode() if body else None request = Request(url, data, HEADERS) try: with urlopen(request, timeout=120) as r: return r.status, json.load(r) except HTTPError as error: message = json.load(error)["error"]["message"] raise RuntimeError(message) from errorstatus, run = call(API, { "method": "projects.propublica.org/get_nonprofit_financials" , "input": { "organization": "Wikimedia Foundation" }})# 202: still going after 30 s. Ask again until it ends.while status == 202: time.sleep(2) status, run = call(f"{API}/{run['id']}")print(json.dumps(run["data"], indent=2))// Save as fous.mjs, then run: node fous.mjsconst api = "https://api.fous.com/v1/runs" ;const headers = { Authorization: `Bearer ${process.env.FOUS_API_KEY}`, "Content-Type": "application/json" ,};let response = await fetch(api, { method: "POST", headers, body: JSON.stringify({ "method": "projects.propublica.org/get_nonprofit_financials" , "input": { "organization": "Wikimedia Foundation" } }), signal: AbortSignal.timeout(120_000),});let run = await response.json();// 202: still going after 30 s. Ask again until it ends.while (response.status === 202) { await new Promise((done) => setTimeout(done, 2_000)); response = await fetch(`${api}/${run.id}`, { headers }); run = await response.json();}if (!response.ok) throw new Error(run.error.message);console.log(run.data);# Connect your agent to Fous once, over MCP (Streamable HTTP):# https://api.fous.com/mcp# Set FOUS_API_KEY first: create a key at https://app.fous.com/keys.# Claude Codeclaude mcp add \ --scope user \ --transport http fous https://api.fous.com/mcp \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}"# Codexcodex mcp add fous \ --url https://api.fous.com/mcp \ --bearer-token-env-var FOUS_API_KEY# Cursor, VS Code, Windsurf, Cline and morenpx -y add-mcp https://api.fous.com/mcp -g -n fous \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}"# Then ask your agent:# "Use Fous to run projects.propublica.org/get_nonprofit_financials# with {"organization":"Wikimedia Foundation"}"Over HTTP, the answer’s data holds the output. A run still going after 30 seconds answers 202 with its id: ask GET /v1/runs/{id} until it ends.
Schema
Input schema
{ "type": "object", "required": [ "organization" ], "properties": { "state": { "type": "string", "description": "Optional two-letter state to distinguish similar names, for example CA." }, "max_years": { "type": "integer", "default": 5, "maximum": 20, "minimum": 1, "description": "Maximum number of filing years, newest first, for example 5." }, "organization": { "type": "string", "description": "The nonprofit name, EIN (for example 20-0049703), or its Nonprofit Explorer link." } }}Output schema
{ "type": "object", "required": [ "name", "ein", "city", "state", "nonprofit_explorer_link", "filings" ], "properties": { "ein": { "type": "string" }, "city": { "type": [ "string", "null" ] }, "name": { "type": "string" }, "state": { "type": [ "string", "null" ] }, "filings": { "type": "array", "items": { "type": "object", "required": [ "tax_year", "total_revenue_usd", "total_expenses_usd", "total_assets_usd", "total_liabilities_usd", "highest_paid_executive_name", "highest_paid_executive_pay_usd", "filing_pdf_link", "filing_page_link" ], "properties": { "tax_year": { "type": "integer", "description": "Filing tax year." }, "filing_pdf_link": { "type": [ "string", "null" ], "description": "Direct filing PDF link, if available." }, "filing_page_link": { "type": "string", "description": "Nonprofit Explorer page for this filing year." }, "total_assets_usd": { "type": [ "integer", "null" ], "description": "Year-end total assets in USD, if extracted." }, "total_revenue_usd": { "type": [ "integer", "null" ], "description": "Total revenue in USD, if extracted." }, "total_expenses_usd": { "type": [ "integer", "null" ], "description": "Total expenses in USD, if extracted." }, "total_liabilities_usd": { "type": [ "integer", "null" ], "description": "Year-end total liabilities in USD, if extracted." }, "highest_paid_executive_name": { "type": [ "string", "null" ], "description": "Highest compensated listed officer or key employee, if reported." }, "highest_paid_executive_pay_usd": { "type": [ "integer", "null" ], "description": "Reported compensation, including related and other compensation, in USD." } }, "additionalProperties": false } }, "nonprofit_explorer_link": { "type": "string" } }, "additionalProperties": false}- Price
- 1 credit per completed run (1¢ with pay as you go); failed runs are free.
- Method
projects.propublica.org/get_nonprofit_financials- Returns
- name, EIN, city, state, and per filing year revenue, expenses, assets, liabilities, highest paid executive and PDF link
Use it from your agent
Give your agent this line. It reads SKILL.md, gets a Fous API key and connects the Fous MCP server. Its run then takes the method projects.propublica.org/get_nonprofit_financials with the inputs above.
Ask your agent
- How much revenue and expenses did the Red Cross report on its last few Form 990 filings?
- Pull the Form 990 history for EIN 13-1624041, showing assets and liabilities by year.
- Can you show me the highest paid executive at Habitat for Humanity International across its recent tax filings in CA?
- Get the last 3 years of financials for the Ford Foundation, including PDF links to the 990s.
- What were Doctors Without Borders USA's total assets and liabilities on its propublica nonprofit explorer filings?
See more
All ProPublica methodsFinds U.S. nonprofits by organization name, optionally filtered by state and city, with the latest reported revenue and assets.
projects.propublica.org/search_nonprofitsLooks up an organization in the IRS Tax Exempt Organization Search by name or EIN. It reports whether donations are deductible, whether the organization was automatically revoked, and its recent Form 990 filings.
irs.gov/check_charity_statusLooks up a public company by name or ticker on SEC EDGAR and returns its reported annual or quarterly financial figures from XBRL company facts. Quarterly flows are derived from year-to-date totals when no quarterly figure is filed. Unavailable figures are null.
sec.gov/get_company_financialsFinds current IRS forms, instructions and publications by number or purpose. Each result has its revision and posting dates, PDF links and a short explanation.
irs.gov/get_tax_formReturns federal obligations and distinct awards for a company or organization, including its parent and child recipient records. Covers the selected fiscal year or the last five fiscal years.
usaspending.gov/get_company_federal_awardsFinds PR Newswire press releases by company name or keywords, newest first, with optional publication date filters.
prnewswire.com/search_press_releasesSearches USAspending federal awards by keywords, awarding agency, state of performance and date across contracts, grants, loans and direct payments. Searches from October 1, 2007 onward.
usaspending.gov/search_federal_awardsFinds a public company by name or ticker in SEC EDGAR and lists its filings, newest first, optionally narrowed by filing type and filing date.
sec.gov/get_company_filings