# IRS Form 990-PF Private Foundation Scraper - Grant Detail (`jungle_synthesizer/irs-form-990-private-foundation-scraper`) Actor

Scrape IRS Form 990-PF private-foundation filings with Part XV grant detail (recipient, purpose, amount). Look up by EIN, name, or year. Distinct from propublica-nonprofit-crawler (Form 990 public charities). For grant-research SaaS, fundraising teams, and foundation-prospect consultants.

- **URL**: https://apify.com/jungle\_synthesizer/irs-form-990-private-foundation-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Business, Other, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## IRS Form 990-PF Private Foundation Scraper — Grant Detail

Parses IRS bulk XML downloads for Form 990-PF (private foundation) filings and extracts Part XV grant detail — recipient name, address, purpose, and amount paid. Covers ~120k private foundations filing annually. Distinct from the propublica-nonprofit-crawler, which targets Form 990 public charities — 990-PF is a different schema aimed at grant-research buyers.

---

### Features

- Downloads IRS TEOS (Tax-Exempt Organization Submission) annual ZIP batches directly from the IRS open-data portal.
- Filters for 990-PF returns only and parses XML for each filing.
- Extracts foundation header data: EIN, legal name, address, filing year.
- Extracts financial summaries: total assets at year-end, total revenue, qualifying distributions, investment income, excise tax.
- Extracts all officers and trustees with title and compensation.
- Extracts Part XV grant rows: recipient name, address (US or foreign), purpose, and dollar amount.
- Three modes: browse all foundations in a year, look up specific EINs, or filter by recipient name.
- Supports state filter, foundation name filter, and minimum grant amount threshold.
- No API key, no proxy, no browser required. IRS open data is fully public.

---

### Who Uses 990-PF Data?

- **Grant writers** — Identify private foundations that have funded projects in your sector, then look up recipient names and grant purposes to write more targeted proposals.
- **Nonprofit fundraising teams** — Prospect for new funders by searching for foundations that have granted to peer organizations.
- **Foundation-prospect-research consultants** — Build bulk grant landscapes for clients: which funders are active in education/health/arts in a given state, and how much are they distributing.
- **Grant-research SaaS platforms** — Power foundation search features with structured 990-PF data without writing an IRS parser.
- **Impact investors and program officers** — Analyze grant flows across a field by pulling multi-year distributions and recipient patterns.
- **Journalists** — Follow the money from a specific foundation across years and grantees.

---

### How the IRS 990-PF Scraper Works

The IRS publishes all 990-series XML filings as bulk ZIP archives on their [Form 990 Series Downloads](https://www.irs.gov/charities-non-profits/form-990-series-downloads) page. Each annual ZIP batch contains thousands of XML files, one per return. The scraper:

1. Fetches the IRS download page to discover the ZIP URLs for the requested year.
2. Downloads each ZIP batch sequentially (batches are ~70–100 MB compressed).
3. Unpacks each XML file and checks the `ReturnTypeCd` for `990PF`.
4. Parses the IRS XML schema to extract foundation header, financials, officers, and Part XV grant groups.
5. Applies any filters (state, name, EIN, recipient, minimum grant amount) and saves matching records.

---

### Modes

#### `grants_by_year` (default)

Returns all 990-PF filings in the specified year. Use `stateFilter`, `foundationName`, and `minGrantAmount` to narrow results.

```json
{
  "mode": "grants_by_year",
  "filingYear": 2024,
  "stateFilter": "CA",
  "minGrantAmount": 100000,
  "maxItems": 50
}
````

#### `foundation_lookup`

Fetch filings for specific foundations by EIN. Scans annual batches until all requested EINs are found.

```json
{
  "mode": "foundation_lookup",
  "einList": ["13-1803509", "23-7129889"],
  "filingYear": 2024,
  "maxItems": 10
}
```

#### `grants_by_recipient`

Returns foundations that made grants to recipients matching the supplied name substring. Useful for finding all funders that have supported a specific organization.

```json
{
  "mode": "grants_by_recipient",
  "recipientName": "Red Cross",
  "filingYear": 2024,
  "maxItems": 20
}
```

***

### Output Schema

Each record represents one foundation's 990-PF filing for a given tax year.

| Field | Type | Description |
|---|---|---|
| `foundation_ein` | string | 9-digit EIN |
| `foundation_name` | string | Legal name |
| `filing_year` | number | Tax year |
| `return_type` | string | Always `990PF` |
| `foundation_address` | string | Street address |
| `foundation_city` | string | City |
| `foundation_state` | string | 2-letter state code |
| `foundation_zip` | string | ZIP code |
| `total_assets_eoy` | number | Total assets at year-end (USD) |
| `total_revenue` | number | Total revenue (USD) |
| `total_grants_paid` | number | Qualifying distributions paid (USD) |
| `investment_income` | number | Net investment income (USD) |
| `excise_tax_paid` | number | Excise tax on investment income (USD) |
| `trustee_count` | number | Number of trustees/officers |
| `trustees` | array | `name\|title\|compensation` per trustee |
| `grant_count` | number | Number of Part XV grants |
| `grants` | array | `recipient\|city, state zip\|purpose\|amount` per grant |
| `source_xml_url` | string | IRS ZIP batch URL |
| `source_file` | string | XML filename in the ZIP |
| `scraped_at` | string | ISO 8601 scrape timestamp |

***

### Notes

- **Memory**: The actor uses 2048 MB by default to handle large ZIP decompression and XML parsing. Reduce to 512 MB for small runs.
- **Timeout**: IRS ZIP batches are large. Allow at least 1 hour for a complete year scan.
- **Year coverage**: IRS publishes TEOS data for the current and prior years. Data for the most recent tax year typically appears a few months after year-end.
- **maxItems**: The default is 15 for quick validation. Increase for bulk extraction.
- **Proxy**: Not required. The IRS open-data portal is fully public.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

Please describe how you plan to use the data extracted by this crawler.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

Provide your email address so we can get in touch with you.

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

foundation\_lookup: fetch specific EINs. grants\_by\_year: all foundations in a year. grants\_by\_recipient: filter grants by recipient name.

## `filingYear` (type: `integer`):

Tax year to pull filings for (e.g. 2024). IRS publishes data within a few months of year end.

## `einList` (type: `array`):

Foundation EINs to look up (foundation\_lookup mode). Accepts 9-digit strings or XX-XXXXXXX format.

## `foundationName` (type: `string`):

Filter foundations by name substring (case-insensitive). Applies to grants\_by\_year mode.

## `recipientName` (type: `string`):

Filter grants by recipient name substring (grants\_by\_recipient mode).

## `stateFilter` (type: `string`):

Filter foundations by state code (e.g. CA, NY). Leave blank for all states.

## `minGrantAmount` (type: `integer`):

Only include foundations with total grants paid at or above this amount.

## `maxItems` (type: `integer`):

Maximum number of foundation records to return.

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

IRS open data does not require proxies.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "mode": "grants_by_year",
  "filingYear": 2024,
  "einList": [],
  "minGrantAmount": 0,
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "mode": "grants_by_year",
    "filingYear": 2024,
    "einList": [],
    "foundationName": "",
    "recipientName": "",
    "stateFilter": "",
    "minGrantAmount": 0,
    "maxItems": 15,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/irs-form-990-private-foundation-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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "mode": "grants_by_year",
    "filingYear": 2024,
    "einList": [],
    "foundationName": "",
    "recipientName": "",
    "stateFilter": "",
    "minGrantAmount": 0,
    "maxItems": 15,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/irs-form-990-private-foundation-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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "mode": "grants_by_year",
  "filingYear": 2024,
  "einList": [],
  "foundationName": "",
  "recipientName": "",
  "stateFilter": "",
  "minGrantAmount": 0,
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call jungle_synthesizer/irs-form-990-private-foundation-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "IRS Form 990-PF Private Foundation Scraper - Grant Detail",
        "description": "Scrape IRS Form 990-PF private-foundation filings with Part XV grant detail (recipient, purpose, amount). Look up by EIN, name, or year. Distinct from propublica-nonprofit-crawler (Form 990 public charities). For grant-research SaaS, fundraising teams, and foundation-prospect consultants.",
        "version": "0.1",
        "x-build-id": "mFkDJ2QW9QCOG1ZEN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/jungle_synthesizer~irs-form-990-private-foundation-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-jungle_synthesizer-irs-form-990-private-foundation-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/jungle_synthesizer~irs-form-990-private-foundation-scraper/runs": {
            "post": {
                "operationId": "runs-sync-jungle_synthesizer-irs-form-990-private-foundation-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/jungle_synthesizer~irs-form-990-private-foundation-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-jungle_synthesizer-irs-form-990-private-foundation-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "sp_intended_usage",
                    "sp_improvement_suggestions"
                ],
                "properties": {
                    "sp_intended_usage": {
                        "title": "What is the intended usage of this data?",
                        "minLength": 1,
                        "type": "string",
                        "description": "Please describe how you plan to use the data extracted by this crawler."
                    },
                    "sp_improvement_suggestions": {
                        "title": "How can we improve this crawler for you?",
                        "minLength": 1,
                        "type": "string",
                        "description": "Provide any feedback or suggestions for improvements."
                    },
                    "sp_contact": {
                        "title": "Contact Email",
                        "minLength": 1,
                        "type": "string",
                        "description": "Provide your email address so we can get in touch with you."
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "foundation_lookup",
                            "grants_by_year",
                            "grants_by_recipient"
                        ],
                        "type": "string",
                        "description": "foundation_lookup: fetch specific EINs. grants_by_year: all foundations in a year. grants_by_recipient: filter grants by recipient name.",
                        "default": "grants_by_year"
                    },
                    "filingYear": {
                        "title": "Filing Year",
                        "type": "integer",
                        "description": "Tax year to pull filings for (e.g. 2024). IRS publishes data within a few months of year end.",
                        "default": 2024
                    },
                    "einList": {
                        "title": "Foundation EINs",
                        "type": "array",
                        "description": "Foundation EINs to look up (foundation_lookup mode). Accepts 9-digit strings or XX-XXXXXXX format.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "foundationName": {
                        "title": "Foundation Name Filter",
                        "type": "string",
                        "description": "Filter foundations by name substring (case-insensitive). Applies to grants_by_year mode."
                    },
                    "recipientName": {
                        "title": "Recipient Name Filter",
                        "type": "string",
                        "description": "Filter grants by recipient name substring (grants_by_recipient mode)."
                    },
                    "stateFilter": {
                        "title": "State Filter",
                        "type": "string",
                        "description": "Filter foundations by state code (e.g. CA, NY). Leave blank for all states."
                    },
                    "minGrantAmount": {
                        "title": "Minimum Grant Amount (USD)",
                        "type": "integer",
                        "description": "Only include foundations with total grants paid at or above this amount.",
                        "default": 0
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "type": "integer",
                        "description": "Maximum number of foundation records to return.",
                        "default": 15
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "IRS open data does not require proxies."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
