US Federal Grants Monitor
Pricing
from $18.50 / 1,000 new grant alerts
US Federal Grants Monitor
Pricing
from $18.50 / 1,000 new grant alerts
Rating
0.0
(0)
Developer
Lowland Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 minutes ago
Last modified
Categories
Share
Watches every federal funding opportunity published on Grants.gov and alerts you the moment one matching your profile appears — a new NIH research announcement, a USDA rural programme, a DOE demonstration grant. It remembers what it has already told you, so an alert always means something changed, never "here is the same list again".
Live health record: lowlanddata.com/status/grants-gov-monitor - 30-day success rate and daily canary results, failures included. Full input/output reference: tool page.
It reads the official Grants.gov API — the same public feed the website itself runs on, no key, no login, no scraping around a defence. Output is institutional by construction: agency, programme, deadlines, award band. Programme-officer names, emails and phone numbers are never extracted, so the rows are safe to store, share and drop into a CRM.
Quick start (30 seconds, no account keys needed)
- Hit Start with the prefilled
keywords: ["water quality"]— it runs in a few seconds and shows a baseline of everything currently open on that term. - Replace the keywords with your own, or clear them and filter by
agencies/fundingCategoriesinstead. Every run logs the agency codes valid for your search, with counts. - Add a daily schedule (Actor page → Schedule). From then on, runs are quiet until a genuinely new opportunity appears.
Who uses this
- Grant writers at nonprofits watch
fundingCategoriesplus a keyword like"housing", and get the announcement number andcloseDatethe morning it posts, instead of finding it three weeks into a six-week window. - University research offices monitor
agencies: ["HHS-NIH11"]withscrapeDetails: true, and route each alert to the right department usingawardCeilingUsdandcfdaNumbers. - Consultants who bid federal work run several profiles in separate
stateStoreNames — one per client sector — so each client's digest contains only their opportunities. - Municipal finance teams set
eligibilities: ["02"](city and township governments) andalertOn: "new-and-updated", because a deadline that moves matters as much as one that appears.
What you get
One JSON item per event: on the first run a baseline of everything currently matching, then only transitions — a newly posted or forecasted opportunity, and (with alertOn: "new-and-updated") one whose status flipped or whose deadline moved. An alert looks like:
{"opportunityId": "357305","opportunityNumber": "PAR-25-274","title": "Feasibility Clinical Trials of Mind and Body Interventions","agency": "National Institutes of Health","agencyCode": "HHS-NIH11","status": "posted","docType": "synopsis","postedDate": "2024-11-21","closeDate": "2026-11-17","cfdaNumbers": ["93.213"],"url": "https://www.grants.gov/search-results-detail/357305","isBaseline": false,"isUpdate": false}
Field honesty notes:
postedDateandcloseDateare converted from the API'sMM/DD/YYYYto ISO. A forecast often has nocloseDateyet — the field is then absent rather than guessed.description,awardCeilingUsd,awardFloorUsd,costSharingRequired,responseDateandarchiveDateappear only withscrapeDetails: true. They come from the opportunity's full synopsis.isUpdate: truemeans an opportunity you were already told about changed its status or its deadline. The search feed carries no "last modified" timestamp, so a change to the description text alone will not re-alert — see the coverage note below.- A failed synopsis fetch never breaks the run: the row still ships with its search fields.
How much does grants monitoring cost?
Pay per outcome - checking costs nothing; you pay when the monitor tells you something. Three events, each charged for a different thing:
| Event | Price | When it is charged |
|---|---|---|
| New grant alert | $0.0199 | A funding opportunity that is genuinely new to your profile - or a status/deadline change, if you opted in |
| Baseline result | $0.00199 | Once per opportunity on your first run only, while the monitor learns what already exists |
| Actor start | $0.005 | Per run, whatever it finds |
The split exists because a monitor's rows are not all worth the same. The first run pushes everything currently matching your filters - useful as a snapshot, but nothing you did not know the world contained - so those rows cost a tenth of an alert. From the second run on, you pay the alert price only for real transitions. A run that finds nothing new costs $0.005 total.
Cost feel: a profile watching two agencies and a keyword typically baselines at 30-80 opportunities (about $0.06-$0.16, once), then alerts on perhaps 5-30 a month - roughly $0.15-$0.75/month including daily scheduled runs. A quiet month is a few cents of start events. Instrumentl and similar grant-discovery tools run $179-899/month against this same public source.
Not sure yet? Set emitBaseline: false on the first run to seed the memory silently - you skip the baseline charges entirely and pay only for what appears afterwards.
Why an alert costs more than a scraped row
The store headline is per 1,000 events, so alerts read "$19.90 / 1,000" next to raw scrapers at $1-5 per 1,000 rows - but those are different products:
- A raw scraper sells rows. To turn rows into alerts you would pull the full opportunity list every day, diff it yourself, and store the state - thousands of rows a month to find the handful that are new.
- This monitor sells the transition. It keeps the memory and charges $0.0199 exactly when something is genuinely new to you. Nobody buys 1,000 alerts a month; a busy profile sees a few dozen.
Not technical? Let your AI assistant set it up
Paste this to Claude, ChatGPT or Cursor along with what you want to watch:
I want to monitor US federal grant opportunities on Apify using the actorlowlanddata/grants-gov-monitor. Build me the input JSON.The fields are:- keywords: array of free-text terms (optional; omit to watch everything matching the other filters)- agencies: array of Grants.gov agency codes, e.g. ["USDA","DOD"] (optional)- eligibilities: array of applicant-type codes, e.g. ["02"] (optional)- fundingCategories: array of category codes (optional)- fundingInstruments: array of "CA" | "G" | "PC" | "O" (optional)- oppStatuses: array of "posted" | "forecasted" | "closed" | "archived" (default ["posted","forecasted"])- scrapeDetails: boolean, adds description and award amounts (default false)- alertOn: "new" or "new-and-updated" (default "new")- emitBaseline: boolean (default true)- maxItems: integer (default 500)- stateStoreName: string, one per watch profile (default "grants-gov-monitor-state")Here is what I want to watch: <describe it>Give me the JSON only. Then tell me how to add a daily schedule on the actorpage, and how to get an email when a run produces items.
Sources and honest coverage notes
- Federal only. Grants.gov covers US federal funding opportunities. State, county and private-foundation grants are not in this feed and this actor does not invent them.
- Both synopses and forecasts.
docTypetells you which. Forecasts are early notice with dates that often move — that is exactly whyalertOn: "new-and-updated"exists. - The official API, unauthenticated. No login wall, no anti-bot bypass, no rate-limit games. If Grants.gov rejects a search — usually an invalid agency or category code — the run fails with the message the API returned and the valid codes are in the log above it.
- Amendment detection is coarse. Status and deadline are the revision marker, because the search feed exposes no modification timestamp. A silently reworded description will not re-alert.
How the monitor thinks
- First run = baseline. Everything currently matching is pushed once, flagged
isBaseline: true. SetemitBaseline: falseto seed the memory silently and receive only what appears afterwards. - After that, only transitions. A new opportunity always alerts. An amended one alerts only with
alertOn: "new-and-updated"— and even when it stays silent, its marker is updated, so switching the toggle on later does not replay months of old changes as fresh news. - Changing filters changes the profile. The memory is keyed by the filter set, so a different keyword or agency list is a different profile and baselines on its own.
- Memory lives in a named key-value store (
stateStoreName, defaultgrants-gov-monitor-state) in your account. Use a separate name per watch profile to keep them independent.resetState: truewipes it and starts fresh. - Re-running after a crash re-alerts at most the last few unsaved items — state is checkpointed every 25 rows during the run.
Input reference
| Field | Type | Default | Notes |
|---|---|---|---|
keywords | string[] | [] | Free text, joined into one search phrase |
agencies | string[] | [] | Top-level codes (USDA, HHS) auto-expand to their sub-agencies; exact codes (USDA-NIFA) also work. Valid values are logged each run |
eligibilities | string[] | [] | Applicant-type codes |
fundingCategories | string[] | [] | Category codes |
fundingInstruments | string[] | [] | CA, G, PC, O |
oppStatuses | string[] | ["posted","forecasted"] | Which statuses to watch |
scrapeDetails | boolean | false | Adds synopsis fields; one extra request per alerted row |
alertOn | string | "new" | Or "new-and-updated" for status and deadline changes |
emitBaseline | boolean | true | Off = silent first run |
maxItems | integer | 500 | Overflow alerts on the next run |
stateStoreName | string | grants-gov-monitor-state | One per watch profile |
resetState | boolean | false | Wipe the memory and re-baseline |
Scheduling and API use
Daily is the right cadence — Grants.gov posts on business days and nothing is gained by checking hourly. On the Actor page, add a schedule, then set a Monitoring alert for "dataset items > 0" so a quiet day stays quiet and a match reaches your inbox.
curl -X POST \"https://api.apify.com/v2/acts/lowlanddata~grants-gov-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"keywords":["water quality"],"oppStatuses":["posted"]}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lowlanddata/grants-gov-monitor').call({agencies: ['USDA'],alertOn: 'new-and-updated',stateStoreName: 'usda-watch',});const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(token=os.environ["APIFY_TOKEN"])run = client.actor("lowlanddata/grants-gov-monitor").call(run_input={"keywords": ["renewable energy"],"scrapeDetails": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item.get("closeDate"))
A typical profile finishes well inside the 300-second synchronous wall. Very broad profiles with scrapeDetails: true are better run asynchronously, since the synopsis adds a request per alerted row.
Use it with AI agents (MCP)
Claude, Cursor and other MCP-capable agents can run this monitor as a tool through Apify's hosted MCP server — the agent picks the filters, reads the alerts and summarises them, with no glue code.
Claude Code:
$claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/grants-gov-monitor"
Cursor or Claude Desktop (add a custom connector / MCP server with this URL):
https://mcp.apify.com?actors=lowlanddata/grants-gov-monitor
Sign in with your Apify account when prompted — runs are billed to it. Setup details per client: Apify MCP docs, or start from this actor's own MCP page: apify.com/lowlanddata/grants-gov-monitor/api/mcp.
Prompts that work once connected:
- "Which federal grants for coastal water quality opened this week, and when do they close?"
- "Watch USDA rural development opportunities and tell me only about new ones."
- "Summarise the award ceiling and cost-sharing rules for the NIH grants that appeared today."
Is it legal to monitor federal grant opportunities?
Yes. Grants.gov is the US government's own public announcement channel and publishes a documented API for exactly this purpose — no login wall, no anti-bot measures, nothing circumvented. The whole point of the feed is that opportunities reach applicants.
And the output is safe by construction: no programme-officer names, emails or phone numbers are extracted, so nothing here is personal data (see below).
Compliance: safe to store, safe to CRM-import
The mapper is a whitelist. It names the fields it emits — identifiers, titles, agency, dates, award band, links — and everything else in the API response is dropped by construction rather than filtered afterwards.
That matters here specifically. The Grants.gov detail endpoint returns agencyContactName, agencyContactEmail, agencyContactPhone and a free-text contact block, often naming an individual officer with a direct line. None of them is in the whitelist, and an automated test feeds the mapper a record stuffed with contact data and fails the build if any person-shaped key or value reaches the output.
US federal data sits outside GDPR's scope, but the promise is not jurisdictional: no personal identifiers, by design, everywhere.
Honest limit: description is text the agency wrote. If an agency types a person's name into a programme description, that text is passed through as published — we do not rewrite source prose.
FAQ
Why did my second run return nothing? That is the product working. The first run baselines everything currently matching; after that you only hear about opportunities that are new to you. A quiet run means nothing changed.
Does it collect personal data? No — by design. Contact names, emails and phone numbers are never extracted, with or without scrapeDetails.
How do I find valid agency or category codes? Run it once and read the log: every run prints the agency codes valid for your search with their counts, e.g. HHS(182) DOD(128) USDA(29) NSF(25). Top-level codes like USDA or HHS work directly - the monitor expands them to their sub-agencies for you. Copy codes from the log rather than guessing — and note that a narrow keyword combined with an agency can legitimately return nothing, which is a real empty result, not a bad code.
Can I watch several unrelated topics? Yes — give each one its own stateStoreName. Profiles with different filters keep separate memories and baseline independently.
Why didn't I get an alert when a grant's description changed? Amendment detection uses status and deadline, because the search feed has no modification timestamp. A reworded description alone stays silent.
What happens if Grants.gov is down? The run fails loudly with the API's own message rather than reporting an empty result as "nothing new". Your memory is untouched, and the next run catches up.
Troubleshooting
- "Grants.gov rejected the search: ..." — an invalid filter code, almost always an agency or category. The valid codes for your search are logged immediately above the error; copy one from there.
- "Actor failed: items were found but none carried usable data (title)" — the API changed shape. Please report it on the Issues tab; it is treated as a break, not a shrug.
- A baseline that looks too large — narrow with
agenciesorfundingCategories, or setemitBaseline: falseto seed the memory silently and start from the next new opportunity.
Something else off? Open an issue on the actor's Issues tab — reports are read and answered.
And if the alerts are earning their keep, a rating on this page takes ten seconds and helps other buyers find a GDPR-clean monitor among the lookalikes.