# Grants.gov Scraper: Federal Grant Opportunities Feed (`fecklesspleb/grants-gov-opportunities`) Actor

New and open U.S. federal grant opportunities from the official Grants.gov API: title, agency, deadline, award ceiling and floor, eligibility, Assistance Listings, full description. Daily feed with dedupe and filters. Not endorsed or certified by HHS.

- **URL**: https://apify.com/fecklesspleb/grants-gov-opportunities.md
- **Developed by:** [Scott Williams](https://apify.com/fecklesspleb) (community)
- **Categories:** Business, Lead generation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 grant 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 Scraper: Federal Grant Opportunities Feed

> **This product uses the Grants.gov API but is not endorsed or certified by the U.S. Department of Health and Human Services.**

This **Grants.gov scraper** turns the official, keyless Grants.gov API into a clean daily feed of **U.S. federal grant opportunities**.
Each record has the title, agency, posted and closing dates, **award ceiling and floor**, estimated total funding, expected number of awards,
**eligible applicants**, Assistance Listing (ALN, formerly CFDA) numbers, the full description, the announcement file list and a link to
the official opportunity page.

Use it as a **federal grant alert** for a nonprofit, university research office, city or grant consultant, to watch **forecasted grants**
before they open, to screen opportunities by award size or applicant type, or to feed a funding calendar, CRM or spreadsheet.

### What you get

- **New and open federal grants:** posted (open for applications) and forecasted opportunities by default; closed and archived on request.
- **Only new or changed on a schedule:** each opportunity is returned once, and again if its **status changes** (forecast to posted) or its
  **closing date changes** (deadline extension). The memory is kept per `stateKey`, so several schedules can run side by side.
- **Full detail** (on by default): one extra API call per opportunity adds the description, eligibility text, award ceiling and floor,
  funding totals, forecast dates and attachments. Turn it off for a fast list of search fields only.
- **Filters:** keyword, agencies (a top-level code such as `HHS` includes every sub-agency; `HHS-NIH11` is one office), applicant
  types, funding categories, funding instruments (grant, cooperative agreement, procurement contract, other), ALN numbers,
  open-for-applications only, minimum award ceiling and minimum total funding.
- **Polite by design:** at most 2 requests a second, back-off on 429 and 5xx responses, and an immediate stop on 403.

### Input example

```json
{
  "statuses": ["posted", "forecasted"],
  "postedWithinDays": 7,
  "agencies": ["HHS", "NSF"],
  "eligibilities": ["12", "06"],
  "minAwardCeiling": 100000,
  "openForApplicationsOnly": true,
  "maxItems": 500
}
```

- `postedWithinDays` (default 7, U.S. Eastern dates) keeps daily runs small. Set 0 for the whole list.
- Eligibility codes: `12` = 501(c)(3) nonprofits, `06` = public universities, `20` = private universities, `23` = small businesses,
  `00` = state governments. The full lists are in the input form.
- `minAwardCeiling` and `minTotalFunding` use the detail fields, so they need `includeDetails` on (the default).

### Output example

A record from a run on 2026-10-31 (description, eligibility text and attachments shortened here):

```json
{
  "source": "Grants.gov",
  "opportunityId": "364178",
  "opportunityNumber": "G27AS00081",
  "title": "Cooperative Agreement for affiliated Partner with the Californian Cooperative Ecosystem Studies Unit",
  "status": "posted",
  "docType": "synopsis",
  "agencyCode": "DOI-USGS1",
  "agencyName": "Geological Survey",
  "topAgencyCode": "DOI",
  "topAgencyName": "Department of the Interior",
  "postedDate": "2026-10-30",
  "closeDate": "2026-11-30",
  "alnNumbers": ["15.808"],
  "alnPrograms": ["U.S. Geological Survey Research and Data Collection"],
  "category": "Discretionary",
  "fundingInstruments": ["Cooperative Agreement"],
  "fundingCategories": ["Science and Technology and other Research and Development"],
  "eligibilityText": "This financial assistance opportunity is being issued under a Cooperative Ecosystem Studies Units (C ...",
  "description": "This Notice of Funding Opportunity (NOFO) is for a U.S. Geological Survey (USGS) National and Regional Climate ...",
  "estimatedTotalFunding": 480000.0,
  "awardCeiling": 480000.0,
  "awardFloor": 1.0,
  "expectedAwards": 1,
  "costSharing": false,
  "lastUpdatedDate": "2026-10-30",
  "attachments": [{"folder": "Full Announcement", "fileName": "G27AS00081.docx"}],
  "url": "https://www.grants.gov/search-results-detail/364178",
  "detailFetched": true,
  "parseError": null
}
```

`sample_output.json` has more full records (a posted grant, a forecast, one with the agency contact on, and one without details).

**All fields:** `source`, `opportunityId`, `opportunityNumber`, `title`, `status`, `docType`, `agencyCode`, `agencyName`,
`topAgencyCode`, `topAgencyName`, `postedDate`, `closeDate`, `alnNumbers`, `alnPrograms`, `category`, `fundingInstruments`,
`fundingCategories`, `eligibleApplicants`, `eligibilityText`, `description`, `estimatedTotalFunding`, `awardCeiling`,
`awardFloor`, `expectedAwards`, `costSharing`, `fiscalYear`, `estimatedPostDate`, `estimatedCloseDate`, `estimatedAwardDate`,
`estimatedProjectStartDate`, `archiveDate`, `lastUpdatedDate`, `version`, `additionalInfoUrl`, `attachments`, `url`,
`detailFetched`, `parseError`, `scrapedAt`, plus `agencyContact` when `includeAgencyContact` is on.

- Dates are `YYYY-MM-DD`. Money is in U.S. dollars. A missing value is `null`, never `0`.
- Forecasts have no `closeDate`; use `estimatedCloseDate` and the other estimated dates.
- **Agency contact:** `includeAgencyContact` adds `agencyContact` (the grants officer or help desk the agency publishes for
  applicants: name, e-mail, phone). It is off by default.

Each run also writes a `RUN_SUMMARY` record: read, saved, skipped as already seen, filtered out, HTTP requests and why it stopped.

### Price

Pay per event: **$0.0015 per grant opportunity** saved ($1.50 per 1,000). The Actor sets no start fee or other events.
Records that could not be parsed are saved free.

Empty input `{}` and the prefilled input stop at **6 opportunities** (the `maxItems` default), so they cost at most $0.009.
Raise `maxItems` for a full daily feed. `maxItems` and the run's maximum cost setting cap your spend.

### FAQ and limits

- **Is there a Grants.gov API key to get?** No. The `search2` and `fetchOpportunity` endpoints are public and keyless.
- **Why is `awardCeiling` null?** The agency did not set one. That is common, and the minimum-ceiling filter drops those records.
- **The ALN filter:** Grants.gov's documented `aln` search field is ignored by the API, so this Actor sends the working `cfda` field.
  API callers may pass `aln` (a string, comma list or array) as an alias for `alnNumbers`; both are merged.
- **Closed and archived opportunities** are available, but a large archive pull is slow at 2 requests a second. Turn off details for
  big historical lists.
- Grants.gov sometimes republishes one opportunity under a new id; those appear as separate records.
- **Source down:** if Grants.gov is unreachable or keeps answering with errors and no records were saved, the run writes one free status record (`recordType: "status"`, not charged) instead of failing.
- **Nothing new:** if "only new since last run" is on and every opportunity found was already delivered by an earlier run with the same `stateKey`, the run writes one free status record (`recordType: "status"`, `status: "warning"`, message starting "Not charged: no new items since last run") instead of an empty dataset.
- **Invalid input:** if the input cannot be used (for example an unknown status, an agency or Assistance Listing code in the wrong format, or a field of the wrong type), nothing is fetched and the run still ends SUCCEEDED with one free record `{"recordType": "status", "type": "status", "status": "error", "statusRow": true, "charged": false, "message": "Invalid input, nothing was fetched or charged: <reason>", ...}`. No opportunities are charged.

### Data source and attribution

Data comes from the Grants.gov `search2` and `fetchOpportunity` APIs. This product uses the Grants.gov API but is not endorsed or
certified by the U.S. Department of Health and Human Services. Content is passed on unchanged except for formatting (HTML to plain
text, dates to ISO format). Text is complete unless you set `descriptionMaxChars`, which trims it and marks the cut with " ...".

# Changelog

This Actor's version history is a separate document: https://apify.com/fecklesspleb/grants-gov-opportunities/changelog.md

# Actor input Schema

## `statuses` (type: `array`):

Which Grants.gov statuses to include. Forecasted = announced ahead of time; posted = open for applications.

## `postedWithinDays` (type: `integer`):

Only opportunities posted (or forecast) in the last N days, U.S. Eastern dates. 0 = any date (all opportunities with the chosen statuses).

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

Grants.gov full-text keyword search, e.g. broadband or "rural health".

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

Agency codes. A top-level code (HHS, USDA, NSF, DOE) includes all its sub-agencies; a sub-agency code (HHS-NIH11, USDA-FS) only that office.

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

Only opportunities open to at least one of these applicant types.

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

Only these funding activity categories.

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

Grant, cooperative agreement, procurement contract or other.

## `alnNumbers` (type: `array`):

Assistance Listing (formerly CFDA) numbers, e.g. 93.866.

## `openForApplicationsOnly` (type: `boolean`):

Drops records with a close date before today. Opportunities with no close date are kept.

## `minAwardCeiling` (type: `integer`):

Only opportunities whose largest single award is at least this. Opportunities without a ceiling are dropped. Needs details.

## `minTotalFunding` (type: `integer`):

Only opportunities with at least this much total program funding. Needs details.

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

Fetch each opportunity's detail record (description, eligibility, award ceiling/floor, funding, forecast dates, attachments). One extra API request per opportunity. Off = search fields only.

## `includeAgencyContact` (type: `boolean`):

Add the official agency contact published for applicants (name, e-mail, phone). Off by default.

## `descriptionMaxChars` (type: `integer`):

Optionally trim description and eligibility text to this many characters (a trimmed text ends with ' ...'). 0 = full text, the default.

## `onlyNewSinceLastRun` (type: `string`):

auto = yes when 'Posted within' is set, no for a full listing. An opportunity comes back when its status or closing date changes.

## `stateKey` (type: `string`):

Name for the 'already seen' memory. Use different keys for different saved searches.

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

Stop after this many records are saved. Default 6 (at most $0.009). Raise it for a full daily feed.

## `maxPages` (type: `integer`):

Safety cap on search pages (250 results each).

## Actor input object example

```json
{
  "statuses": [
    "posted",
    "forecasted"
  ],
  "postedWithinDays": 7,
  "keyword": "rural health",
  "agencies": [
    "HHS",
    "NSF",
    "USDA"
  ],
  "fundingCategories": [
    "HL",
    "ST"
  ],
  "fundingInstruments": [
    "G",
    "CA"
  ],
  "alnNumbers": [
    "93.866",
    "47.076"
  ],
  "openForApplicationsOnly": true,
  "minAwardCeiling": 250000,
  "minTotalFunding": 1000000,
  "includeDetails": true,
  "includeAgencyContact": false,
  "descriptionMaxChars": 0,
  "onlyNewSinceLastRun": "auto",
  "stateKey": "default",
  "maxItems": 6,
  "maxPages": 40
}
```

# Actor output Schema

## `opportunities` (type: `string`):

No description

## `summary` (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 = {
    "statuses": [
        "posted",
        "forecasted"
    ],
    "postedWithinDays": 7,
    "openForApplicationsOnly": true,
    "includeDetails": true,
    "maxItems": 6
};

// Run the Actor and wait for it to finish
const run = await client.actor("fecklesspleb/grants-gov-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 = {
    "statuses": [
        "posted",
        "forecasted",
    ],
    "postedWithinDays": 7,
    "openForApplicationsOnly": True,
    "includeDetails": True,
    "maxItems": 6,
}

# Run the Actor and wait for it to finish
run = client.actor("fecklesspleb/grants-gov-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 '{
  "statuses": [
    "posted",
    "forecasted"
  ],
  "postedWithinDays": 7,
  "openForApplicationsOnly": true,
  "includeDetails": true,
  "maxItems": 6
}' |
apify call fecklesspleb/grants-gov-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fecklesspleb/grants-gov-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/fuZnrx66KOjqH372v/builds/JZAkGht9ADzOTPuvd/openapi.json
