# Nonprofit & IRS 990 Scraper - Charities, Officers & Leads (`scrapesage/nonprofit-990-scraper`) Actor

Scrape U.S. nonprofits & IRS Form 990 data: name, EIN, address, NTEE category, 501(c) status, multi-year revenue/expenses/assets, officers & key-employee compensation, and a lead score. Filter by state, category, subsection & revenue. B2B leads + monitoring. No browser.

- **URL**: https://apify.com/scrapesage/nonprofit-990-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 nonprofit organization records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Nonprofit & IRS 990 Scraper — Charities, Officers & B2B Leads

Turn the IRS's digitized **Form 990** filings into **ready-to-use nonprofit leads and organization intelligence**. This actor extracts every U.S. tax-exempt organization you search for — the **name, EIN, full address**, **NTEE category**, **501(c) subsection & foundation type**, **multi-year financials** (revenue, expenses, assets, liabilities, net assets, contributions, program revenue, investment income), and the **Key Employees & Officers** from the latest 990 with their **titles and compensation** — then scores each one as a lead.

A nonprofit with a real budget is a real buyer: it purchases software (CRM/fundraising/accounting/HR), insurance (D\&O, liability, benefits), banking & investment services, audits, consulting, events, marketing, and more. Its **officers and directors are the decision-makers** — and this actor gives you their names and roles.

No login, no API key, no browser — data comes straight from **ProPublica's Nonprofit Explorer** (digitized IRS Form 990 data), so it never breaks on anti-bot walls.

### Why this nonprofit scraper?

Most "nonprofit" lists are thin name-and-EIN dumps. This actor ships the **richest, most filterable record in the category**:

| Data | Typical lists | This actor |
|---|---|---|
| Name, EIN, full address | partial | ✅ |
| NTEE category + 501(c) subsection (human-readable) | code only | ✅ |
| Public charity vs **private foundation** | ❌ | ✅ |
| Latest revenue, expenses & **surplus/deficit** | sometimes | ✅ |
| Total assets, liabilities & net assets | ❌ | ✅ |
| Contributions, program revenue & investment income | ❌ | ✅ |
| **Multi-year financial history + revenue trend** | ❌ | ✅ |
| **Officers & key employees — names, titles, compensation** | ❌ | ✅ |
| Filing PDFs (links to every digitized 990) | ❌ | ✅ |
| Revenue tier + **lead score (0–100)** | ❌ | ✅ |
| Filter by state, city, ZIP, NTEE, subsection, revenue & assets | ❌ | ✅ |
| Monitoring mode — only **new / newly-filed** orgs since last run | ❌ | ✅ |

### Use cases

- **Lead generation** — find nonprofits by **state, category, subsection, and budget**, then reach the **named officers** (Executive Director, CFO, Development Director…). Proven buyers for fundraising/CRM software, accounting & audit, insurance, banking, payroll/HR, IT, and events. Sort by `leadScore` and work the biggest, best-resourced, most active first.
- **Fundraising & grant prospecting** — target **private foundations** (`organizationKind = privateFoundation`) and large public charities; size them by assets and giving capacity.
- **Financial & investment services** — filter by `minAssets` to find endowed organizations and foundations that need investment management, banking, and treasury services.
- **Market research & sector analysis** — analyze the nonprofit sector by NTEE category, geography, revenue size, and multi-year financial trend.
- **CRM enrichment & territory planning** — pull org lists by ZIP/state to build call lists, size territories, and append financials and decision-makers to existing accounts.
- **Monitoring new filings** — run on a schedule with **monitoring mode** to capture organizations that are new — or that just filed a fresh 990 — since your last run.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Nonprofit & IRS 990 Scraper**, enter **search terms** and/or **filters** (state, NTEE category, subsection, min revenue…), then click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, or XML — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "mode": "search",
    "searchTerms": ["community foundation"],
    "states": ["CA", "NY"],
    "nteeMajorGroups": ["7"],
    "only501c3": true,
    "minRevenue": 1000000,
    "includeOfficers": true,
    "maxResults": 200,
    "monitorMode": false
}
```

- **mode** — `search` (discover by keyword/filters) or `organizations` (look up specific orgs by EIN).
- **searchTerms** — keywords matched against organization names & purposes (e.g. `food bank`, `private school`, `animal rescue`). Each term runs as a separate search; leave empty to browse purely by filters.
- **eins / startUrls** — exact EINs (`53-0196605`) or ProPublica URLs (organization or search pages), auto-routed.
- **states / cities / zipCodes** — location filters (USPS state codes, exact city names, full-or-prefix ZIPs).
- **nteeMajorGroups** — broad NTEE category (Arts, Education, Environment & Animals, Health, Human Services, International, Public/Societal Benefit, Religion, Mutual/Membership, Unknown).
- **nteeCodePrefixes** — finer NTEE code prefixes per record (e.g. `B` education, `E` health, `T` foundations, `A6` museums).
- **subsectionCodes / only501c3 / organizationKind** — filter by 501(c) subsection, restrict to 501(c)(3), or split public charities vs private foundations.
- **nameQuery** — substring filter on the organization name.
- **minRevenue / maxRevenue / minAssets / minOfficerCompensation** — qualify leads by budget and staffing.
- **withOfficersOnly** — keep only orgs that report named officers (decision-maker contacts).
- **activeOnly** — only IRS-active tax-exempt organizations.
- **includeOfficers** *(default true)* — extract officers, titles & compensation from the latest 990 (the lead wedge). Turn off for faster/cheaper financials-only runs.
- **maxResults** *(default 200)* / **maxConcurrency** *(default 5)* — size and speed.
- **monitorMode / monitorKey** — emit only orgs that are new or newly-filed since the last run; use a distinct key per saved watch.

### Output

One record per organization (`recordType: "nonprofit"`):

```json
{
    "recordType": "nonprofit",
    "ein": "83-0287513",
    "name": "Wyoming Community Foundation",
    "fullAddress": "1472 N 5th St Ste 201, Laramie, WY, 82072",
    "city": "Laramie",
    "state": "WY",
    "nteeCode": "T310",
    "nteeCategory": "Philanthropy, Voluntarism & Grantmaking Foundations",
    "nteeMajorGroup": "Public & Societal Benefit",
    "subsectionCode": 3,
    "subsection": "Charitable / religious / educational (501(c)(3))",
    "is501c3": true,
    "foundationType": "Publicly supported 170(b)(1)(A)(vi)",
    "isPrivateFoundation": false,
    "exemptStatus": "Active (unconditional exemption)",
    "isActive": true,
    "rulingYear": 1989,
    "latestFiscalYear": 2023,
    "revenue": 22988814,
    "expenses": 18650122,
    "surplusOrDeficit": 4338692,
    "totalAssets": 214358745,
    "totalLiabilities": 9120044,
    "netAssets": 205238701,
    "contributions": 14210333,
    "programServiceRevenue": 0,
    "investmentIncome": 8120455,
    "revenueTier": "very large ($10M–50M)",
    "revenueTrend": "growing",
    "financials": [
        { "fiscalYear": 2023, "revenue": 22988814, "expenses": 18650122, "totalAssets": 214358745, "netAssets": 205238701 }
    ],
    "filingsCount": 11,
    "yearsCovered": "2012–2023",
    "officers": [
        { "name": "Samin Dadelahi", "title": "President & CEO", "compensation": 221011, "relatedCompensation": 0, "otherCompensation": 18420 }
    ],
    "officerCount": 23,
    "topOfficerName": "Samin Dadelahi",
    "topOfficerTitle": "President & CEO",
    "topOfficerCompensation": 221011,
    "latestFilingPdfUrl": "https://projects.propublica.org/nonprofits/download-filing?path=...",
    "filingPdfUrls": ["https://projects.propublica.org/nonprofits/download-filing?path=..."],
    "profileUrl": "https://projects.propublica.org/nonprofits/organizations/830287513",
    "leadScore": 92,
    "scrapedAt": "2026-06-20T03:30:00.000Z"
}
```

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it weekly/monthly with **monitoring mode** to capture only new or newly-filed organizations as fresh leads.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, email sequence) the moment a run finishes.

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/nonprofit-990-scraper').call({
    mode: 'search',
    searchTerms: ['community foundation'],
    states: ['CA'],
    minRevenue: 1000000,
    maxResults: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} nonprofit leads`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new nonprofit leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored watch finds new organizations.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find California environmental nonprofits with over $1M revenue and list their executive directors" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **U.S. B2B & government-data lead stack**:

- **[US Business Formation Scraper](https://apify.com/scrapesage/us-business-formation-scraper)** — newly-registered LLCs & companies (fresh formation leads).
- **[SBA Loan Leads Scraper](https://apify.com/scrapesage/sba-loan-leads-scraper)** — SBA 7(a) & 504 borrowers — financed, growing small businesses.
- **[USAspending Scraper](https://apify.com/scrapesage/usaspending-scraper)** — federal awards, contractors & recipient leads.
- **[US Federal Grants Scraper](https://apify.com/scrapesage/us-federal-grants-scraper)** — Grants.gov, NIH & NSF funding.
- **[GSA eLibrary Scraper](https://apify.com/scrapesage/gsa-elibrary-scraper)** — federal Schedule contractors & B2B leads.
- **[FEC Campaign Finance Scraper](https://apify.com/scrapesage/fec-campaign-finance-scraper)** — donors, PACs & committees.
- **[Financial Advisor Scraper](https://apify.com/scrapesage/financial-advisor-scraper)** — FINRA + SEC advisors & firms.
- **[TaxBuzz Scraper](https://apify.com/scrapesage/taxbuzz-scraper)** — tax preparers, CPAs & accountant leads.

### Tips

- **Reach the people, not just the org.** Keep `includeOfficers` on — the officer names, titles, and compensation are what turn a filing into a workable lead.
- **Qualify by budget.** Use `minRevenue` / `minAssets` to focus on well-resourced organizations, and sort by `leadScore`.
- **Target a category fast.** Combine `nteeMajorGroups` (e.g. Health, Education) with `nteeCodePrefixes` (e.g. `T` for foundations) and `states`.
- **Grantmakers vs operators.** Set `organizationKind` to `privateFoundation` to find funders, or `publicCharity` for operating nonprofits.
- **Recurring monitoring.** Combine [Schedules](https://docs.apify.com/platform/schedules) with `monitorMode` and a distinct `monitorKey` per saved watch.

### FAQ

**Where does the data come from?** [ProPublica's Nonprofit Explorer](https://projects.propublica.org/nonprofits/), which digitizes the IRS's released Form 990 data (2.2M+ tax-exempt organizations, filings back to 2001). This actor searches, fetches, parses, normalizes, and scores it.

**How fresh is it?** The IRS releases digitized 990 data on a rolling basis and ProPublica updates continuously. Each record includes `latestFiscalYear` and `dataUpdatedAt` so you always know the vintage. Run with `monitorMode` on a schedule to capture new and newly-filed organizations automatically.

**Is there phone/email?** Form 990 data is firmographic and financial: organization name, full mailing address, financials, and the named officers (decision-makers). It does not include direct phone or email — those are easy to append with an email/phone enrichment tool or your CRM using the org name, address, and officer names provided.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How much does a run cost?** You pay per organization record returned (no start fee) — a lower price for the financial record and a little more when officers are included. A few hundred filtered leads costs only a few cents of platform compute plus the per-record price.

**Is this legal?** This actor collects publicly available IRS Form 990 data (republished by ProPublica). You are responsible for using the data in compliance with applicable laws and the source's terms.

**A field is null — why?** Some organizations genuinely don't report a value (e.g. very small 990-N/990-EZ filers have no officer table or extracted financials). Fields are `null` only when the source doesn't provide them.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `mode` (type: `string`):

<b>Search</b> = discover organizations by keyword, state, NTEE category and 501(c) subsection (the usual lead-gen flow). <b>Organizations</b> = look up specific orgs by EIN (or paste ProPublica URLs in Start URLs).

## `searchTerms` (type: `array`):

Keywords to search organization names & purposes, e.g. <code>food bank</code>, <code>private school</code>, <code>animal rescue</code>, <code>community foundation</code>. Each term runs as a separate search. Leave empty to browse purely by the filters below (state / category / subsection).

## `eins` (type: `array`):

Employer Identification Numbers to look up directly, e.g. <code>53-0196605</code> or <code>530196605</code>. Used when Mode = Specific organizations.

## `startUrls` (type: `array`):

Paste ProPublica Nonprofit Explorer URLs — organization pages (<code>.../nonprofits/organizations/530196605</code>) or search URLs (<code>.../nonprofits/search?q=...\&state\[id]=CA</code>). They are auto-routed.

## `states` (type: `array`):

Filter by the organization's state — two-letter USPS codes, e.g. <code>CA</code>, <code>TX</code>, <code>NY</code>. Applied as a server-side search filter and verified on each record. Leave empty for all states.

## `cities` (type: `array`):

Filter by city (case-insensitive, exact city name), e.g. <code>Los Angeles</code>, <code>Chicago</code>.

## `zipCodes` (type: `array`):

Filter by ZIP — full ZIP (<code>90012</code>) or a prefix (<code>900</code> matches 900xx).

## `nteeMajorGroups` (type: `array`):

Filter by the org's broad NTEE category. Applied as a server-side search filter.

## `nteeCodePrefixes` (type: `array`):

Finer filter on the full NTEE code (checked per record), e.g. <code>B</code> = education, <code>E</code> = health, <code>P</code> = human services, <code>A6</code> = museums, <code>T</code> = philanthropy/foundations.

## `subsectionCodes` (type: `array`):

Filter by IRS 501(c) subsection. Applied as a server-side search filter.

## `organizationKind` (type: `string`):

Narrow 501(c)(3)s to <b>public charities</b> (operating nonprofits — the usual lead target) or <b>private foundations</b> (grantmakers — useful for fundraising teams).

## `only501c3` (type: `boolean`):

Only return 501(c)(3) charitable organizations (the most common and most-targeted type).

## `nameQuery` (type: `string`):

Only return organizations whose name contains this text (case-insensitive).

## `minRevenue` (type: `integer`):

Only orgs with latest-year total revenue at or above this (a proxy for budget / buying power). E.g. <code>1000000</code> for $1M+.

## `maxRevenue` (type: `integer`):

Only orgs with latest-year total revenue at or below this.

## `minAssets` (type: `integer`):

Only orgs with latest-year total assets at or above this.

## `minOfficerCompensation` (type: `integer`):

Only orgs whose highest-paid officer earns at least this much — a strong signal of a well-resourced, professionally-staffed organization. Requires officer extraction (on by default).

## `withOfficersOnly` (type: `boolean`):

Skip organizations that don't report Key Employees & Officers on their latest 990 (typically very small 990-N/990-EZ filers). Keeps only records with decision-maker contacts.

## `activeOnly` (type: `boolean`):

Only organizations with an active IRS tax-exempt status.

## `includeOfficers` (type: `boolean`):

Extract the Key Employees & Officers (names, titles, compensation) from each org's latest Form 990. This is the decision-maker lead wedge. Turning it off makes runs faster and cheaper (financial firmographics only).

## `maxResults` (type: `integer`):

Maximum number of organization records to return in this run.

## `maxConcurrency` (type: `integer`):

How many organizations to fetch in parallel. 5 is a good, polite default.

## `monitorMode` (type: `boolean`):

Remember which organizations (and filing years) were already returned in a named key-value store and emit ONLY orgs that are new — or that have filed a newer 990 — since the last run. Each is tagged <code>monitorEvent: "new"</code> or <code>"updated"</code>. Run on a Schedule to capture fresh nonprofits / fresh financials as leads. Works alongside Apify Schedules (the schedule starts the run; monitoring decides what's new).

## `monitorKey` (type: `string`):

Names the memory used by monitoring mode. Use a distinct key per saved watch (e.g. per state/category) so different monitors don't share state.

## `proxyConfiguration` (type: `object`):

Proxy used for requests to ProPublica. Apify Proxy (datacenter) is recommended and on by default; the actor automatically rotates sessions and escalates to US residential if needed.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "food bank"
  ],
  "organizationKind": "any",
  "only501c3": false,
  "withOfficersOnly": false,
  "activeOnly": false,
  "includeOfficers": true,
  "maxResults": 200,
  "maxConcurrency": 5,
  "monitorMode": false,
  "monitorKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped nonprofit / Form 990 records as JSON items in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "food bank"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/nonprofit-990-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["food bank"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/nonprofit-990-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "food bank"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapesage/nonprofit-990-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/nonprofit-990-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/u1dSheRgvNUGNag3F/builds/CnJ01fTAbPklk9hKk/openapi.json
