If you sell to local government (IT services, construction, janitorial, consulting), you know the annoying part of the job isn't writing the proposal. It's finding the bid in time. Every city, county, school district and transit agency posts RFPs on its own portal, and paid bid-alert services that watch them for you typically run $49 to $149 a month.
A big chunk of those agencies use the same e-procurement platform, OpenGov Procurement. Right now its public agency directory lists 549 active agencies across the US (127 in California, 93 in Florida, 49 in Arizona, 44 in Texas...). So I built an independent Apify Actor that checks all of them for you: OpenGov Procurement Bids Scraper.
Try it free: open the Florida software/IT bids example and press Start. Apify's free plan includes $5 of platform usage every month and doesn't need a credit card, which covers about 2,500 bids at this Actor's price.
This post walks through two real runs I did today: what goes in, what comes out, how the "only new bids" mode works, and what it costs.
What makes it different
-
Scan a whole state in one run. Put
"FL"instatesand every active OpenGov Procurement agency in Florida is checked, using OpenGov's own agency directory. No list of portal slugs to maintain. -
Only-new mode for a real alert feed. With
onlyNewon, each run returns only bids you haven't received yet. If an agency posts an addendum to a bid you already have, that bid comes back once withchangeType: "new_addendum". - The details you actually bid with. Buyer name, title, email and phone (as the agency published them), Q&A deadline, pre-bid meeting, UNSPSC/NIGP category codes, addenda, attachment names, timeline and evaluation criteria.
- $2 per 1,000 bids, details included. Other bid Actors on the Apify Store I compared charge $3 to $20 per 1,000.
Input
This is the exact input I ran:
{
"states": ["FL"],
"keywords": ["software", "technology", "cybersecurity", "cloud", "IT services", "data"],
"keywordsInTitleOnly": true,
"onlyNew": true,
"stateKey": "devto-demo-fl-it"
}
-
statesscans every active OpenGov agency in those states. You can also passagencies(portal codes likepittsburghpaor full portal URLs) instead. -
keywordsmatch the start of words, case-insensitive.keywordsInTitleOnlykeeps it strict, so "cloud" doesn't match "St. Cloud" in a summary. -
onlyNewremembers what you already got, under the name instateKey.
Other useful filters: dueWithinDays, postedWithinDays, excludeKeywords, solicitationTypes (e.g. "Request for Proposal"), agencyNameContains (e.g. "school", "airport") and statuses (open by default).
What happened
| Run | Agencies scanned | Open bids listed | Matches returned | Runtime |
|---|---|---|---|---|
| First run | 93 | 324 | 4 new bids | 4.6 s |
| Re-run right after | 93 | 324 | 0 (4 skipped as already seen) | 5.0 s |
Both ran at 256 MB, and peak memory was about 60 MB. The four Florida matches:
| Agency | Bid | Type |
|---|---|---|
| City of Clermont | Cloud Based Location Intelligence Foot Traffic Data Platform | Request for Proposal |
| City of Lakeland | Consulting Services for the Preparation of a Data Center and Large-Load Development Regulatory Framework | Request for Proposal - Standard |
| Jacksonville Transportation Authority | Public Engagement Web Based Software Platform | Solicitation (Attach a Document) |
| Putnam County School District | K-12 Master Scheduling Software, Implementation, and Support Services | Request for Proposal |
That second run is the point. Schedule the same input daily and most days you get zero or a handful of records, and every one is something you haven't seen.
Output
One dataset record per bid. Here's the Clermont one, trimmed (summary shortened, 3 of 7 evaluation criteria kept):
{
"type": "bid",
"title": "Cloud Based Location Intelligence Foot Traffic Data Platform",
"referenceNumber": "RFP 27-002",
"solicitationType": "Request for Proposal",
"status": "open",
"agency": "City of Clermont",
"agencyState": "FL",
"department": "Parks and Recreation",
"postedAt": "2026-09-10T04:00:00.000Z",
"dueAt": "2026-11-12T19:00:00.000Z",
"daysUntilDue": 23,
"summary": "The City is seeking proposals from qualified firms to provide a cloud-based location intelligence and foot traffic analytics platform...",
"url": "https://procurement.opengov.com/portal/clermontfl/projects/298812",
"procurementContact": {
"name": "Freddy Suarez",
"title": "Procurement Services Director",
"email": "fsuarez@clermontfl.org",
"phone": "(352) 241-7350"
},
"preProposalMeeting": null,
"questionsDeadline": "2026-11-04T20:00:00.000Z",
"sealedBid": true,
"categories": [
{ "code": "20949", "title": "Geographic Information System (GIS) Software" },
{ "code": "92005", "title": "Application, Infrastructure, Hosting and Cloud Computing Services" }
],
"addendaCount": 0,
"attachments": [
{ "title": "OpenGov Vendor Registration", "fileType": "pdf" },
{ "title": "Cost Proposal Form", "fileType": "docx" }
],
"evaluationCriteria": [
{ "title": "Proposed Platform and Technical Capabilities", "weight": 30 },
{ "title": "Data Methodology and Quality", "weight": 25 },
{ "title": "Cost Proposal", "weight": 10 }
],
"changeType": "new"
}
The contact shown is the buyer's published work contact on the public bid page. If an agency hides its contact, the field stays empty. The Lakeland bid in the same run came back with 5 addenda, 8 attachment names and 9 category codes. Note its deadline was the same afternoon, which is exactly why a daily check beats a weekly one.
Every run also writes a RUN_SUMMARY record (agencies scanned, bids listed, matched, skipped as already seen, errors), so you can tell "nothing new" apart from "something broke".
Turn it into a daily bid alert
Everything below is built into Apify; nothing extra to install:
- Open the Actor, paste your input and click Save as a new task.
- On the task, add a Schedule (for example, every weekday at 7 AM in your time zone).
- Under Integrations, pick where results go: Slack, Gmail or Google Drive are native options, or use a webhook, n8n, Make or Zapier to push new bids into a CRM or a spreadsheet.
Because onlyNew is on, each scheduled run sends only new bids and new addenda, not the same list every morning. For a California construction version, see the daily CA construction alert example.
What it costs
It's pay-per-result:
- $2.00 per 1,000 bids ($0.002 a bid), details included, plus a $0.00005 start fee per run
- Agencies with no matching bids add nothing to the bill
- A re-run with nothing new costs only the start fee
My first run above (4 bids) cost about $0.008. A daily Florida IT alert with a few new bids a week stays well under the $5 monthly credit on Apify's free plan. You can also set a max cost per run, and the Actor stops cleanly when it reaches it.
Honest limits
- It's an independent tool, not made by or affiliated with OpenGov.
- It covers agencies on OpenGov Procurement only. Lots of agencies use other portals (Bonfire, PlanetBids, BidNet, state systems), and those aren't in here. 549 agencies is a big slice of US local government, not all of it.
- It returns notice details with a link back to each bid on the agency's portal. It doesn't download the bid documents: you get attachment titles and file types, and you download the files (and register to respond) on the agency's own page.
- Keyword matching is simple word-start matching. Good keywords and
excludeKeywordsmatter more than anything else for useful results.
Try it
- Store page: OpenGov Procurement Bids Scraper
- One-click example: Florida software and IT bids
- Free to try on Apify's free plan ($5 of monthly credit, no credit card)
It's new, so I'd really like feedback. If a field you need when bidding is missing, or a keyword setup gives you noise, tell me in the comments or open an issue on the Actor page.












