# Grants.gov Federal Grant Opportunities Monitor (`brightish_ascent/grants-gov-opportunities-monitor`) Actor

Unofficial; not affiliated with Grants.gov or HHS. Search and monitor U.S. federal grant opportunities (forecasts and open NOFOs) from the official Grants.gov API: deadlines, award amounts, eligibility. Only new and changed opportunities.

- **URL**: https://apify.com/brightish_ascent/grants-gov-opportunities-monitor.md
- **Developed by:** [Michael Rice](https://apify.com/brightish_ascent) (community)
- **Categories:** Business, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 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/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 Federal Grant Opportunities Monitor

Unofficial tool. Not affiliated with or endorsed by Grants.gov, the U.S. Department of Health and Human Services, or any federal agency.

Find and track U.S. federal funding opportunities straight from the **official Grants.gov public API**: forecasts of upcoming programs and notices of funding opportunity (NOFOs) that are open now. Each row has the deadline, days left, award ceiling and floor, estimated total funding, expected number of awards, eligible applicant types and a plain-text description. No login, no API key, no proxies. In monitor mode it returns only opportunities that are **new**, or whose status, deadline, document type or title **changed** since your last run, so a daily schedule becomes a funding update feed for nonprofits, universities, local governments, tribes, small businesses and grant consultants.

### What you get

- **One row per opportunity:** opportunity ID and number, title, agency, status (forecasted, posted, closed, archived), posting date, close date, days until close, Assistance Listing (CFDA) numbers and the Grants.gov link.
- **Details** (`includeDetails`, on by default): award ceiling and floor, estimated total funding, expected number of awards, cost sharing, funding instruments, funding categories, eligible applicant types, eligibility notes, description (first 4,000 characters), estimated post and close dates for forecasts, fiscal year, archive date, last-updated date, version and `moreInfoUrl` (the agency's own link for the opportunity, when given). If Grants.gov fails to return details for a row, that row still comes back with the basic fields and `detailsUnavailable: true`.
- **Filters:** keywords, status, agency (a top-level code like `HHS` includes all sub-agencies), eligible applicant type, funding category, funding instrument, Assistance Listing numbers and "posted in the last N days".
- **Sorting:** newest posted, closing soonest, or keyword relevance.
- **Monitor mode** (`onlyNewSinceLastRun`):
  - The first run is a baseline. It returns up to `maxItems` of the newest matches and remembers every current match (up to the 5,000 newest).
  - Later runs return only `new` opportunities and `changed` ones (status, close date, forecast-to-posted, title or opportunity number). Changed rows carry `previous` and `changedFields`.
  - Closures show up as a `changed` status only when `closed` is among the selected statuses. With the default (forecasted and posted), an opportunity that closes simply drops out of the results.
  - Monitor mode scans at most the 5,000 newest matches. Forecasted and posted together are usually well under that, but closed or archived can match tens of thousands, so add keywords, agencies or other filters when you select them. If the cap is hit, `truncated` is `true` and the `truncationNote` says older matches aren't tracked.
- **Exact `truncated` flag.** It's `true` only when more matching rows existed than were delivered. In monitor mode, rows cut by `maxItems` or the run's max charge are delivered on the next run (rows beyond the 5,000-match scan cap are not).
- **Compact output** (`outputFormat: "compact"`) for spreadsheets and AI agents.

### Input example

```json
{
  "keywords": "climate resilience",
  "opportunityStatuses": ["forecasted", "posted"],
  "eligibilities": ["12"],
  "maxItems": 20,
  "includeDetails": true
}
```

- **Agency codes:** use the codes Grants.gov shows, such as `NSF`, `HHS`, `USDA`, `DOE`, `EPA`, `HHS-NIH11` or `USDA-NIFA`.
- **Eligibility codes:** for example `12` = 501(c)(3) nonprofits, `23` = small businesses, `06` = public universities, `00` = state governments, `07` = federally recognized tribes. The input form lists them all.
- **Daily updates:** set `onlyNewSinceLastRun: true`, pick your filters and add a schedule. Changing the filters starts a new baseline.

### Output example (full row, shortened)

```json
{
  "opportunityId": "358004",
  "opportunityNumber": "25-531",
  "title": "Cybersecurity Innovation for Cyberinfrastructure (CICI)",
  "agencyCode": "NSF", "agencyName": "U.S. National Science Foundation",
  "status": "posted", "documentType": "synopsis",
  "postedDate": "2025-01-04", "closeDate": "2027-01-20", "daysUntilClose": 88,
  "assistanceListings": ["47.075"],
  "url": "https://www.grants.gov/search-results-detail/358004",
  "awardCeiling": 1200000, "awardFloor": null, "estimatedTotalFunding": 12000000, "expectedNumberOfAwards": 20,
  "costSharingRequired": false, "fundingInstruments": ["Grant"],
  "fundingCategories": ["Science and Technology and other Research and Development"],
  "eligibleApplicants": ["Others (see text field entitled \"Additional Information on Eligibility\" for clarification)"],
  "eligibilityNotes": "...", "description": "...",
  "archiveDate": "2027-02-19", "lastUpdated": "2026-10-05", "version": 8,
  "moreInfoUrl": "https://www.nsf.gov/funding/opportunities/...",
  "updateType": null, "changeHash": "..."
}
```

The **run summary** is saved to the `OUTPUT` record in the key-value store: row count, charged count, total matches, rows scanned, new/changed counts, request stats and the exact request bodies sent to Grants.gov.

### Good to know

- **Amounts:** Grants.gov uses 0 or "none" when an agency doesn't state an amount. Those come back as `null`, not 0.
- **Dates** are calendar dates as Grants.gov publishes them (no time zone). `daysUntilClose` counts to the end of the close date in UTC. Always confirm the deadline and time in the official notice.
- **Privacy:** the agency contact fields (name, email, phone) are never output. In the description and eligibility text, email addresses (including encoded and `[at]` forms) are replaced with `[email removed]` and US-format phone numbers with `[phone removed]`. Other contact details written in prose, such as a person's name, may remain. Use the Grants.gov link for contacts.
- **Monitor state** is kept per filter set in a named key-value store (`grants-gov-opportunities-monitor-state`) in your own Apify account.
- **Request pacing:** at least 250 ms between Grants.gov requests, retries on 429/5xx errors, and a cap of 1,200 requests per run. Details cost one extra request per row; turn `includeDetails` off for faster, lighter runs.
- **Coverage:** whatever Grants.gov publishes through its public search API. Some agencies also post opportunities only on their own sites, and those aren't included.

### Use with AI agents / MCP

This Actor works as a tool through Apify's MCP server (`https://mcp.apify.com`). Ask an agent things like "find open NSF or DOE grants for small businesses closing in the next 60 days". Use `outputFormat: "compact"` and a small `maxItems` to keep answers short.

### Pricing

Pay per event: a small charge per Actor start plus one charge per dataset row (`opportunity`). The run's maximum total charge is respected, and rows beyond it are not pushed. Runs that find nothing new cost only the start charge.

### FAQ

**Where does the data come from?** The documented Grants.gov public REST API (`search2` and `fetchOpportunity`), which Grants.gov says needs no login or key.

**Is this grant-writing or legal advice?** No. It's a search and monitoring tool. Read the full notice on Grants.gov before applying.

**Can I monitor several topics?** Yes. Create one saved task or schedule per filter set; each keeps its own monitor state.

Support: digitalpromohub.support@gmail.com

# Actor input Schema

## `keywords` (type: `string`):

Free-text search across opportunity titles, numbers and descriptions, the same as the Grants.gov search box (e.g. "broadband", "mental health", "STEM education"). Leave empty to match everything that fits the other filters.

## `opportunityStatuses` (type: `array`):

forecasted = agency announced an upcoming opportunity (estimated dates); posted = open for applications now; closed / archived = past deadline. Default: forecasted and posted.

## `agencies` (type: `array`):

Grants.gov agency codes. A top-level code (e.g. "HHS", "USDA", "DOE", "NSF", "EPA") includes all its sub-agencies; a sub-agency code (e.g. "HHS-NIH11", "USDA-NIFA", "DOC-NIST") narrows to that office. Up to 25. Empty = all agencies.

## `eligibilities` (type: `array`):

Keep opportunities open to ANY of these applicant types (Grants.gov codes). Empty = any applicant type.

## `fundingCategories` (type: `array`):

Keep opportunities in ANY of these Grants.gov funding activity categories. Empty = all categories.

## `fundingInstruments` (type: `array`):

Grant, cooperative agreement, procurement contract or other. Empty = all.

## `assistanceListings` (type: `array`):

Optional Assistance Listing numbers like "93.837" or "47.076" (up to 10; one Grants.gov query each, results merged and deduplicated).

## `postedWithinDays` (type: `string`):

Only opportunities posted in the last N days (Grants.gov's own posted-date filter). Leave unset for any posting date.

## `sortBy` (type: `string`):

newest = most recently posted first; closingSoonest = nearest application deadline first; relevance = Grants.gov keyword relevance. Ignored in only-new mode.

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

Adds award ceiling/floor, estimated total funding, expected number of awards, cost sharing, funding instruments and categories, eligible applicants, eligibility notes, description (first 4,000 characters), forecast dates and last-updated date. One extra Grants.gov request per row. Agency contact fields (name, email, phone) are never output; emails and US-format phone numbers in the text are removed.

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

Maximum rows to return (and be charged for) in this run. 1 to 1000.

## `onlyNewSinceLastRun` (type: `boolean`):

For scheduled runs: return only opportunities that are new, or whose status, deadline, document type (forecast to posted), title or number changed, since the last run with the same filters. The first run is a baseline: it returns up to maxItems newest and remembers every current match (up to the 5,000 newest). Closures show as changes only when Closed is selected. State is kept in a named key-value store in your own Apify account.

## `outputFormat` (type: `string`):

full = every field; compact = id, number, title, agency, status, dates, days until close, award ceiling, total funding, url, update type (smaller rows for AI agents and spreadsheets).

## Actor input object example

```json
{
  "keywords": "climate resilience",
  "opportunityStatuses": [
    "forecasted",
    "posted"
  ],
  "sortBy": "newest",
  "includeDetails": true,
  "maxItems": 25,
  "onlyNewSinceLastRun": false,
  "outputFormat": "full"
}
```

# Actor output Schema

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

Default dataset. full rows: opportunityId, opportunityNumber, title, agencyCode, agencyName, status, documentType, postedDate, closeDate, daysUntilClose, assistanceListings, url; with includeDetails also awardCeiling, awardFloor, estimatedTotalFunding, expectedNumberOfAwards (null when the agency did not specify), costSharingRequired, fundingInstruments, fundingCategories, eligibleApplicants, eligibilityNotes, description, estimatedPostDate / estimatedCloseDate / estimatedDaysUntilClose (forecasts), fiscalYear, archiveDate, lastUpdated, version, moreInfoUrl, detailsUnavailable (only when the detail request failed); then updateType (monitor mode: new | changed; otherwise null), previous and changedFields (changed rows), changeHash. compact rows: opportunityId, opportunityNumber, title, agencyCode, status, postedDate, closeDate, daysUntilClose, awardCeiling, estimatedTotalFunding, url, updateType.

## `runSummary` (type: `string`):

Fields: ok, count, chargeEvent, chargedCount, chargeLimitReached (only when hit), totalMatches, scanned, outputFormat, includeDetails, detailsFetched, detailErrors, detailCapped, sortBy, requestBodies, truncated, incomplete, olderMatchesSkipped (baseline monitor runs), truncationNote, message, warnings, onlyNewSinceLastRun, watermarkStore, watermarkKey, baselineRun, newCount, changedCount, skippedUnchanged, grantsGovRequests (total, retries, throttled, minIntervalMs, perRunCap, userAgent), disclaimer. On failure: ok false, error.

# 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 = {
    "keywords": "climate resilience",
    "opportunityStatuses": [
        "forecasted",
        "posted"
    ],
    "maxItems": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("brightish_ascent/grants-gov-opportunities-monitor").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 = {
    "keywords": "climate resilience",
    "opportunityStatuses": [
        "forecasted",
        "posted",
    ],
    "maxItems": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("brightish_ascent/grants-gov-opportunities-monitor").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 '{
  "keywords": "climate resilience",
  "opportunityStatuses": [
    "forecasted",
    "posted"
  ],
  "maxItems": 25
}' |
apify call brightish_ascent/grants-gov-opportunities-monitor --silent --output-dataset

```

## MCP server setup

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

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/vqZYNM001eVkRHX1P/builds/jAUyXIVsywJVx5Muq/openapi.json
