US Federal Grants Scraper
Scrape US federal grant opportunities from grants.gov: opportunity number, agency, eligibility, award ceiling and floor, deadlines and links.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
searchTerms,opportunityStatus,maxItems(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.002 per opportunity = $2 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Opportunity scraped | One federal grant opportunity with its award ceiling, eligibility and dates. Searches that match nothing are never charged. | $0.002 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-20, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
searchTerms | Words to search for. Each term is searched on its own and the rows are pooled, so "wildfire" and "drought" in one run gives you both. The search covers the opportunity title and its full description, so a term can match a grant whose title never mentions it. Up to 25 terms per run. Leave empty to get everything the filters below select. | array |
opportunityStatus | Which stage of the lifecycle to return. "Posted" is open for applications now. "Forecasted" is an agency saying money is coming, usually with estimated dates rather than real ones. "Closed" has passed its deadline but is still on the site, and "archived" is the long tail going back two decades. Leave empty and you get forecasted plus posted, which is everything you could still apply for. | array |
maxItems | Total opportunities to return across every search term. The budget is split evenly between the terms, so five terms and 50 rows gives you ten of each. Hard ceiling 5,000. Keep it low while you are testing - you pay per row. | integer |
agencies | Limit results to one or more agencies, by code. A top-level code covers everything under it: "HHS" catches every Health and Human Services office, while "HHS-ACF-OHS" narrows it to the Office of Head Start. Other common ones are ED, DOE, NSF, USDA, DOI, DOT, EPA, HUD, DOL, NASA, SBA, VA, DOS and DHS. Case does not matter. | array |
eligibility | Keep only opportunities open to these applicant types. Pick several and a grant open to any one of them is kept. Note that a great many federal grants are coded "Unrestricted" or "Others" rather than naming your exact category, so a narrow pick here can hide grants you are in fact eligible for. | array |
fundingCategories | Keep only opportunities filed under these categories. Agencies pick the category themselves when they post, so it is their label rather than a strict taxonomy - broad searching plus a keyword usually beats a narrow category pick. | array |
fundingInstruments | The kind of agreement on offer. A grant hands money over with reporting obligations; a cooperative agreement means the agency stays involved in the work. | array |
alnNumbers | Exact programme numbers such as 93.600 or 47.076. This is the tightest filter available - it follows a specific federal programme across every opportunity it has ever posted, which is what you want for tracking a grant you have had before. | array |
opportunityNumbers | Look up specific opportunities by their published number, for example HHS-2026-ACF-OHS-HS-0001. Each one is fetched on its own, so a number that no longer exists returns an uncharged row saying so rather than a wrong match. | array |
postedWithinDays | Only opportunities posted in the last N days. The service accepts a fixed set of windows, listed here. Useful for a daily or weekly schedule that should only pick up what is new. | string |
proxyUrls | Leave this empty. The run brings its own addresses and the cost of them is already inside the price. Fill it in only if you specifically want the traffic to leave through servers you already pay for, as http://user:pass@host:port. | array |
What you get
A structured dataset — each result includes fields like:
opportunityNumbertitleagencyNamedepartmentNameagencyCodeopportunityStatusfundingCategorieseligibleApplicantsawardCeilingUsdawardFloorUsdopenDatecloseDateurlExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
OpenAlex Scholarly Works Scraper
Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.
Crossref Scholarly Works Scraper
Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.
Where this tool sits
- Categories
- Developer & Research Tools
US Federal Grants Scraper - grants.gov Opportunities API
Search every grant opportunity the US federal government has published on grants.gov and get one row back per opportunity: the opportunity number, the title, the agency and its parent department, whether it is open or forecast, who may apply, the award ceiling and floor, the open and close dates, the assistance listing number and a link straight to the notice. No account, no API key, no login, no browser.
- Search by keyword, agency, eligibility, category, funding instrument, assistance listing number or exact opportunity number - or combine them.
- Forecasted opportunities are included, so you can see money coming before it opens.
- Every row says whether its close date is a real deadline or an agency estimate.
- Rows the search service returns that do not actually match your filters are dropped and never charged.
- Run it with empty input and you get a labelled sample row, free, so you can see the shape first.
Price
$2.00 per 1,000 opportunities, plus a $0.0005 start fee per run.
This is a flat rate on every plan, free or paid. There are no volume tiers, no minimum spend, no subscription and no add-on fees. What you read here is what you pay on day one and on day four hundred.
| Opportunities | Total cost |
|---|---|
| 100 | $0.2005 |
| 1,000 | $2.0005 |
| 10,000 | $20.0005 |
| 100,000 | $200.0005 |
What is actually charged
- One
opportunity-scrapedevent per opportunity row written to the dataset. Nothing else is metered per row. - Free: the sample row an empty run returns, and every diagnostic row — a blocked target, a dead URL, a search that matched nothing. Those rows all carry
"charged": false. - Opportunities already returned earlier in the same run are skipped before they are charged.
- Rows that came back not matching your filters are dropped, not billed.
- An opportunity whose detail record could not be read is still handed over, marked
detailFetched: false, and not charged. - A run that finds nothing costs the start fee and nothing more.
- Rows never leave the dataset without a charge, and are never charged without a row. The billed event is a named one, so there is no price quietly attached to
apify-default-dataset-item— the trick that makes some scrapers bill you for their own error messages.
Input
{
"searchTerms": [
"wildfire",
"watershed restoration"
],
"opportunityStatus": [
"posted",
"forecasted"
],
"eligibility": [
"12",
"01"
],
"maxItems": 100
}
| Field | What it does |
|---|---|
searchTerms | Words to search for. Each term runs as its own search and the rows are pooled. The search covers the title and the full description, so a term can match a grant whose title never mentions it. Up to 25 terms per run. Leave it empty to get everything the filters select. |
opportunityStatus | forecasted, posted, closed, archived. Leave empty and you get forecasted plus posted - everything you could still apply for. Add archived only if you want the two-decade back catalogue; it is about 73,000 records. |
maxItems | Total rows across all terms, split evenly between them. Hard ceiling 5,000. Keep it low while testing - you pay per row. |
agencies | Agency codes. A top-level code covers everything under it: HHS catches every Health and Human Services office, HHS-ACF-OHS narrows it to the Office of Head Start. There are 47 top-level codes and about 680 sub-codes. |
eligibility | Applicant-type codes. Pick several and a grant open to any one of them is kept. |
fundingCategories | The category the agency filed the opportunity under, such as Health or Natural Resources. |
fundingInstruments | Grant, cooperative agreement, procurement contract or other. |
alnNumbers | Assistance Listing numbers such as 93.600 or 47.076 - the old CFDA numbers. The tightest filter there is: it follows one federal programme across every opportunity it has ever posted. |
opportunityNumbers | Exact published numbers, for example HHS-2026-ACF-OHS-HS-0001. Each is looked up on its own. |
postedWithinDays | Only opportunities posted in the last N days. The service accepts a fixed set of windows, from 3 days to 8 weeks. |
proxyUrls | Leave empty. Fill it in only if you want the traffic to leave through proxy servers you already pay for, as http://user:pass@host:port. |
Run it with empty input and you get one clearly labelled sample row, free, so you can see the output shape before you spend anything.
Output
One row per opportunity. A real row from a real run:
{
"ok": true,
"charged": true,
"recordType": "opportunity",
"opportunityId": "363335",
"opportunityNumber": "L26AS00057",
"title": "FY26 Bureau of Land Management Invasive and Noxious Plant Management - Bureau wide",
"agencyName": "Bureau of Land Management",
"departmentName": "Department of the Interior",
"agencyCode": "DOI-BLM",
"opportunityStatus": "posted",
"recordKind": "synopsis",
"openDate": "2026-07-27",
"closeDate": "2026-09-25",
"closeDateIsEstimated": false,
"archiveDate": "2026-10-25",
"awardCeilingUsd": 400000,
"awardFloorUsd": 20000,
"estimatedTotalFundingUsd": 2000000,
"expectedAwardCount": 40,
"costSharingRequired": false,
"eligibleApplicants": [
"State governments",
"Native American tribal governments (Federally recognized)",
"Private institutions of higher education",
"County governments",
"City or township governments",
"Public and State controlled institutions of higher education",
"Native American tribal organizations (other than Federally recognized tribal governments)",
"Nonprofits having a 501(c)(3) status with the IRS, other than institutions of higher education",
"Special district governments",
"Nonprofits that do not have a 501(c)(3) status with the IRS, other than institutions of higher education"
],
"eligibilityCodes": [
"00",
"07",
"20",
"01",
"02",
"06",
"11",
"12",
"04",
"13"
],
"fundingCategories": [
"Natural Resources"
],
"fundingCategoryCodes": [
"NR"
],
"fundingInstruments": [
"Cooperative Agreement"
],
"fundingInstrumentCodes": [
"CA"
],
"alnNumbers": [
"15.230"
],
"description": "BLM Invasive and Noxious Plant Management Programs work to prevent, detect, inventory, control, and monitor weed populations on public lands. …",
"url": "https://www.grants.gov/search-results-detail/363335",
"lastUpdated": "2026-07-27",
"detailFetched": true,
"scrapedAt": "2026-09-20T09:46:07.424Z"
}
Field notes
opportunityNumber— the number the agency published. This is what people quote at each other;opportunityIdis grants.gov's own internal key and is what theurlis built from.agencyName— the office that posted it.departmentNameis the cabinet department above it, so you can group a hundred sub-offices into fifteen departments.recordKind—synopsisfor a real posting,forecastfor an announcement of money that has not opened yet. The two come from different records and carry different amounts of certainty.closeDate— the application deadline. On a forecast this is the agency's estimate, andcloseDateIsEstimatedis then true - do not put an estimate in a calendar and forget which it was.awardCeilingUsd— the largest single award on offer, in dollars. Frequently null, because most agencies do not publish one. Null means "not published", not "no limit".awardFloorUsd— the smallest single award. Published even less often than the ceiling.estimatedTotalFundingUsd— the whole pot, across all awards.expectedAwardCountis how many they intend to make.eligibleApplicants— the applicant types the agency ticked, spelled out.eligibilityCodesis the same list as the codes you pass in the input, so you can round-trip them.alnNumbers— Assistance Listing numbers. An opportunity can carry several when it draws on more than one programme.description— the agency's own synopsis, with the HTML stripped out. Long ones are cut at 8,000 characters.detailFetched— true when the award, eligibility and category fields were read successfully. A false here means the blanks are missing data rather than unpublished figures - and that row was not charged.
Every real row carries "charged": true. Sample rows carry "_sample": true and diagnostic rows carry "_diagnostic": true with an errorCode you can filter on, and neither is ever billed.
How it works
- It calls the public grants.gov search service directly and pages through the results. No key, no cookie, no session and no browser - the service answers anyone who asks properly.
- The search result carries nine fields and no money, so each row costs one extra call to fetch the full record, which is where the award ceiling, the award floor, the eligibility list and the category live. Those calls run several at a time and are capped at the number of rows you actually asked for.
- A posted opportunity and a forecast are stored in differently-named records with differently-named date fields. Both are read, and the row tells you which one it came from.
- Every row is checked against what you asked for before it is charged. The search service quietly ignores a parameter it does not recognise and answers with a full unfiltered list at HTTP 200, so trusting the status code would mean billing you for a nationwide list when you asked for one agency.
What people use it for
- Grant writers keeping a live list of what is open in their field, without paying a subscription to a search box that will not let them export.
- Nonprofits watching a specific Assistance Listing number, because last year's programme usually comes back with a new opportunity number and the same ALN.
- Anyone who wants a calendar of deadlines: filter to posted, sort by
closeDate, and you have the next ninety days. - Consultants screening by eligibility - every grant open to 501(c)(3) nonprofits in a category, in one table.
- Watching forecasts so a proposal is half-written before the notice goes live.
- Feeding a dashboard or a database. The rows are flat and typed, dates are ISO, money is numeric, so nothing needs cleaning first.
What this does not do
Worth reading before you buy, because these are the things people assume.
- Opportunities, not awards. Every row is money that is open or about to open. Who actually received a grant, and how much, is a different dataset with different columns and it is not here.
- Federal only. State, county, city, school-district and foundation grants are not on grants.gov and so are not in these rows. If you need municipal funding, this is the wrong tool.
- No contact details for people. The underlying records name a programme officer with a phone number and an email address. None of that is emitted, on purpose. If you need to reach the officer, open the
url- it is on the notice. - No application forms or attachments. The notice usually has a package of PDFs attached. This returns the opportunity record and a link, not the documents.
- Award amounts are often blank. Measured on a sample of 40 posted opportunities: a ceiling was published on 21 and a floor on 11. That is the agencies, not the scraper - a null means nobody published a figure.
- It does not judge your chances. There is no scoring, no matching and no advice. It returns what the agency published.
Reading the output
Every run writes three kinds of row and they are easy to tell apart:
- Real rows carry
"charged": trueand"recordType": "opportunity". One billed event each. - The sample row carries
"_sample": trueand"charged": false. There is exactly one, it only appears when the input had nothing to search for, and it is there so you can see the shape before you spend anything. - Diagnostic rows carry
"_diagnostic": true,"charged": falseand anerrorCodeworth switching on:NO_RESULTSwhen a search ran fine and matched nothing,BAD_INPUTwhen rows came back that did not match your filters (usually a wrong code in the input),NETWORKwhen the service could not be reached at all,TIME_BUDGETwhen the run ran out of time before a term.
The difference between NO_RESULTS and NETWORK is the one that matters: the first means there is genuinely nothing there, the second means nobody looked. Neither is charged, and confusing them is how people conclude a programme has stopped funding when the service was simply down.
If you only want data, filter on charged == true. The count of those rows always equals the number of events you were billed for, so the dataset is its own invoice.
Limitations
- Grant opportunities only. Awarded grants, spending history and recipients are a different dataset and are not returned.
- Federal only. State, county, municipal, tribal-administered and private foundation grants are not published on grants.gov.
- Programme officer names, phone numbers and email addresses are deliberately not emitted, even though they exist on the source record.
- Award ceiling and floor are null on most opportunities because most agencies do not publish them. On 40 sampled posted opportunities, 21 had a ceiling and 11 had a floor.
- A forecast has no firm deadline. Its
closeDateis the agency's estimate and moves;closeDateIsEstimatedflags it. - Keyword search is the service's own full-text search over title and description. It is not a phrase match, and it does not support boolean operators.
- The "posted recently" filter only accepts the fixed windows the service offers, from 3 days to 8 weeks. Arbitrary date ranges are not supported.
- Attachments, application packages and the full funding announcement PDF are not downloaded. The
urltakes you to them. - Descriptions longer than 8,000 characters are cut, with an ellipsis at the end.
- The hard ceiling is 5,000 rows and 25 search terms per run. Split bigger jobs across runs.
- Data is only as current as grants.gov. An agency that has not updated a notice leaves a stale close date on it, and the row will repeat that faithfully.
Questions
Does this cover state or local grants?
No. grants.gov is the federal government's own listing and that is the entire source. State, county, city, school-district and foundation funding is published on hundreds of separate portals and none of it appears here.
Can I get the list of who actually won a grant?
Not from this Actor. Opportunities and awards are two different datasets with almost no columns in common, and mixing them would give you a table that is half empty on every row. This one returns money you can still apply for.
Why is the award ceiling empty on so many rows?
Because the agency did not publish one. It is an optional field on the notice and most agencies leave it blank. A null means "not published" - it does not mean the award is unlimited. When the field could not be read at all, rather than being genuinely blank, the row says detailFetched: false and you are not charged for it.
What is an ALN, and why would I filter on it?
An Assistance Listing Number, which used to be called a CFDA number - 93.600 is Head Start, for instance. It identifies the federal programme rather than the individual notice, so if you have had a grant before, filtering on its ALN finds this year's version even though the opportunity number changed.
What happens if my search matches nothing?
You get one uncharged diagnostic row with errorCode: "NO_RESULTS" and the run finishes as succeeded. You are never billed for a search that returned nothing.
I asked for one agency and got rows from another. What now?
You will not, and that is the point. Rows that do not match what you asked for are dropped before they are charged, and you get a BAD_INPUT diagnostic saying how many and why. That usually means a code in the input is not one the service recognises - check it against the dropdown list.
Can I run this on a schedule?
Yes. Nothing is held between runs. Pair a daily schedule with postedWithinDays and you only pick up what is new, and opportunityNumber makes a stable key for diffing against yesterday.
Will the run fail if grants.gov is down?
No. You get an uncharged diagnostic row saying the service could not be reached, and the run still finishes as succeeded. A failed run would still bill the start fee, which would mean paying to be told something was broken.
Do I need a grants.gov account or an API key?
No. The service this reads is open to anyone, and the Actor does not hold an account, a login or a cookie for it.