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" in states and 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 onlyNew on, 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 with changeType: "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" } 
  • states scans every active OpenGov agency in those states. You can also pass agencies (portal codes like pittsburghpa or full portal URLs) instead.
  • keywords match the start of words, case-insensitive. keywordsInTitleOnly keeps it strict, so "cloud" doesn't match "St. Cloud" in a summary.
  • onlyNew remembers what you already got, under the name in stateKey.

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:

  1. Open the Actor, paste your input and click Save as a new task.
  2. On the task, add a Schedule (for example, every weekday at 7 AM in your time zone).
  3. 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 excludeKeywords matter more than anything else for useful results.

Try it

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.