# Grants.gov Funding Opportunities (`grit-77/grants-gov-funding-opportunities`) Actor

Grants.gov funding opportunity scraper for federal grant research. Export agency details, eligibility, source dates and available funding fields as JSON.

- **URL**: https://apify.com/grit-77/grants-gov-funding-opportunities.md
- **Developed by:** [Grit](https://apify.com/grit-77) (community)
- **Categories:** Business, Education
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / 1,000 funding opportunities

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Grants.gov Funding Opportunities

Grants.gov scraper returns federal funding opportunity records with source dates, agency data, eligibility, and available funding fields.

Grants.gov scraper uses the public source named below and writes its results to the Actor dataset.

The Actor calls the public Grants.gov search2 and fetchOpportunity APIs. No source login, API key or proxy is required. [Official API guide](https://www.grants.gov/api/api-guide).

### What you receive

Fields vary by result type and optional enrichment. The examples below are from `sample_output.json`.

| Output field | Type | Example value or excerpt from saved sample |
|---|---|---|
| `opportunityId` | string | `"361754"` |
| `opportunityNumber` | string | `"PA-FPH-27-001"` |
| `title` | string | `"Title X Family Planning Services Grants"` |
| `agency` | string | `"Office of the Assistant Secretary for Health"` |
| `agencyCode` | string | `"HHS-OPHS"` |
| `status` | string | `"posted"` |
| `documentType` | string | `"synopsis"` |
| `opportunityCategory` | string | `"Discretionary"` |
| `postedDate` | string | `"2026-04-03"` |
| `closeDate` | string | `"2027-01-11"` |
| `closeDateNotes` | string or null | `"Applications must be submitted electronically no later than 6:00 pm Eastern Time."` |
| `archiveDate` | string | `"2027-07-31"` |
| `lastUpdatedDate` | string | `"2026-07-09"` |
| `estimatedPostDate` | null | `null` |
| `estimatedCloseDate` | null | `null` |
| `estimatedCloseDateNotes` | null | `null` |
| `estimatedAwardDate` | null | `null` |
| `estimatedProjectStartDate` | null | `null` |
| `awardCeiling` | integer | `22000000` |
| `awardFloor` | integer | `200000` |
| `estimatedFunding` | integer | `257000000` |
| `numberOfAwards` | integer | `90` |
| `costSharing` | boolean | `false` |
| `description` | string | `"The Office of Population Affairs (OPA) announces the anticipated availability of funds for Fiscal Y…` |
| `eligibility` | array | `[{"code": "12"}]` |
| `eligibilityNotes` | string | `"Any public or private nonprofit entity is eligible to apply."` |
| `categories` | array | `[{"code": "HL", "description": "Health"}]` |
| `fundingInstruments` | array | `[{"code": "G", "description": "Grant"}]` |
| `assistanceListingNumbers` | array | `["93.217"]` |
| `contactName` | string | `"Office of the Assistant Secretary for Health"` |
| `contactEmail` | string | `"Eric.West@hhs.gov"` |
| `contactPhone` | string | `"240-453-883"` |
| `attachments` | array | `[{"id": 350973}]` |
| `url` | string | `"https://www.grants.gov/search-results-detail/361754"` |
| `source` | string | `"Grants.gov"` |
| `retrievedAt` | string | `"2026-10-05T14:52:55.733904+00:00"` |
| `detailsIncluded` | boolean | `true` |
| `recordStatus` | string | `"ok"` |
| `errors` | array | `[]` |

One row per unique opportunity, with four dataset views for browsing results, funding, eligibility and source diagnostics. JSON results retain nested lists; export the overview view for a compact table.

| Fields | Meaning |
|---|---|
| opportunityId, opportunityNumber, title | Official identifier, funding notice number and title |
| agency, agencyCode | Official funding agency name and exact agency code |
| status, documentType, opportunityCategory | Source status, synopsis/forecast type and opportunity category |
| postedDate, closeDate, closeDateNotes, archiveDate, lastUpdatedDate | ISO calendar dates; notes preserve source cutoff instructions |
| estimatedPostDate, estimatedCloseDate, estimatedCloseDateNotes, estimatedAwardDate, estimatedProjectStartDate | Anticipated dates from forecast records, kept separate from actual deadlines |
| awardFloor, awardCeiling, estimatedFunding, numberOfAwards, costSharing | Numeric USD funding, award count and boolean cost-sharing flag; missing values stay null |
| description | Synopsis or forecast text with HTML removed |
| eligibility, eligibilityNotes | Applicant code/description objects and extra eligibility conditions |
| categories, fundingInstruments, assistanceListingNumbers | Funding category/instrument code objects and ALN/CFDA strings |
| contactName, contactEmail, contactPhone | Public contacts published for the funding notice |
| attachments | Attachment metadata: id, fileName, description, mimeType, sizeBytes, folder; files are not downloaded |
| url, source, retrievedAt | Official opportunity page, source name and UTC retrieval timestamp |
| detailsIncluded, recordStatus, errors | Detail-fetch flag, ok/error outcome and an array of source/processing errors |

Summary mode (includeDetails=false) keeps the search identifiers, agency, status, dates and assistance listings; detailed funding/contact/eligibility values remain absent or null. A failed detail fetch retains the search summary with recordStatus=error and an identifiable error message.

### Input example

```json
{
  "keyword": "health",
  "agencies": "HHS-NIH11",
  "categories": "HL",
  "eligibilities": "06,12",
  "status": "posted",
  "includeDetails": true,
  "maxItems": 100,
  "concurrency": 3,
  "pageSize": 50
}
```

| Input | Default | Accepted values |
|---|---|---|
| keyword | Empty | Full-text query; blank browses by filters |
| agencies | Empty | Comma-separated exact official codes, e.g. NSF,HHS-NIH11 |
| categories | Empty | Comma-separated category codes from the table below |
| eligibilities | Empty | Comma-separated applicant codes; preserve leading zeros |
| status | posted | posted, forecasted, closed, archived, all |
| includeDetails | true | Boolean; fetching details has no extra event fee |
| maxItems | 100 | Integer 1–10000; cap includes error rows |
| concurrency | 3 | Integer 1–10 for simultaneous detail requests |
| pageSize | 50 | Integer 1–100; reduced when fewer rows remain under the cap |

All string inputs accept at most 500 characters. Multiple codes within a filter are combined by the source; different filter fields narrow the search together. The Actor converts comma-separated input codes to the pipe separator required by the official API. Agency filtering uses exact codes: HHS does not automatically include HHS-NIH11 or other child agencies. With status=all, results follow the source ordering and can include older closed/archived notices.

#### Category codes

| Codes | Categories |
|---|---|
| AG, AR, BC, CD, CP | Agriculture; Arts; Business/Commerce; Community Development; Consumer Protection |
| DPR, ED, ELT, EN, ENV | Disaster Prevention/Relief; Education; Employment/Labor/Training; Energy; Environment |
| FN, HL, HO, HU, ISS | Food/Nutrition; Health; Housing; Humanities; Income Security/Social Services |
| IIJ, LJL, NR, OZ, O | Infrastructure Investment/Jobs Act; Law/Justice/Legal Services; Natural Resources; Opportunity Zone Benefits; Other |
| RT, RD, ST, T | Recreation/Tourism; Regional Development; Science/Technology/Research; Transportation |

#### Eligibility codes

| Codes | Applicants |
|---|---|
| 00, 01, 02, 04, 05 | State; County; City/Township; Special District governments; Independent School Districts |
| 06, 20 | Public/state-controlled universities; Private universities |
| 07, 11 | Federally recognized tribal governments; Other tribal organizations |
| 08 | Public/Indian housing authorities |
| 12, 13 | Nonprofits with 501(c)(3); Nonprofits without 501(c)(3), excluding universities |
| 21, 22, 23 | Individuals; For-profit organizations other than small businesses; Small businesses |
| 25, 99 | Other applicants (check eligibilityNotes); Unrestricted (subject to source conditions) |

### Output example

Actual sample projection from sample_output.json; the full rows also contain descriptions, contacts, eligibility and attachment metadata.

```json
{
  "opportunityId": "361754",
  "opportunityNumber": "PA-FPH-27-001",
  "title": "Title X Family Planning Services Grants",
  "agency": "Office of the Assistant Secretary for Health",
  "agencyCode": "HHS-OPHS",
  "status": "posted",
  "postedDate": "2026-04-03",
  "closeDate": "2027-01-11",
  "awardFloor": 200000,
  "awardCeiling": 22000000,
  "estimatedFunding": 257000000,
  "detailsIncluded": true,
  "recordStatus": "ok",
  "errors": [],
  "url": "https://www.grants.gov/search-results-detail/361754"
}
```

### Pricing

Proposed event opportunity: **$0.000008 per successful saved opportunity** ($0.008 per 1,000 events). Details are included in the same event. Duplicate IDs, error rows and results excluded by maxItems produce no custom opportunity charge. Publication and pricing activation are pending; see [PRICING.md](PRICING.md) for the dated Store API comparison and configuration.

The Actor checks the available opportunity budget before searching and stops publishing when the budget is reached. Source requests already in progress may complete. Platform usage charges depend on the owner's pricing setup and are separate from this proposed event rate.

### Limits and measured validation

- Temporary network errors, HTTP 408/429 and server errors receive at most three attempts with backoff; a Retry-After wait is capped at 30 seconds. Each HTTP request times out after 30 seconds.
- Search/API-wide failures fail the run with a diagnostic row. Per-opportunity detail/normalization failures produce uncharged error rows while other opportunities continue.
- 5 health/posted opportunities were saved in 3.5 seconds inside the Actor (4.172 seconds for the Python process) on this Windows machine, 2026-10-05. This is a local observation, not a cloud performance guarantee.
- 52 passed in 1.83s (unit and live API tests); the Apify input and dataset schemas passed CLI validation. Logs are in evidence/.
- Forecast dates and posted statuses can be stale in Grants.gov. A posted status does not by itself establish that a notice is accepting applications. Read deadline notes and the linked official announcement.
- The full announcement determines eligibility and application instructions. This Actor does not assess your organization's eligibility, submit applications or download attachments.
- The Docker image and actual cloud payment settlement have not been exercised. The proposed low event rate needs a cloud cost check before publication.

### FAQ

**What limits a search?** `maxItems` caps all saved rows, including errors. `includeDetails` adds an opportunity detail request for available records.

**Do I need a proxy, login, or API key?** No. The actor uses the public Grants.gov read APIs without source authentication.

**How is it priced?** The proposed pay-per-event model charges `opportunity` for each successfully saved opportunity; detail enrichment is included. Error and duplicate rows have no custom event charge.

**How are source limits handled?** Requests use bounded concurrency and retry transient failures, including source rate responses, using `Retry-After` when available.

**How fresh are deadlines?** The actor reads Grants.gov during the run and records `retrievedAt`. Check `status`, `closeDate`, and any source notes before relying on a deadline.

**Are forecast deadlines final?** No. Forecast timing is kept in estimated date fields, separate from actual deadline fields.

### Use with AI agents / MCP

After the owner publishes this Actor, connect it through Apify's [MCP server](https://docs.apify.com/platform/integrations/mcp). Give the agent the input schema, then ask it to search by keyword, exact agency codes, categories, eligibility and status. For example: “Find posted NIH health grants with applicant codes 06 or 12; return at most 25 opportunities with official links and deadline notes.”

Agents should distinguish estimated deadlines from actual dates, preserve null values, check recordStatus/errors and cite the official url when discussing an opportunity. Do not interpret a matching applicant code as confirmation of eligibility.

### Local development

Use the existing project virtual environment; no additional packages were installed. Docker installs the two pinned dependencies in requirements.txt.

PowerShell example (from this Actor directory; prepare INPUT.json before running):

```powershell
$env:APIFY_LOCAL_STORAGE_DIR = "$PWD/storage"
C:/GritWork/earn/.venv/Scripts/python -m src
C:/GritWork/earn/.venv/Scripts/python -m pytest tests -q
apify validate-schema
```

Put input in storage/key_value_stores/default/INPUT.json. Read result rows in storage/datasets/default/ and RUN_SUMMARY in the default key-value store. Ordinary local runs call the charge method but do not make real payments; the SDK warns that charging is inactive. The controlled local billing proofs in evidence/ enable the SDK's test mode and use no Apify cloud calls.

# Actor input Schema

## `keyword` (type: `string`):

Full-text keyword search. Leave blank to browse by filters.

## `agencies` (type: `string`):

Comma-separated exact official agency codes, for example NSF,HHS-NIH11. Blank means any agency. Parent agency codes do not automatically include their subagencies.

## `categories` (type: `string`):

Comma-separated codes: HL health, ED education, ST science/research, ENV environment, EN energy, AG agriculture. Full code table is in README.

## `eligibilities` (type: `string`):

Comma-separated applicant codes. Preserve leading zeros: 06 public universities, 12 nonprofits with 501(c)(3), 23 small businesses, 00 state governments. Full code table is in README.

## `status` (type: `string`):

Official Grants.gov status. All includes posted, forecasted, closed and archived.

## `includeDetails` (type: `boolean`):

Fetch official details for funding amounts, eligibility, plain-text description, public grant contacts and attachment metadata. No extra event fee. Failed detail requests produce uncharged error rows.

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

Hard cap on saved rows, including per-opportunity error rows. Duplicates are removed before processing.

## `concurrency` (type: `integer`):

Maximum simultaneous detail requests to the official API. Publishing and charging remain serial.

## `pageSize` (type: `integer`):

Maximum opportunities requested per search page. Actual request is reduced to the remaining maxItems cap.

## Actor input object example

```json
{
  "keyword": "health",
  "agencies": "",
  "categories": "",
  "eligibilities": "",
  "status": "posted",
  "includeDetails": true,
  "maxItems": 100,
  "concurrency": 3,
  "pageSize": 50
}
```

# Actor output Schema

## `dataset` (type: `string`):

Funding opportunities from Grants.gov and per-opportunity errors.

# 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 = {
    "keyword": "health"
};

// Run the Actor and wait for it to finish
const run = await client.actor("grit-77/grants-gov-funding-opportunities").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 = { "keyword": "health" }

# Run the Actor and wait for it to finish
run = client.actor("grit-77/grants-gov-funding-opportunities").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keyword": "health"
}' |
apify call grit-77/grants-gov-funding-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,grit-77/grants-gov-funding-opportunities"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zbMdVgGRVzgVM10kH/builds/ibGTpLpk11CthuR2Z/openapi.json
