SAM.gov Opportunities – Government Bids & Federal Procurement avatar

SAM.gov Opportunities – Government Bids & Federal Procurement

Pricing

$1.50 / 1,000 result items

Go to Apify Store
SAM.gov Opportunities – Government Bids & Federal Procurement

SAM.gov Opportunities – Government Bids & Federal Procurement

Scrape live US federal contracting opportunities from SAM.gov — solicitations, sources sought and awards — plus wage determinations, CFDA grant/loan programs and organization-only exclusion records, with no API key and no login. NAICS, set-aside, notice type and state filters, contacts, watch mode.

Pricing

$1.50 / 1,000 result items

Rating

0.0

(0)

Developer

Fetch Smith

Fetch Smith

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

SAM.gov Scraper – US Federal Procurement, Contracts, Bids, Wage Determinations & Grants

Scrape live US federal contracting opportunities from SAM.gov — presolicitations, solicitations, combined synopses, sources sought, special notices and award notices — with no API key, no login, no proxy and no browser. Filter by keyword, NAICS code, set-aside type, notice type, place-of-performance state and issuing organization, and optionally enrich every row with the contracting officer's contact details, NAICS codes, set-aside and place of performance.

In short: a federal RFP data API and an organization-only Excluded Parties List check in one keyless Actor — the same run lists open solicitations and tells you whether a firm is debarred.

What it does

  • Six public SAM.gov datasets, one Actor, no key. dataType picks which one: opportunities (default — solicitations, presolicitations, sources sought, awards), one of three Department of Labor wage-determination sets SAM.gov publishes — wage-determinations-dbra (Davis-Bacon Act, construction), wage-determinations-sca (Service Contract Act, services) and wage-determinations-cba (collective bargaining agreements) — assistance-listings, the Catalog of Federal Domestic Assistance (CFDA) grant/loan/direct-payment programs, or exclusions, the federal debarment/suspension list (organizations only — see below). All six come off the same keyless public search backend, so none of them needs a registered API key.

  • Calls the same backend that powers sam.gov's own public opportunity search page, so results match what you see on the site. SAM.gov's official developer API (api.sam.gov/opportunities/v2) requires a free registered API key — this Actor needs none. You do not have to register with GSA, wait for key approval, or rotate a key across a team.

  • enrichDetail joins each row with the per-opportunity record, which is where the fields a bidder actually qualifies on live: naicsCodes, setAside, placeOfPerformanceState/placeOfPerformanceCountry, and pointOfContact (the contracting officer's name, email and phone, primary and secondary). None of these are on the search row. Off by default because it costs one extra HTTP call per row; turn it on when you are qualifying, not just listing.

  • Multi-value filters really OR. naicsCodes: ["541511", "541512"] returns the union of both, not just the first. This is worth stating because SAM.gov's backend silently accepts a repeated query parameter and then honours only the first value — verified live: naics=541511 → 607 hits, naics=541512 → 312, repeated-key form → 607 (wrong, and no error), comma-joined form → exactly 919. This Actor sends the comma-joined form for every multi-value filter (naicsCodes, setAsideTypes, noticeTypes, states), so a two-code search does not quietly drop half your pipeline.

  • noticeTypes uses SAM's own notice-type codes — p presolicitation, o solicitation, k combined synopsis/solicitation, r sources sought, a award notice, s special notice, g sale of surplus, i intent to bundle, u justification. Every row also comes back with both the raw noticeTypeCode and the human-readable noticeType. Four more codes exist in SAM.gov's historical data but are no longer issued and don't appear in SAM's own current UI dropdown — m modification/amendment/cancel, f foreign government standard, j justification and approval (J&A), l fair opportunity/limited sources justification (all retired 2019-2020, ~97k rows fleet-wide, live-verified cycle 835). Useful for historical research; leave them out for a current-solicitations pipeline.

  • setAsideTypes takes SAM.gov's own set-aside codes, and this Actor fixes the case for you. The full vocabulary, each value live-verified non-zero against the opportunity index on 2026-09-30: SBA total small business, SBP partial small business, 8A 8(a) competed, 8AN 8(a) sole source, HZC HUBZone competed, HZS HUBZone sole source, SDVOSBC service-disabled veteran-owned competed, SDVOSBS SDVOSB sole source, WOSB women-owned, WOSBSS WOSB sole source, EDWOSB economically-disadvantaged WOSB, EDWOSBSS EDWOSB sole source, LAS local area set-aside, IEE Indian economic enterprise, ISBEE Indian small business economic enterprise, BICiv Buy Indian, VSA veteran-owned competed, VSS veteran-owned sole source. SAM.gov's backend matches these case-sensitively and fails closed, so before this was handled setAsideTypes: ["sba"] returned zero rows on the largest set-aside category in the index (1.2M opportunities) with no error to tell you why — measured live: SBA → 1,204,971 hits, sba → 0. This Actor now canonicalises the case, so sba, SBA and Sba are the same query. Note that upstream is not uniformly uppercase — BICiv really is mixed-case (BICiv → 4,498 hits, BICIV → 0), which is why this is a code lookup and not a blanket upper-casing. The umbrella names buyers actually say — 8(a), SDVOSB, HUBZone — are accepted too and expand to the real code(s) they cover (SDVOSB → SDVOSBC + SDVOSBS, since SAM.gov splits competed from sole-source and "SDVOSB" means either). Any value that is not a code or an alias is still sent as-is, which is safe — SAM.gov fails closed on it, so it matches zero rows rather than silently widening your search to the unfiltered index — and the run logs a warning naming the value and listing the valid codes.

    Re-audited both directions on 2026-10-10, which is how the list above got three values it was missing. Every prior pass only checked our codes against SAM.gov (all 18 still return rows, nothing dead, counts up only by natural growth: SBA 1,204,971 → 1,206,126). The reverse direction — what SAM.gov accepts that we never listed — had never been run, because SAM.gov publishes no set-aside reference endpoint to read (re-confirmed: no facets/aggregations on the search response, locationservices/v1/api/setasidetypes 500s, every other guessable path 404s). So it was derived empirically instead: 1,500 live opportunity rows sampled across the index for the set-aside code each row carries itself, plus a brute-force probe of the entire 1- and 2-character code space (1,332 values, of which only 8A is real — so that space is now closed). Three real, filterable codes turned up, all of them previously reported to you as typos:

    • setAsideTypes: ["NONE"] — SAM.gov's explicit unrestricted / no set-aside tag. 38,997 opportunities, 3,349 of them active, newest modified the day of the audit, so this one is live and useful. Note what it does and does not mean: it narrows your search to opportunities SAM.gov tagged NONE outright, and is not the same as leaving setAsideTypes empty — the millions of unrestricted opportunities that carry no set-aside field at all are not in it. The run logs that distinction when you use it.
    • setAsideTypes: ["SDB"] (Total Small Disadvantaged Business, 464 rows, newest modified 2019-06-27) and setAsideTypes: ["ESB"] (Emerging Small Business, 714 rows, newest 2020-01-20) — retired programs with zero active opportunities, the same historical-only class as the legacy m/f/j/l notice types below. Nothing has posted under either since 2020, so they are for research, not for a bid pipeline; they are supported because those rows are otherwise unreachable through this filter. The run logs a note when you use them.
  • states filters on place of performance, not the issuing office. SAM's official API calls this state; on this backend that parameter name is silently ignored and returns zero rows, a trap this Actor sidesteps by sending pop_state.

  • activeOnly (default on) restricts to opportunities still open for response. Turn it off for historical and award research.

  • Pay per result: charged only for rows actually returned, with no Actor-start fee — a search that matches nothing costs nothing.

  • watchLabel — only what's new since your last run. Name a saved search and every run after the first returns just the opportunities not already delivered under that label and filter combination. The first run for a label is a free baseline (0 results, 0 charged); it records what already matches in a key-value store on your own Apify account, keyed by the label plus a fingerprint of your other filters, so editing a filter starts a fresh baseline instead of dumping every previously-excluded opportunity as "new". Built for a daily/weekly scheduled run.

  • postedFrom/postedTo and deadlineFrom/deadlineTo — real two-sided date windows, and you are not charged for what they drop. SAM.gov's search backend has no date-range parameter at all (which is why most Actors on this index make you post-process the whole result set yourself, paying for every row you then throw away). This Actor applies the window after fetching each row and before pushing or charging it, so a window is free narrowing: deadlineFrom set to today gives you only opportunities you can still bid on, postedFrom/postedTo gives you one quarter's postings, and the rows outside never appear on your bill. Both ends are inclusive and compared on the calendar date the notice itself carries, never re-zoned. Honest trade-off: because the filtering is ours and not SAM.gov's, the window does not reduce what is read upstream — a narrow window over a broad keyword still walks the full match set, so keep your keyword/NAICS filters narrow too, and read dateWindowDropped in RUN_SUMMARY (plus declaredMatches, which stays SAM.gov's pre-window count) to see exactly what the window removed.

  • solicitationNumber — exact-match lookup, not a keyword guess, now with a one-request fast path. Give it a real solicitation number (dashes/spaces optional, matching is case-insensitive) and the run drops every fetched row whose own solicitation number isn't an exact match before pushing or charging it — the same pre-charge placement as the date windows above. Searching by keyword alone can false-positive on a number that merely appears in a title or description; this field matches the number the row actually carries. SAM.gov's search backend silently ignores a solnum-style parameter (confirmed live), but it does honour notice_id as an exact, case-sensitive, raw-punctuation match on the solicitation number — this Actor tries that first (one probe request), and when your value matches, the whole run completes in a single page instead of walking the broader keyword search; when it doesn't, it falls back automatically to sending the value as the search keyword and walking, same as before. Opportunities only.

  • minAwardAmount/maxAwardAmount — a real dollar range on award notices, and you are not charged for what it drops. SAM.gov's search backend only supports an exact award-amount match (award_amount=<n>) and rejects every range syntax with HTTP 400, so this is applied the same way as the date windows above: after fetching each row, before pushing or charging it. award.amount is null on every notice that hasn't been awarded yet, so pair this with noticeTypes: ["a"] or most fetched rows will be dropped as having nothing to compare (read awardAmountMissing in RUN_SUMMARY to see how many). Opportunities only.

  • includeIncumbentAwards answers the question you actually have about a notice: who holds this work today? For each opportunity's NAICS code it attaches the top 3 US federal contract awards by dollar value from USAspending.gov as incumbentAwards — recipient name and UEI, amount, start and end dates, awarding agency, and a usaspending.gov link — matched on NAICS and, where the issuing department maps to one of USAspending's top-tier agency names, on agency too (every row's incumbentAwardsMatchedBy tells you which of the two it got). Not billed separately: no extra per-result charge. Two things worth knowing, both reported in RUN_SUMMARY: NAICS codes are not on SAM.gov's search row, so this turns enrichDetail on automatically (one extra request and ~200 ms per row, and you get the contact/set-aside/place-of-performance fields along with it); and incumbentYears is matched against each award's last-modification date, not its start date, so a long-running contract that began before your window but was recently modified is included — intentionally, because it is still the incumbent, and every award carries both dates so you can tell. Lookups are deduped per unique NAICS+agency pair, so 200 opportunities spread across 5 NAICS codes cost 5 USAspending requests, not 200.

  • description is the full solicitation text, not a truncated snippet — the same original HTML SAM.gov itself stores, which can run to several thousand characters on a detailed notice.

  • includeAttachments lists each notice's files — drawings, full statements of work, forms — with a direct, no-login download URL for each. One extra HTTP call per row, off by default. Every link is SAM.gov's own stable file-download path, not a short-lived signed URL, so it works whenever you actually click it, not just at scrape time. Export-controlled and sign-in-required attachments are excluded from the list — this Actor never hands you a link that 403s or bounces to a SAM.gov login, so every URL you get back actually works with no account. A notice with genuinely no files returns attachments: []; a failed lookup returns null and is reported in RUN_SUMMARY, so the two are never confused.

  • watchChanges — also catch a deadline extension, a lifecycle transition, or an award landing. Add this to watchLabel and an opportunity you already have gets re-delivered (at the normal per-row price, tagged _watchChangeType/_watchPrevious) if its isActive flag, noticeTypeCode (a presolicitation turning into a solicitation, or a solicitation turning into an award), responseDate (deadline moved), modifiedDate, modificationsCount or awardeeName (an award landing) has changed since you last saw it — not just brand-new opportunities. Off by default so existing watches keep their current behaviour. Don't combine it with activeOnly (on by default!) or noticeTypes — see the FAQ "don't filter on the field you're watching".

Wage determinations

Set dataType to one of the three wage-determination options and the same filters you already know (keyword, states, activeOnly, maxResults, watchLabel, watchChanges, webhookUrl) apply to Department of Labor determinations instead of solicitations.

dataTypeWhat it returnsLive record count
wage-determinations-dbraDavis-Bacon Act determinations — construction, with constructionTypes (Building / Heavy / Highway / Residential)~85,400 (~4,200 active)
wage-determinations-scaService Contract Act determinations — services, with a services[] list of covered categories~2,700 (~1,500 active)
wage-determinations-cbaCollective bargaining agreement determinations~107,600 (~10,100 active)
  • Coverage is normalized across all three. SAM.gov returns the covered geography in three different shapes (DBRA nests a single location.state, CBA an array of location.states, SCA an array whose counties split into include/exclude lists). Every row here carries the same flat coverage array of { stateCode, stateName, isStateWide, counties, excludedCounties }, plus stateCodes and countyCount for filtering. SCA's excluded counties are kept in their own field rather than merged into the covered list — an excluded county is the opposite of a covered one.
  • Dates are normalized too. publishDate comes back as an ISO string on CBA rows but as epoch milliseconds on DBRA/SCA rows; this Actor emits ISO 8601 for every row so you are not parsing two formats.
  • states filters on the state the determination covers, and multiple states OR together the same way: measured live, AL → 3,509 and TX → 6,909 CBA determinations, ["AL","TX"] → 10,415 (the 3 determinations covering both states are returned once, not twice).
  • activeOnly means "currently in force" — a determination superseded by a later revision has isActive: false. Combine with watchLabel + watchChanges and a run tells you when a determination you track is revised (revisionNumber moves) or goes inactive.
  • keyword searches the reference number, not trades. On these indices q matches the determination's own number (e.g. AK20260001), so q=roofing returns zero against 85,000+ live Davis-Bacon records. Filter by state and construction/service type instead, and leave keyword empty to get the whole set. The exact-match behavior is also narrower than it looks — a complete reference number matches exactly one row, but adding so much as a space silently switches the query to an OR across every token, so q=AK 20260001 returns the 106 determinations that merely start with AK, not the 1 you asked for, with no error either way. See the full measurement — this is why keyword defaults to empty on every wage-determination run from this Actor rather than passing a caller's value straight through.
  • What this does NOT include: per-occupation hourly wage rate tables. SAM.gov does not publish the rate schedule on any of the three search indices, so every row has wageRates: null. This Actor gives you the determination index — which determination applies to which state and counties, its revision number, its construction/service scope and whether it is current — which is what you need to pick the right determination; read the rates themselves from the determination's own page on sam.gov.
  • naicsCodes, setAsideTypes, noticeTypes, organizationId, enrichDetail and includeAttachments are opportunity-only. If you set one in a wage-determination run it is ignored and the run logs a warning saying so, rather than silently returning an unfiltered set that looks filtered. includeIncumbentAwards is opportunity-only too, but it stops the run instead of being ignored: a wage determination or exclusion record carries no NAICS code, so there would be nothing to match an incumbent award on, and every delivered row would be billed with an empty incumbentAwards.

Example wage-determination input

{
"dataType": "wage-determinations-dbra",
"states": ["TX", "NM"],
"activeOnly": true,
"maxResults": 500
}

Sample wage-determination output row

{
"wageDeterminationId": "AK20260001",
"referenceNumber": "AK20260001",
"shortReferenceNumber": "AK1",
"title": "AK20260001",
"actCode": "DBA",
"actName": "Davis-Bacon Act",
"recordType": "wdDBRA",
"isActive": true,
"isStandard": true,
"revisionNumber": 4,
"year": 2026,
"publishDate": "2026-10-15T04:00:00.000Z",
"modifiedDate": "2026-10-15T00:00:00-04:00",
"constructionTypes": ["Building", "Heavy"],
"services": null,
"coverage": [
{
"stateCode": "AK",
"stateName": "Alaska",
"isStateWide": null,
"counties": ["Anchorage", "Matanuska-Susitna", "Fairbanks North Star", "Juneau"],
"excludedCounties": []
}
],
"stateCodes": ["AK"],
"countyCount": 28,
"wageRates": null
}

Assistance listings (CFDA)

Set dataType to assistance-listings to pull the Catalog of Federal Domestic Assistance — ~7,400 federal grant/loan/direct-payment programs (~2,900 currently active), each with its objective, eligibility rules, funding-obligation history, related programs and the agency's own published program contact.

  • Supports keyword, organizationId, activeOnly, maxResults, watchLabel, watchChanges, webhookUrl. naicsCodes, setAsideTypes, noticeTypes and states are opportunity-only and are ignored (with a log warning) here — assistance-listing programs are nationwide, not filtered by place of performance. enrichDetail and includeAttachments are also ignored: the search row already carries the full record, and CFDA programs have no notice attachments.
  • keyword matches title, objective and program number (e.g. q=flood → 60 of 7,392 programs), not a reference-number-only match like the wage-determination indices.
  • programNumber (e.g. "12.103") is the CFDA number buyers actually search by — the natural reference for cross-checking against grants.gov or an agency's own NOFO.
  • obligations is shipped as SAM.gov's own raw per-assistance-type funding history ({ assistanceType, values: [{ year, actual, estimate, flag, explanation }], additionalInfo }) rather than normalized into a single amount field. Measured over the entire catalog (all 7,396 programs, cycle 1988): the amounts are mostly there — 4,205 programs carry a non-empty block and 4,093 of those (97.3%) carry a real number — but any single normalized amount field would be silently wrong on over a third of the 16,594 year-entries. 0 is a placeholder, not a quantity (2,943 estimate: 0 + 2,737 actual: 0 = 34.2% of entries; e.g. 10.856 FY2013 is {flag: "ena", estimate: 0, explanation: "Program not funded"}); estimate and actual co-occur on 1,771 entries and disagree by up to ~50% (e.g. 14.880 FY2019 estimate $20.0M vs actual $29.97M); and the flag vocabulary is exactly two values, ena (696, estimate not available) and nsi (340, not separately identifiable — the money is booked under another program number, given in explanation, e.g. 14.159 FY2014 → "Reported under 14.117"). Raw keeps those distinctions; a plausible-looking single number would destroy them. Full measurement: a zero in federal program funding history doesn't mean zero dollars.
  • contacts is the agency's own published program contact (name/title/phone/address) from the public listing, the same disclosure class as opportunities' pointOfContact.
  • watchChanges on assistance listings re-delivers a program if its active or funded status, modified date, or historical-index entry count has changed since you last saw it — there is no revision number or response deadline on this dataset, so funded/active status is the closest signal to "this program moved."

Example assistance-listings input

{
"dataType": "assistance-listings",
"keyword": "broadband",
"activeOnly": true,
"maxResults": 100
}

Sample assistance-listings output row

{
"assistanceListingId": "8d745b5ad52a421dbf9483c7451adec1",
"programNumber": "12.002",
"title": "Procurement Technical Assistance For Business Firms",
"alternativeNames": ["APEX Accelerator Program/Procurement Technical Assistance Program (PTAP))"],
"objective": "Building a strong and sustainable U.S. supply chain and supporting a wide range of diverse businesses by providing procurement assistance to businesses...",
"isActive": true,
"isFunded": false,
"isLatest": true,
"publishDate": "2026-01-16T00:02:55-05:00",
"modifiedDate": "2026-01-16T00:02:55-05:00",
"department": "DEPT OF DEFENSE",
"agency": "WASHINGTON HEADQUARTERS SERVICES (WHS)",
"assistanceTypes": [["Financial", "Cooperative Agreement"]],
"eligibleApplicants": ["Nonprofit Organization", "Tribal", "..."],
"eligibleApplicantsNote": "Eligible applicants. Only those entities listed in this section are eligible to apply...",
"eligibleBeneficiaries": ["Anyone/general public", "State", "Local"],
"eligibleBeneficiariesNote": null,
"obligations": [{ "assistanceType": { "code": "F002", "value": "Cooperative Agreement" }, "values": [{ "actual": 55170000, "year": 2024 }, { "actual": 54999925, "year": 2025 }, { "estimate": 59098543, "year": 2026 }], "additionalInfo": "" }],
"contacts": [{ "name": null, "title": null, "phone": null, "address": "Commander, U.S. Army Corps of Engineers, Attn: CECW-OE, Washington, DC 20314-1000." }],
"relatedPrograms": ["12.104", "12.105"],
"website": "http://www.usace.army.mil/business.html.",
"historicalIndexCount": 6,
"sourceUrl": "https://sam.gov/fal/8d745b5ad52a421dbf9483c7451adec1/view"
}

Exclusions

Set dataType to exclusions to pull SAM.gov's federal debarment/suspension list — entities barred from receiving federal contracts, grants or other assistance — restricted to organizations only (firms, vessels and special entity designations, ~35,200 records).

  • This Actor never returns the individual-person exclusion records SAM.gov also publishes. SAM.gov's exclusions index carries 168,673 records total, and 79% of them (133,478) name a private person with a home city, state and zip — not a company. Turning that into a bulk-downloadable dataset would be a people-search product, which this Actor deliberately does not offer: the classification filter that separates organizations from individuals is hard-coded into every request this Actor makes, with no input anywhere that can widen it. If you need to check whether a specific named individual is excluded, look them up one at a time on sam.gov/search directly — SAM.gov's own public exclusions checker is exactly built for that single-lookup use case.
  • Supports keyword (matches the excluded entity's name), organizationId, maxResults, watchLabel, watchChanges, webhookUrl. naicsCodes, setAsideTypes, noticeTypes and states are opportunity-only and are ignored (with a log warning) here. activeOnly has no effect on this dataset — SAM.gov's exclusions index does not support server-side active-status filtering, so every matching record is returned regardless of the setting; check each row's own isActive/terminationDate if you need to filter locally. enrichDetail and includeAttachments are also ignored: the search row already carries the full record, and exclusion records have no notice attachments.
  • Rows SAM.gov itself flags "do not display" are dropped before you ever see them, regardless of classification — a small number of exclusion records carry SAM.gov's own noPublicDisplayFlag, and this Actor honors it the same way sam.gov's own public search does.
  • watchChanges on exclusions re-delivers a record if its active status or termination date has changed since you last saw it — the two signals that mean a debarment was lifted.

Example exclusions input

{
"dataType": "exclusions",
"keyword": "construction",
"maxResults": 100
}

Sample exclusions output row

{
"exclusionId": "4550ad9c-4b01-4e3d-bc94-716ee807836e",
"title": "CHOSUN INTERNATIONAL CHEMICALS JOINT OPERATION COMPANY",
"classificationCode": "Special Entity Designation",
"ueiSam": "NTRNRHCG7L45",
"cageCode": null,
"samNumber": null,
"addressCity": null,
"addressState": "XX",
"addressCountry": "USA",
"addressZip": null,
"exclusionTypeCode": "PR",
"exclusionType": "Prohibition/Restriction",
"exclusionProgram": "Reciprocal",
"excludingAgency": "OFAC",
"excludingAgencyDesc": "OFFICE OF FOREIGN ASSETS CONTROL",
"department": "TREASURY, DEPARTMENT OF THE",
"agency": "DEPARTMENTAL OFFICES",
"office": "OFFICE OF FOREIGN ASSETS CONTROL",
"isActive": true,
"activationDate": null,
"terminationDate": null,
"isFascsaOrder": false,
"sourceUrl": "https://sam.gov/exclusion/4550ad9c-4b01-4e3d-bc94-716ee807836e/view"
}

Use cases

  • GovCon bid pipelines — pull every active solicitation in your NAICS codes and set-aside category (naicsCodes + setAsideTypes + noticeTypes: ["o", "k"]) into a CRM, already qualified by place of performance.
  • Small-business / 8(a) / SDVOSB capture — filter to the set-asides you actually hold and stop reading opportunities you are not eligible for: setAsideTypes: ["8(a)"], ["SDVOSB"] or ["HUBZone"] work as written, as do the underlying codes (8A, SDVOSBC, HZC, …).
  • Contracting-officer outreach on sources-sought notices — noticeTypes: ["r"] plus enrichDetail gives you the pre-RFP notices where a vendor can still shape the requirement, together with the officer's published contact details.
  • Competitive award research — activeOnly: false with noticeTypes: ["a"] returns award notices including awardeeName and awardeeUeiSAM, so you can see who is winning in your NAICS.
  • Agency- or state-specific monitoring — organizationId for one department/agency, or states for the geographies your team can actually staff.
  • Daily cron alerts — watchLabel on a narrow keyword/NAICS search on a schedule returns only the handful of new notices, instead of refreshing sam.gov by hand or re-paying for the whole result set every run.
  • Davis-Bacon compliance for construction bids — dataType: "wage-determinations-dbra" with the states you build in tells you which determination covers each county and whether it is the current revision, so a bid is priced against a determination that is actually in force.
  • Service Contract Act scoping — dataType: "wage-determinations-sca" returns the service categories each determination covers, so you can map a services solicitation to the right determination before pricing labour.
  • Wage-determination revision alerts — watchLabel + watchChanges on a state-filtered wage-determination search re-delivers a determination only when its revisionNumber, active status or modified date moves — the signal that an in-flight bid or a running contract needs repricing.
  • Deadline-extension / lifecycle alerts — watchLabel + watchChanges flags a presolicitation turning into a solicitation, a deadline extension, or an award landing on a solicitation you're already tracking.
  • Grant-eligibility screening — dataType: "assistance-listings" with a keyword returns each matching program's eligibleApplicants/eligibleBeneficiaries and objective, so a grant writer can shortlist which CFDA programs a client actually qualifies for before drafting anything.
  • New/defunded grant program alerts — watchLabel + watchChanges on assistance-listings flags a program going active, funded, or unfunded since your last check.

Example input

{
"keyword": "solar",
"naicsCodes": ["221122"],
"maxResults": 15,
"enrichDetail": true
}

Input

FieldTypeDescription
dataTypestringWhich SAM.gov dataset: opportunities (default), wage-determinations-dbra, wage-determinations-sca, wage-determinations-cba, assistance-listings
keywordstringFull-text search across the opportunity index (default contract). On wage-determination types it matches the determination's reference number; on assistance-listings it matches title/objective/program number — leave empty for all
naicsCodesarrayNAICS codes, e.g. ["541511", "541512"] — multiple codes are ORed. Opportunities only
setAsideTypesarraySet-aside codes, e.g. ["SBA"] — case-insensitive, multiple values are ORed. Opportunities only. Full code list below
noticeTypesarrayNotice-type codes p/o/k/r/a/s/g/i/u (current) plus m/f/j/l (legacy, retired 2019-2020) — multiple values are ORed. Opportunities only
statesarrayTwo-letter state codes, e.g. ["TX", "CA"] — ORed. Place of performance for opportunities; covered state for wage determinations; not supported for assistance-listings
postedFrom / postedTostringOptional YYYY-MM-DD posted-date window on publishDate, both ends inclusive, either side usable alone. Applied by the Actor after fetch and before charging, so rows outside your window are never billed. Opportunities, wage determinations and assistance-listings; not supported for exclusions (no publish date on those records — the run stops and says so rather than billing an unwindowed set)
deadlineFrom / deadlineTostringOptional YYYY-MM-DD response-deadline window on responseDate, both ends inclusive. Set deadlineFrom to today to drop opportunities you can no longer bid on. Same pre-charge filtering. Opportunities only. Don't combine with watchChanges — see FAQ "don't filter on the field you're watching"
solicitationNumberstringExact-match lookup, e.g. "SPRRA2-22-R-0016" — dashes/spaces ignored, case-insensitive. Tries SAM.gov's notice_id param first (exact, one request); falls back to a search-and-filter walk (overriding keyword) if that doesn't match. Applied by the Actor before charging either way. Opportunities only; not supported for wage determinations, assistance-listings or exclusions (no solicitation number on those records — the run stops and says so rather than billing an unfiltered set)
minAwardAmount / maxAwardAmountintegerDollar range on award.amount, inclusive, either side usable alone. SAM.gov only supports an exact award-amount match and rejects range syntax, so applied by the Actor after fetch and before charging, same as the date windows above. award.amount is null until a notice is awarded — pair with noticeTypes: ["a"] or most rows drop as awardAmountMissing. Opportunities only
organizationIdstringRestrict to one issuing department/agency/office by SAM organization id. Opportunities and assistance-listings only
activeOnlybooleanOnly opportunities still open for response — for wage determinations, only determinations currently in force; for assistance-listings, only currently-active programs (default true)
enrichDetailbooleanJoin each row with NAICS / set-aside / place of performance / contacts (default false). Opportunities only
includeIncumbentAwardsbooleanAttach the top 3 USAspending contract awards for each opportunity's NAICS code (and agency, when recognised) as incumbentAwards — who holds this work now (default false). Turns enrichDetail on automatically, since NAICS is not on the search row. Not billed separately. Opportunities only; stops the run on other data types
incumbentYearsintegerIncumbent look-back in years, 1–10 (default 3), clamped rather than refused. Matched against each award's last-modification date, not its start date — see the FAQ. Only used when includeIncumbentAwards is on
includeAttachmentsbooleanList each notice's attachments — name, size, MIME type, direct no-login download URL (default false). Opportunities only
maxResultsintegerCap on rows returned (default 200)
watchLabelstringOptional. Name a saved search to get only records new since your last run under that label — see FAQ
watchChangesbooleanOptional, requires watchLabel. Also re-deliver an already-seen record if a watched field changed — for opportunities: isActive, noticeTypeCode, responseDate, modifiedDate, modificationsCount, awardeeName or description; for wage determinations: revisionNumber, isActive or modifiedDate; for assistance-listings: isActive, isFunded, modifiedDate or historicalIndexCount (default false) — see FAQ
webhookUrlstringOptional. POST a small JSON completion summary (opportunities pushed, rows scanned, dataset ID, watch new/changed/skipped counts) here when the run finishes — see FAQ

Sample output row

{
"opportunityId": "c8092b56b2c14be9bea3ac6081207963",
"title": "This is a sources sought to identify contractors who possess the capabilities to provide CFE and associated EACs produced using domestically-manufactured solar panel systems.",
"solicitationNumber": "47PA0723SS0001",
"cleanSolicitationNumber": "47PA0723SS0001",
"noticeTypeCode": "r",
"noticeType": "Sources Sought",
"isActive": true,
"isCanceled": false,
"publishDate": "2023-07-12T19:23:54+00:00",
"modifiedDate": "2023-07-12T19:23:54+00:00",
"responseDate": "2023-06-27T20:00:00+00:00",
"responseDateActual": "2023-06-27T16:00:00-04:00",
"responseTimeZone": "America/New_York",
"department": "GENERAL SERVICES ADMINISTRATION",
"agency": "PUBLIC BUILDINGS SERVICE",
"office": "PBS R00 CPF CLEAN ENERGY",
"description": "<p><strong>THIS IS A SOURCES SOUGHT ANNOUNCEMENT ONLY - </strong>A solicitation is not available at this time...",
"awardeeName": null,
"awardeeUeiSAM": null,
"awardAmount": null,
"modificationsCount": 0,
"sourceUrl": "https://sam.gov/opp/c8092b56b2c14be9bea3ac6081207963/view",
"naicsCodes": ["221122"],
"setAside": null,
"placeOfPerformanceState": null,
"placeOfPerformanceCountry": "USA",
"pointOfContact": [
{ "name": "Bonnie Bueter", "email": "bonnie.bueter@gsa.gov", "phone": "202-227-1635", "type": "primary" }
],
"attachments": [
{
"name": "Domestic Solar Sources Sought.pdf",
"mimeType": ".pdf",
"sizeBytes": 66900,
"postedDate": "2023-05-23T17:41:41.033+00:00",
"downloadUrl": "https://sam.gov/api/prod/opps/v3/opportunities/resources/files/127fca9028ef46ebb6f4f57863fe12e7/download"
}
]
}

Pricing

One event, no Actor-start fee, same flat $0.0015 per row across all four dataTypes (opportunities, wage determinations, assistance listings/CFDA, exclusions).

Verified live 2026-10-01 against every live SAM.gov-niche listing on the Store with real traction — re-enumerated this cycle via a fresh Store search rather than re-checking only the rivals already named (the prior 2026-09-30 pass used a narrower search term and missed the niche's two biggest listings by user count). jungle_synthesizer/samgov-scraper (171 users) is the Store's actual user-count leader here, not scrapebench — and it ships the same four-dataset scope as this Actor (opportunities, exclusions, wage determinations, assistance listings), so the "unlike this Actor's 4-dataset scope" framing below applies only to the smaller rivals, not to it. It tiers $0.001/row (FREE/BRONZE) down to $0.0008 (GOLD+) plus a $0.0001 Actor-start fee — cheaper than our flat $0.0015 at every tier. scrapesage/sam-gov-scraper (55 users, re-verified live 2026-10-28, 24 in the last 30 days — the niche's busiest by recent activity) is opportunities-only: $0.0025/row on FREE tapering to $0.00063 on DIAMOND, undercutting us above the SILVER tier, and it also ships a PSC-code filter we lack. Both rivals, like this Actor (includeAttachments, added cycle 1133), offer an attachment-download feature — no longer a gap here, though their exact implementation hasn't been diffed against ours field-for-field. fortuitous_pirate/sam-gov-scraper (129 users) is opportunities-only at a flat $0.003/row plus a $0.01 Actor-start fee — pricier than us at every tier. magicfingers/sam-gov-scraper (43 users) is genuinely FREE — no pricing record at all. Of the previously-named rivals: scrapebench/samgov-opportunity-alert (29 users) still charges a flat $0.0025/opportunity, no start fee; bovi/sam-gov-opportunities-scraper (verified live 2026-10-05) still tiers $0.0025 down to $0.002375 plus a $0.00005 start fee and still requires the buyer's own SAM.gov API key, which this Actor does not; publicmoney/sam-gov-opportunity-scraper still tapers to $0.0007/tender on DIAMOND (plus its own bizarre $0.5–$1 "schema.org block" event we don't charge at all); maydit/sam-gov-opportunities-scraper still tapers to $0.0012 on GOLD and above. agentready ($0.0019+start), practicalmodules ($0.0025 flat) and two more newly-priced listings, pink_comic/sam-gov-contract-opportunities (30 users, $0.002/row + $0.0001 start) and omarchydev/government-contract-monitor (33 users, a bundled AI-analysis product billing $0.02/contract plus per-feature add-on events, not a comparable per-row price), all price above us. We are not the cheapest in this niche — jungle_synthesizer and scrapesage both undercut us on volume, and publicmoney/maydit undercut us once a buyer reaches their top tier. Our case is covering all four datasets with no API key, no start fee, and the watch-mode/attachment features below — not being the single cheapest listing.

Verified live 2026-10-02, re-swept with the broader sam.gov term (the fleet's post-1124 lesson that a narrow search term silently caps a niche audit, applied here too) rather than re-checking only the rivals already named above — 18 listings with real traction, surfacing 6 rival Actors never priced in this file before. Three are genuine undercutters: automation-lab/samgov-government-contracts-scraper stacks a $0.005 Actor-start fee on a tiered per-row rate from $0.000115 (FREE) down to $0.000028 (DIAMOND) — the start fee amortizes by about row 4 at every tier, after which it undercuts our flat $0.0015/row for the rest of the run. automation-lab/sam-gov-entity-exclusions-scraper is the same $0.005-start-plus-tiered-item shape ($0.0000381 FREE down to $0.00001 DIAMOND), scoped to the exclusions dataset only — same ~row-4 crossover, but it covers one of our four dataTypes, not all four. alizarin_refrigerator-owner/sam-gov-contracts---federal-opportunities-search prices its dataset item at just $0.00001/row, but that sits behind a $0.10 Actor-start fee plus a $0.01 per-search-type event (one of six: opportunity/NAICS/agency/set-aside/award/solicitation search) — at least $0.11 charged before a single row is counted, so it only overtakes our flat rate above roughly 74 rows per run; we are cheaper on every smaller run, which covers the common keyword-filtered pull. Five more price above us at every volume and are named for completeness, not as a threat: taroyamada/procurement-intel-actor (20 users, $0.008/row), inexhaustible_glass/federal-contractor-intelligence ($0.01 start + $0.005/row), cblu/sam-gov-contract-opportunities-scraper ($0.004/row flat), signalcrawl/sam-gov-contract-monitor ($0.00005 start + $0.002/row) and shipsatnight/sam-gov-contract-scraper ($0.00005 start + $0.002/row). upward_enterprises/sam-gov-contract-radar ties us at its FREE tier ($0.002/row) and undercuts us from GOLD+ ($0.0012, then $0.0006 on its second tiered event) — a real rival rate, but a 3-user listing moves nothing yet. None of the 9 widens the "we are not the cheapest" admission above; jungle_synthesizer and scrapesage remain the two rivals that beat us on volume at every tier, and automation-lab's two listings now join them above row 4.

Verified live 2026-10-03, re-swept sam.gov with the Store search limit raised from the default 20 to 60 — 54 listings came back instead of 18, almost entirely 2-user micro-listings (relevance ranking had been cutting the sweep off before reaching them). All 13 previously-named rivals re-verified live straight from pricingInfos, zero price drift on any of them. One filed-but-not-yet-effective change found: fortuitous_pirate/sam-gov-scraper's Actor-start fee drops from $0.01 to $0.005 on 2026-10-13 (its per-row $0.003 is unchanged); even after the cut it stays pricier than us at every tier, so no competitive-position change — re-read on/after that date rather than treating it as new. Three genuine new undercutters disclosed from the widened sweep, all 2-user listings: yourwingman/usa-federal-contracts-scraper charges a flat $0.0005/row plus a $0.00005 start fee — a third of our rate at every volume, the largest undercut found in this niche after jungle_synthesizer/scrapesage. factpipe/sam-gov-contracts tiers $0.002 (FREE) down to $0.0014 (GOLD and above) with no start fee, undercutting us from GOLD+. bakos_bence/sam-gov-opportunities tiers its per-row rate lower still ($0.00249 down to $0.001245 GOLD+) but stacks a $0.02 (FREE/BRONZE) to $0.003 (GOLD+) Actor-start fee, so it only overtakes our flat rate past roughly 12 rows/run on GOLD and above — dearer below that and on lower tiers. Two more tie our rate exactly rather than undercutting it: adobeflex/sam-opportunities-lite ($0.0015/row primary event, plus a separate $0.001 "search run" event and a $0.00005 start fee that make it dearer in practice) and andrew_avina/federal-contracts-mcp (flat $0.0015/row, no other fees — a genuine exact tie). Deliberately left unpriced as out of this Actor's scope, not an oversight: wage-determination-only (wishbone_data/davis-bacon-wage-determinations), exclusions-only (nexgendata/sam-gov-federal-contractor-exclusions, maximedupre/sam-gov-exclusions), contractor lead-gen/registration monitoring (lead.gen.labs's three listings), a bundled amendment-detection product (blaidlink/sam-opportunity-fit-amendment-monitor, $0.02-$0.03/event), and multi-country tender aggregators that merely mention SAM.gov alongside EU TED/UK listings (practicalmodules, gazidev/global-tender-alerts, chorelet/government-tenders-scraper, snow_leo_data/government-tenders-scraper, apeye/government-tenders-api) — none read all four of this Actor's dataTypes as a SAM.gov-specific product. Updated bottom line: jungle_synthesizer, scrapesage and now yourwingman undercut us at every tier; publicmoney/maydit/upward_enterprises/factpipe/bakos_bence undercut us only from their upper tiers or past a row-count crossover. We remain not the cheapest in this niche at any realistic volume — the case is four-dataset coverage, no API key and no start fee, not price leadership.

Verified live 2026-10-03 (second pass, 15-term sweep instead of one search term) — the prior passes all searched the single phrase sam.gov, which caps the sweep at whatever that one query ranks. This pass swept 15 hand-curated terms covering SAM.gov's own names for the four domains this Actor's dataType reads (contract opportunities, wage determinations, assistance listings, entity exclusions), the portal's dead predecessor name (FBO.gov), and the buyer-side words (RFP, solicitation, set-aside/NAICS, bid alerts): 484 distinct listings seen, 137 mentioning SAM.gov or one of those four domains (97 if only names/titles are counted), against the 54 the one-term pass saw. 105 of the 137 were never priced in this file before — nearly all are 2-user micro-listings, and the 14 with the most traction or the most head-on scope were all priced live from pricingInfos.

  • One genuinely free rival, and it is the biggest listing this file had never named: martc03/gov-contracts-mcp has no pricing record at all — public, not deprecated, confirmed three times live. On Apify's free model that is $0/row, cheaper than anything anyone can charge, so it is the cheapest listing in this niche by definition. It is packaged as an MCP server for contracts and procurement rather than a dataset scraper, and its zero 30-day users suggest it is not actually being used, but on price alone there is nothing to beat.
  • One marginal undercutter: ahmed_jasarevic/sam-scraper advertises "Only $1.5/1K" in its own title and lives up to it — tiered $0.0015/row (FREE) to $0.00147 (GOLD and above), so it ties our flat rate on the lower tiers and undercuts it by 2% on the upper ones. It also charges a $0.0005 Actor-start fee, which we do not, so on GOLD+ it only actually costs less past roughly 17 rows per run; below that we are cheaper, and on FREE/BRONZE/SILVER we are cheaper at every volume.
  • Twelve more price above us, named for completeness: technicaldost/government-bid-tracker ($0.005/result + $0.00005 start), parseforge/government-contract-awards-scraper ($0.01599 → $0.01199 + $0.005 start, and award-scoped rather than opportunity-scoped), fascinating_lentil/global-government-contracts-aggregator ($0.002/contract + $0.00005 start, UK/EU/US bundle), parseforge/us-gov-contract-watch-scraper ($0.0075 → $0.006675/result plus a separate $0.005 → $0.00445 event for the SAM.gov attachment/detail lookup that our includeAttachments does not charge for), lowlanddata/us-rfp-monitor ($0.003 → $0.0024 per baseline row but $0.02 → $0.016 per new-RFP alert + $0.0005 start), kantolabs/sam-gov-contract-opportunities ($0.003/opportunity + $0.00005 start), labrat011/gov-contracts-scraper ($0.005/result + $0.00005 start today, start fee rising to $0.005 on 2026-10-10), georgy.malanichev/govtender-scraper ($0.003/result behind a $0.50 Actor-start fee, the largest start fee seen in this niche), mooseandraven/samgov-federal-contracting-suite ($0.004/opportunity + $0.003/exclusion + $0.005/batch-screen + $0.05/monitor-run — its "No Start Fee" title claim is true, but it is 2.7x our rate and covers two of our four datasets), splendorous_astrolabe_xs9/govcon-monitor ($0.003/record flat, no start fee), viralanalyzer/sam-gov-contracts-watcher ($0.01 FREE tapering to $0.003 DIAMOND — still 2x us at its cheapest tier) and thoob/sam-opportunities-feed ($0.01/opportunity flat).
  • A note on the watch-mode rivals specifically, since that is this Actor's main non-price feature: lowlanddata charges 6.7x its own baseline row rate for an alert row, and parseforge/us-gov-contract-watch-scraper bills attachments as a second event. This Actor charges the same $0.0015 for a watchChanges re-delivery as for a new row, and nothing extra for includeAttachments.
  • Bottom line unchanged in substance, with one addition: jungle_synthesizer, scrapesage and yourwingman still undercut us at every tier, publicmoney/maydit/upward_enterprises/factpipe/bakos_bence/ahmed_jasarevic only from their upper tiers or past a row-count crossover, and magicfingers/sam-gov-scraper plus now martc03/gov-contracts-mcp are free. We are not the cheapest listing in this niche and do not claim to be — the case is four-dataset coverage, no SAM.gov API key, no Actor-start fee, and the watch/attachment features above.

Verified live 2026-10-04 — every listing this file had never named, priced at any user count rather than above a user-count floor. 484 listings seen on the same 15-term sweep, 139 mentioning SAM.gov or one of the four dataType domains, 93 of them not named anywhere above. Only 3 of those 93 had 3+ users and all 3 were non-SAM.gov tender products (artificially/eu-tenders-scraper, fortuitous_pirate/canadabuys-scraper, logiover/global-public-tenders-scraper), so a user-count cut would have priced only non-substitutes; all 93 were live-priced from pricingInfos instead, reading each tiered block explicitly. Our own live price was re-read first: flat $0.0015/row, one result event, no start fee, no tiered block, zero drift against meta.json. Findings:

  • Three new undercutters that beat us at essentially every volume. acid-base/borg-sam-contract-opportunities charges a flat $0.0005/row with no start fee — one third of our rate at every volume, and it makes this Actor's exact pitch (SAM.gov's public Data Services, no login, no API key). It now ties yourwingman/usa-federal-contracts-scraper as the cheapest flat per-row rate found in this niche. bridged/sam-gov-opportunities-api charges a flat $0.001/opportunity with no start fee and no second event at all — the cleanest sub-our-rate listing here, scoped to solicitations/RFPs/sources-sought off SAM.gov's official Get Opportunities API. gochujang/gov-contract-tracker charges $0.001/row plus a $0.001 once-per-run start fee, so it is dearer only on a 1-row run and cheaper from about 3 rows up; it also ships keyword/NAICS/agency/set-aside/date filters comparable to ours.
  • Four more undercut us only from a tier or a row-count crossover. publicrecords/govcon-opportunity-feed tiers $0.002 (FREE) down to $0.0014 from GOLD — cheaper than us on GOLD and above only, dearer on FREE/BRONZE/SILVER, and its new-since-last-run delta-record ($0.02) and incumbent-record ($0.01) events cost far more than our flat $0.0015 for a watchChanges re-delivery. sigma-dev/usa-government-contract-scraper charges $0.001/row behind a $0.05 once-per-run start fee, so it only overtakes our flat rate past roughly 100 rows per run. oswaldocarabano/sam-gov-data-scraper is dearer on notices ($0.0025/notice, 1.67x us) but charges just $0.0005 per exclusion record and per attachment — a genuine 3x undercut on one of our four dataTypes, and the only rival found that prices exclusions separately below our flat rate. jungle_synthesizer/dol-oflc-prevailing-wage-determination-scraper (listed 2026-10-01 — a second listing from the niche's user-count leader) tiers $0.001 down to $0.0008 on wage determinations, under our flat rate at every tier; it reads DOL OFLC prevailing-wage determinations (the H-1B/PERM/H-2B wage floor), not the SCA/DBA wage determinations SAM.gov publishes, so it is a price anchor for wage-data buyers rather than a substitute for our dataType: wageDeterminations.
  • Correction, verified live 2026-10-05: leadharbor/sam-gov-vendor-screening is gone from the Store (404 on its own API record). The 2026-10-04 pass named it as a free exclusions-screening rival; it no longer exists, so it is not a live price comparison and should not be cited as a free alternative.
  • One near-parity rival worth naming: artificially/samgov-opportunities-scraper tiers $0.00225 (FREE) down to $0.001575 from GOLD — dearer than us at every tier, but only by 5% at the top, the closest same-scope price to ours in the niche. It also advertises contracting-officer emails/phones, attachments and a new-notices-only monitor, i.e. our feature set.
  • Ruled out by scope rather than by price, so a later audit does not re-price them: zentrafoundry/govcon-grants-bid-intelligence ($0.02/qualified tender, and its own description says SAM.gov still requires the buyer's API key — it is a TED/grants product), lead.gen.labs's three contractor-registration lead listings (the $0.00001 apify-default-dataset-item on them is vestigial; the real charge is $0.019/profile behind a $0.05 start fee), adobeflex/worldbank-procurement-lite, aicatraz/gov-rfp-aggregator-mcp and rl1987/samgov-mcp (MCP tool-call billing, not per-row), plus the EU/Canada/global tender aggregators above. The remaining ~70 priced listings are dearer than $0.0015/row at every tier and changed nothing.
  • Bottom line, updated: jungle_synthesizer/samgov-scraper, scrapesage, yourwingman, and now acid-base, bridged and gochujang undercut us at every realistic volume; publicmoney/maydit/upward_enterprises/factpipe/bakos_bence/ahmed_jasarevic/publicrecords/sigma-dev only from an upper tier or past a crossover; oswaldocarabano only on exclusions; magicfingers and martc03/gov-contracts-mcp are free (leadharbor, previously named free here, is gone from the Store as of 2026-10-05). We are not the cheapest listing in this niche, at any volume, and do not claim to be — the case is all four dataTypes in one Actor with no SAM.gov API key, no Actor-start fee, watch mode and attachment links at no extra charge.

Verified live 2026-10-05 — full-cohort re-sweep, one day after the 2026-10-04 pass above. bin/niche-unnamed found the niche had grown slightly (140 matched vs 139 the day before) with 80 still-unnamed listings; only 1 of the 80 (accountable_eel/sam-gov-opportunity-alerts, 3 users) cleared a 3-user cut, so — per the standing full-cohort rule — all 80 were live-priced from pricingInfos rather than just that one. Our own live price was re-read first and is unchanged: flat $0.0015/row, no start fee. Three genuine new findings, none named anywhere above:

  • One more free rival: artificially/business-data-mcp has no pricing record at all — $0/run. It is a bundled MCP server covering gov contracts, jobs, LinkedIn and leads together, not a SAM.gov-specific scraper, but on price alone nothing beats free.
  • One real per-row undercutter, but dormant: fetch_cat/sam-gov-contract-opportunities-monitor charges a $0.005 once-per-run start fee plus a tiered item price from $0.000115/row (FREE) down to lower tiers — about 13x cheaper than our flat rate once the start fee amortizes around row 4, but it has had no runs in 30 days.
  • One modest undercutter: vhsgreed/us-federal-contracts charges a $0.002 once-per-run start fee plus $0.00125/row (FREE tier, tapering to $0.00095 from GOLD) — about 17% cheaper per row than us, crossing over after roughly 2 rows.
  • The remaining 76 of the 80 confirmed dearer or out of scope — including second_coming/gov-contract-monitor, which bills a flat $0.02 per scan run rather than per row and is not a comparable substitute. No need to re-price them; this line is the record that they were checked at this cycle.
  • Bottom line unchanged in substance: jungle_synthesizer/samgov-scraper, scrapesage, yourwingman, acid-base, bridged and gochujang still undercut us at every realistic volume; the three new findings above join the "free" and "crossover" groups rather than displacing the leaders. We remain not the cheapest listing in this niche, at any volume, and do not claim to be.

Verified live 2026-10-06 — full-cohort re-sweep, one day after the 2026-10-05 pass above. bin/niche-unnamed found the niche had grown again (145 matched vs 140 the day before) with 80 still-unnamed listings (zero cleared a 3-user cut this time), so — per the standing full-cohort rule — all 80 were live-priced from pricingInfos. Our own live price was re-read first and is unchanged: flat $0.0015/row, one result event, no start fee. Result: clean, zero new findings — no free rivals, no undercutters among any of the 80 (every primary-event tier, where tiered, priced at or above $0.0015). Also spot-checked the six headline undercutters named above directly against their live pricingInfos rather than trusting yesterday's record: jungle_synthesizer ($0.001 FREE/BRONZE → $0.0008 GOLD+), scrapesage ($0.0025 FREE → $0.00063 DIAMOND), yourwingman ($0.0005/row + $0.00005 start), acid-base ($0.0005/row flat), bridged ($0.001/row flat) and gochujang ($0.001/row + $0.001 start) — all six unchanged, zero drift. Bottom line stands exactly as above.

Verified live 2026-10-07 — full-cohort re-sweep, one day after the 2026-10-06 pass above. bin/niche-unnamed found the niche flat at 145 matched (same as the day before) with 81 still-unnamed listings (one more than the 80 on 2026-10-06); zero cleared a 3-user cut, so — per the standing full-cohort rule — all 81 were live-priced from pricingInfos, this time via a tier-ladder-aware pricer (the cycle-1350/1356 method: score every tier, not just the FREE-tier headline, and separate one-time Actor-start events from the per-row rate in code). Our own live price was re-read first and is unchanged: flat $0.0015/row, one result event, no start fee.

  • One real undercutter, scoped differently: jtpalms/gov-tenders-monitor tiers $0.001/row (FREE/BRONZE) down to $0.0008 (GOLD+) plus a $0.00005 start fee — under our flat rate at every tier — but it is a four-country tender aggregator (CanadaBuys, UK Find a Tender, EU TED, plus SAM.gov) and its own description says the SAM.gov portion needs "your own key"; this Actor needs none. On price alone it beats us; on the no-key, SAM.gov-only case this Actor targets, it doesn't apply.
  • Two more reach or cross our rate only from an upper tier: steadydata/sam-gov-contract-opportunities tiers $0.002 (FREE) down to $0.0013 (GOLD and above), no start fee, no API key, reading the same GSA daily public extract this Actor does — undercutting us from GOLD+. optimistprime/federal-contract-opportunities-monitor ties our rate exactly on FREE ($0.0015, matching its own "$1.5/1k" headline), undercuts slightly on BRONZE ($0.0014), then drops to $0.0012 from SILVER up.
  • Three ruled out by scope, not price: tagadanar/usaspending-federal-awards reads USAspending.gov award/grant/loan/payment records, not SAM.gov's open-opportunity listings — a different dataset despite advertising "no SAM.gov login, no API key." automation-lab/grants-gov-funding-opportunities-scraper and soilair/grants-gov-api are both Grants.gov tools — this Actor's sibling grants-gov-scraper's niche, not this one.
  • Four more resolved by hand after the pricer flagged them AMBIGUOUS (each pairs an apify-actor-start event with exactly one other recurring event, but neither carries an isPrimaryEvent flag on this API record, so the tool refused to guess which one is the per-row rate rather than mis-pick): waags/sam-gov-contract-opportunities ($0.004 start + $0.00175/row), civic-data-tools/public-bid-search ($0.00005 start + $0.005/bid record), chimerical_quicklime/sam-gov-opportunity-monitor ($0.005 start + $0.01/opportunity, matching its own "$10 per 1,000 alerts" line) and ambolt/sam-gov-opportunities ($0.005 start + $0.002/notice, matching its own "$0.002/notice" title) — all four dearer than us at every volume once hand-read.
  • The remaining 71 of the 81 confirmed dearer or out of scope by the same pricer run; no need to re-price them individually, this line is the record that they were checked this cycle.
  • Bottom line unchanged in substance, with two additions: jungle_synthesizer/samgov-scraper, scrapesage, yourwingman, acid-base, bridged, gochujang and now jtpalms/gov-tenders-monitor (own-key, multi-country caveat above) undercut us at every realistic volume; publicmoney/maydit/upward_enterprises/factpipe/bakos_bence/ahmed_jasarevic/publicrecords/sigma-dev/steadydata/optimistprime undercut only from an upper tier or past a crossover; oswaldocarabano only on exclusions; magicfingers, martc03/gov-contracts-mcp and artificially/business-data-mcp are free. We remain not the cheapest listing in this niche, at any volume, and do not claim to be — the case is all four dataTypes in one Actor with no SAM.gov API key, no Actor-start fee, and the watch/attachment features above.

Verified live 2026-10-08 — full-cohort re-sweep, one day after the 2026-10-07 pass above. bin/niche-unnamed found the niche had grown again (151 matched vs 145 three days before) with 77 still-unnamed listings (76 of 77 at 2 users or fewer); only the same two 3-user listings already ruled out above (parseforge/sam-gov-wage-determinations-scraper, wage-determinations-only at $0.00445–$0.005/row; pink_comic/federal-grant-awards, USAspending grant-award data not SAM.gov opportunities) cleared a 3-user cut, so — per the standing full-cohort rule — all 77 were live-priced via a tier-ladder-aware pricer, 0 unresolvable, 0 ambiguous. Result: 0 of 77 undercuts us at any tier, 0 free-model rivals, 0 future-dated price changes. One new exact tie: kadi_bence/sam-gov-scraper (2 users) prices its single opportunity event at exactly our $0.0015/row, but stacks a $0.00005 Actor-start fee we don't charge, so it is dearer than us in practice at every volume — the same "ties on the headline rate, loses on the start fee" shape as adobeflex/sam-opportunities-lite and optimistprime/federal-contract-opportunities-monitor above. The other 75 of 77 price dearer or are out of scope (freelancer-jobs-scraper clones, Grants.gov/USAspending tools, OFAC sanctions screening, EU TED aggregators). Bottom line unchanged in substance.

Verified live 2026-10-09 — full-cohort re-sweep (150 matched, 73 unnamed, same thin cohort, max 2 users) plus, for the first time on this niche, an every-event-every-tier scan of every rival's secondary (non-selected) charge events, not just the one headline event each pricer run already picks. The per-row resweep is unchanged in substance: 0 of 73 undercuts us at any tier, 0 free-model rivals, 0 future-dated changes. The secondary-event scan raised 7 raw hits, all false positives or out of scope once read: cleanpull/public-tenders-tracker and neverempty/sam-gov-opportunities-monitor's cheap events are both a monitoring "nothing changed" check (notice-checked, search-checked) that bills once per poll, not once per row — their real primary events (notice-result $0.002, opportunity-returned $0.0025) are dearer than us; george.the.developer/federal-contract-opportunity-monitor's is an unflagged actor-start one-time fee by name, behind a $0.1/row primary event. piotrv1001/sam-gov-tenders-scraper's amendment-history ($0.001) is its own opt-in add-on for pulling a notice's full amendment trail, not the per-row rate (tender, $0.002, is). thisisb3/sam-gov-contracts-scraper's award event ($0.0012–$0.0015) bills USAspending contract-award records, not SAM.gov opportunity notices — the same different-dataset distinction this README already draws for tagadanar/usaspending-federal-awards above; its own opportunity event ($0.002–$0.0016) is the comparable unit and is dearer. lead.gen.labs/sam-gov-active-federal-contractor-leads's cheap event is the platform-default dataset-item charge beside its real named rate, and the Actor itself is GSA contractor-profile data, out of scope regardless. tagadanar/us-grants-monitor is a Grants.gov/NIH tool (this Actor's sibling niche), out of scope on title and description alone. 0 genuine undercutters found this way either.

Verified live 2026-10-23 — competitor_audit resumed after a 2-week gap (last pass 2026-10-09), full-cohort re-sweep. Own price re-read first: flat $0.0015/row, one result event, no start fee — unchanged, 0 drift against meta.json. niche-size's 15-term sweep found real growth, 150 → 229 matched listings (2,025 distinct listings seen across the sweep). niche-unnamed: 148 of the 229 unnamed (133 NONE / 15 OWNER); all 133 NONE live-priced via the durable tier-ladder-aware pricer bin/_batch_price_sgos2.py, 0 unresolvable, 4 AMBIGUOUS (no-primary-flag event lists) hand-read below.

Six genuine new undercutters, none named above:

  • j0401/sam-gov-contracts (2 users) is the standout: a flat $0.00005/notice tapering to $0.00003 (GOLD+), no start fee — 30x–50x under our rate at every tier, reading the same SAM.gov notice index this Actor does (solicitations, presolicitations, sources sought, awards, special notices), no API key required, matching our own pitch almost exactly.
  • tiger19935/sam-gov-usaspending-contracts (2 users) tiers $0.001 (FREE) down to $0.0007 (GOLD+) on its opportunity-record event, no start fee — cheaper than us at every tier; its separate USAspending award-record event ($0.002→$0.0014) is a different dataset and not compared against our flat rate.
  • usefulapi/sam-gov-opportunities (2 users, titles itself "USD 1/1,000") bills a flat $0.001/notice behind a $0.005 start fee off "SAM.gov's own public daily file" (this Actor's exact backend) — the start fee amortizes by about row 11, after which it undercuts us for the rest of the run.
  • owlabee/gov-opportunity-feed (2 users, a Grants.gov+SAM.gov+USAspending combo already named in our grants-gov-scraper README) bills its SAM.gov opportunity-scraped event at $0.001 behind a $0.00005 start fee — cheaper than us from row 1.
  • badboxx_newlife/sam-gov-grants-gov-scraper (a SAM.gov+Grants.gov combo, also already named in grants-gov-scraper's README on its Grants.gov side) bills its single result event at $0.0009 behind a $0.005 start fee — the start fee amortizes by about row 9, after which it undercuts us by 40%.
  • ayuki/samgov-contract-opportunities (1 user) has no pricing record at all — $0/row on Apify's free model — but, like bovi/sam-gov-opportunities-scraper already named above, requires the buyer's own free SAM.gov API key, which this Actor does not.

Two partial undercutters: tabulary/sam-gov-contract-notices (2 users) ties our $0.0015 on FREE but stacks a $0.001 start fee there (dearer in practice on FREE, the same "ties on headline, loses on start fee" shape as kadi_bence/adobeflex above); from BRONZE ($0.00135) it undercuts us past row 7, and by DIAMOND ($0.00105) past row 3. rowcraft/sam-gov-contract-opportunities-scraper (2 users) is dearer at $0.002 on FREE/BRONZE/SILVER but drops to $0.0014 plus a $0.00005 start fee from GOLD+, undercutting us from row 1 at that tier and above.

Ruled out by scope, not price, so a later audit does not re-price them: amygraphics/usaspending-awards-scraper (its $0.0008/award-extracted rate is cheaper than our $0.0015, for the record) and the AMBIGUOUS listing's own award-record event above both read USAspending.gov's awards database — the same different-dataset distinction this README already draws for tagadanar/usaspending-federal-awards. opendatalabs/grants-gov-monitor (likewise cheaper on a $0.0012/opportunity headline rate) is a Grants.gov-only tool (our sibling grants-gov-scraper's niche; it matched this sweep only because its description uses the phrase "Assistance Listing" for a Grants.gov field, not SAM.gov's CFDA dataset).

4 AMBIGUOUS listings (no isPrimaryEvent flag) hand-read, all ruled out dearer: factline/us-company-lookup-sec's cheap $0.00001 apify-default-dataset-item is the same vestigial-default-event shape already documented for lead.gen.labs above — its real charge is the $0.01 company-lookup event, dearer than us. signalscouter/us-federal-contracts-signals prices every one of its three events ($0.002–$0.005) above our flat rate. kempt_horizon_yzk/samgov-opportunities prices its opportunity ($0.004) and opportunity-enriched ($0.01) events above our flat rate.

Bottom line, updated — the "and now" names below were live-priced and verified 2026-10-23; every other name carries the date of its own pass above: jungle_synthesizer/samgov-scraper, scrapesage, yourwingman, acid-base, bridged, gochujang, jtpalms and now j0401, tiger19935, usefulapi and badboxx_newlife undercut us at every realistic volume (the first four unconditionally, the rest past a start-fee crossover); tabulary and rowcraft join the upper-tier/crossover group alongside publicmoney/maydit/upward_enterprises/factpipe/bakos_bence/ahmed_jasarevic/publicrecords/sigma-dev/steadydata/optimistprime; oswaldocarabano only on exclusions; magicfingers, martc03/gov-contracts-mcp, artificially/business-data-mcp and now ayuki (own-API-key caveat) are free. We remain not the cheapest listing in this niche, at any volume, and do not claim to be — the case is all four dataTypes in one Actor with no SAM.gov API key, no Actor-start fee, and the watch/attachment features above.

Correction, verified live 2026-10-28 — a false claim about our own product, caught while feature-comparing the two biggest price threats above. Four prior "Bottom line" paragraphs on this page (2026-10-01 through 2026-10-23) credited this Actor with "the date-window" or "two-sided date window" feature alongside watch mode and attachments. There is no such feature: this Actor's input schema has no postedFrom/postedTo or deadline-range field, and the FAQ above has said so all along ("Not on this backend — it exposes no postedFrom/postedTo equivalent"). All four mentions are corrected in place rather than left to mislead a future sweep. The real gap runs the other way: both j0401/sam-gov-contracts and tiger19935/sam-gov-usaspending-contracts — the two biggest price threats named above — were checked live against their own current input schemas (not just their prices) for the first time this cycle, and both ship real postedFrom/postedTo and response-deadline-range filters that this Actor does not. tiger19935 also adds minAwardAmount/maxAwardAmount and incumbent-award lookback on its USAspending side; j0401 adds a solicitationNumber substring lookup, a single-notice noticeId mode and a groupBy aggregate mode (department/state/NAICS/month) that this Actor's own dataType-only scope doesn't offer. Neither rival's description or schema claims an attachment-download or saved-watch feature, so those two remain real, undiluted advantages on our side — just not a "date window" that never existed. Not fixed this cycle, filed as a follow-up below: this Actor already fetches and returns publishDate/modifiedDate/responseDate on every opportunity row, so adding real postedFrom/postedTo/deadlineFrom/deadlineTo as a client-side post-filter (drop rows outside the window before they're pushed and charged) would close this gap without any new upstream request — scoped as a code change, not a docs fix, so left for a dedicated BUILD cycle rather than rushed in here.

Follow-up closed, verified live 2026-10-28 (build 0.1.74). The gap above is now actually fixed rather than claimed: postedFrom/postedTo/deadlineFrom/deadlineTo exist in the input schema and are enforced in src/main.js as a pre-charge post-fetch filter, so the feature described in the FAQ and in the bullet near the top of this page is the feature the code implements — the specific thing that was false before. Verified by real runs, not by reading the diff: a postedFrom/postedTo run returned 5 of 26 fetched rows with every delivered publishDate inside the window; a deadlineFrom/deadlineTo run returned 6 of 47 with every delivered responseDate inside it (including a boundary row exactly on deadlineTo, confirming inclusivity) and correctly dropped 15 rows whose responseDate was null rather than passing them through unverified; an exhaustive walk (176 declared, 134 dropped by the window) reported COMPLETE instead of the false short-page shortfall the pre-window reconciliation logic would have produced; and all four refusal paths — unreadable date, reversed window, deadlineFrom on wage determinations, postedFrom on exclusions — stopped the run pre-request with the stated reason. What this does not close: j0401's solicitationNumber substring lookup, single-noticeId mode and groupBy aggregates, and tiger19935's minAwardAmount/maxAwardAmount and incumbent-award lookback, all still real rival features this Actor does not have.

Second follow-up closed, verified live 2026-10-28 (build 0.1.23) — the solicitationNumber half of j0401's gap above is now also fixed. Before building, SAM.gov's own solnum-style query parameter was probed live and confirmed to be silently ignored (not a real filter) — see notes/LEARNINGS.md cycle 2394. Shipped as a pre-charge post-fetch exact-match filter instead, same family as the date windows: the value is sent as the search keyword to scope the walk (overriding keyword if also set), then any fetched row whose own cleanSolicitationNumber (SAM.gov's punctuation-stripped form) doesn't case-insensitively match is dropped before pushResult(). Verified by real runs at row level: a lookup for a real, dashed solicitation number returned 3/3 rows all carrying the exact matching cleanSolicitationNumber; a deliberately near-miss raw value sent straight to q (unstripped) picked up a false-positive neighbour (confirming why the value is cleaned before being sent upstream, not just before being compared); a weak 4-digit substring lookup correctly walked to SAM's 10,000-row depth cap, dropped 9,574 non-matching and 424 no-solicitation-number rows, and delivered only the 2 that matched exactly; an unsupported-dataType input (wage determinations) and a punctuation-only value both stopped pre-request with no row delivered or charged. Still open: j0401's single-noticeId mode and groupBy aggregates, and tiger19935's minAwardAmount/maxAwardAmount and incumbent-award lookback.

Third follow-up, verified live 2026-10-28 (build 0.1.76) — an internal speed-up to the solicitationNumber lookup above, not a new rival-gap closure. Live probing (notes/LEARNINGS.md cycle 2396) found that SAM.gov's search backend does honour one real server-side exact-match parameter here, notice_id — it matches the solicitation number, not the 32-hex opportunity id its name implies, and it is case-sensitive and wants the raw punctuated value, unlike the cleaned/uppercased form this Actor sends as q. The Actor now tries notice_id=<your raw value> first, with one lightweight probe request guarded by the same dropped-filter-name canary every other server-side filter here gets (so a future SAM.gov change that silently stops honouring notice_id fails the run loudly instead of quietly turning "1 exact row" into the whole unfiltered index, billed in full); on a match, the real walk runs on notice_id and usually finishes in a single page. On no match it falls back to the existing q=<clean>-and-filter walk, byte-for-byte unchanged. Verified live on the real Apify platform: a known raw solicitation number matched via notice_id and delivered the exact row in one page; a lowercase variant of the same number correctly missed notice_id and fell back to the q=<clean> walk, delivering the identical row. This does not close j0401's single-noticeId mode (a different feature — looking up one opportunity by its own id, which has no search-by-id path at all and needs a separate detail-endpoint call) or its groupBy aggregates (closed as do-not-build, see notes/LEARNINGS.md cycle 2396 — SAM.gov's search exposes no aggregation capability); both remain open. (tiger19935's minAwardAmount/maxAwardAmount, named as still open when this paragraph was written on 2026-10-28, shipped later the same day in build 0.1.77 — see the FAQ.)

Fourth follow-up closed, verified live 2026-10-29 (build 0.1.79) — the last item on the rival-gap list above, tiger19935's incumbent-award lookback, now ships as includeIncumbentAwards/incumbentYears. This one reaches a second upstream rather than filtering SAM.gov's own rows: for each opportunity's NAICS code it queries api.usaspending.gov/api/v2/search/spending_by_award/ for the largest recent definitive contract awards and attaches them as incumbentAwards, so a capture manager sees who currently performs the work before deciding to bid. Both upstreams were probed live before any code was written (notes/LEARNINGS.md cycles 2399 and 2400), which caught three things a blind build would have shipped wrong: NAICS codes are not on SAM.gov's search row (so enrichDetail is forced on with a warning instead of returning silent nulls); USAspending's time_period matches an award's last-modification date, not its start date (disclosed in the schema, the run log, RUN_SUMMARY and the FAQ, rather than labelled "look-back" and left to mislead); and sending SAM.gov's own agency spelling — "VETERANS AFFAIRS, DEPARTMENT OF" — to USAspending's exact-match agencies filter returns 0 rows with no error, so an unrecognised department name falls back to a NAICS-only lookup (recorded per row in incumbentAwardsMatchedBy) rather than silently narrowing a buyer's results to nothing. Verified by real runs at row level, not by reading the diff: a 6-row award-notice run returned 3 real incumbents on every row across 2 unique NAICS+agency pairs (2 USAspending requests, 4 cache hits — the per-pair dedupe working), with DEPT OF DEFENSE and VETERANS AFFAIRS, DEPARTMENT OF both correctly resolved to their USAspending names; incumbentYears: 99 clamped to 10 and widened the window to 2016-10-29; and an exclusions run stopped pre-request with 0 rows delivered and 0 charged. With this, every feature gap found on tiger19935 and j0401 in the 2026-10-28 live comparison is closed except two deliberate non-builds: j0401's single-notice-by-id mode (no search-by-id path exists; the detail endpoint returns HTTP 401, not 404, for an unknown id, which generic error handling would misread as an auth failure — build only on buyer request) and its groupBy aggregates (closed as do-not-build: SAM.gov's search exposes no aggregation capability at all).

Verified live 2026-10-30 — competitor_audit resumed after a 347-cycle gap (last full pass 2026-10-23); confirmed genuinely due first by a full git-log grep of this Actor's history since then (incumbent-award lookup, date-window/solicitation-number fixes, status-clamp work — no hidden competitor resweep). Own price re-read first: flat $0.0015/row, one result event, no start fee — unchanged, 0 drift. niche-size's 15-term sweep found real growth, 229 → 278 matched listings (2,109 seen). niche-unnamed: 184 of 278 unnamed (167 NONE / 17 OWNER); all 167 NONE handles live-priced via bin/_batch_price_sgos2.py, 0 unresolvable, 3 AMBIGUOUS hand-read below. All 17 OWNER-section handles re-priced live under their own handles per the established lesson (an owner's existing ruleout doesn't automatically cover a new listing) — 16 of 17 dearer at $0.003–$0.021/row; the 17th, bovi/grants-scraper, undercuts at $0.0011 but is a Grants.gov tool (our sibling grants-gov-scraper's niche), ruled out by scope like the automation-lab/soilair pair above.

Nine genuine new undercutters, none named above — the largest single-sweep haul this niche has had since the 2026-10-23 pass (verified 2026-10-30):

  • tidyflowlabs/samgov-opportunities (2 users) tiers $0.0012 (FREE) down to $0.0008 (GOLD+), no start fee — under our flat rate at every tier, reading the same GSA public extract (RFPs, sources sought, awards) this Actor does.
  • chaptersoft/gov-contract-opportunities (2 users) bundles SAM.gov + EU TED + USAspending but prices its notice event (its own description: "Contract notice") at a flat $0.0005 (FREE) down to $0.00035 (GOLD+) — 67–77% under us at every tier, on a genuinely comparable per-notice unit.
  • openwell-data/federal-contract-opportunity-monitor (2 users) has no pricing record at all — a real $0 SAM.gov-scoped alternative (NAICS/keyword/set-aside/state filters, dedup, change-tracking), not a vestigial-default-event artifact.
  • loomwise/federal-opportunities (2 users, a SAM.gov+Grants.gov combo already named in grants-gov-scraper's README on its Grants.gov side) bills its SAM.gov event at a flat $0.0009 behind a $0.00005 start fee — 40% under us from row 1.
  • barefoot_grade/sam-gov-opportunities-scraper (2 users) prices its Opportunity event at $0.001/row behind a $0.005 start fee — dearer than us below roughly row 10, undercutting for the rest of the run above it.
  • actor-forge/public-tenders (2 users) is a five-country tender aggregator (UK, US via USAspending, Australia, Brazil, Ukraine) pricing its Notice event at $0.0012 behind a $0.00005 start fee — under our rate at every volume on price, but its own description says SAM.gov inclusion needs the buyer's own API key, the same caveat already carried for bovi/ayuki/jtpalms above; this Actor needs none.
  • jpopendata/us-sam-opportunities (2 users) tiers $0.002 (FREE) down to $0.0014 (GOLD/PLATINUM/DIAMOND) on SAM.gov's own contract-opportunities-and-awards extract — undercutting us only from GOLD and above, dearer on FREE/BRONZE/SILVER.
  • capable_coach/sam-gov-contract-opportunities (2 users) ties our rate on FREE ($0.0015) then tiers down to $0.0009 (GOLD+), undercutting from BRONZE up, behind a $0.001 start fee that amortizes within a few rows.
  • clearpath-data/us-federal-contract-opportunities (2 users) ties FREE/BRONZE at $0.0015 then undercuts from SILVER ($0.0012) down to $0.0009 (GOLD+), behind a negligible $0.00005 start fee.

One ruled out by scope, not price: jpopendata/us-federal-spending (2 users) prices its result event cheaper than us ($0.002 → $0.0014) but reads USAspending.gov federal spending awards (recipient, UEI, obligated amounts) — the same different-dataset distinction this README already draws for tagadanar/usaspending-federal-awards, not a substitute for SAM.gov's pre-award opportunity listings.

Three AMBIGUOUS listings (no isPrimaryEvent flag) hand-read, all ruled out dearer: scarlet_sheet/sam-gov-contract-opportunities prices its result event at $0.003, 2x us. data-done-right/government-contracts-finder prices both its opportunity and award events at $0.0022, 47% dearer. hamsmoothie/us-company-check is a KYB/vendor-verification product ($0.002–$0.008/company checked against state registries, contractor licensing and the SAM.gov exclusion list), not a contract-opportunities feed, and dearer regardless.

Bottom line, updated: jungle_synthesizer/samgov-scraper, scrapesage, yourwingman, acid-base, bridged, gochujang, jtpalms, j0401, tiger19935, usefulapi, badboxx_newlife, tidyflowlabs, chaptersoft and now capable_coach/clearpath-data undercut us at every realistic volume or from an early tier; tabulary/rowcraft/loomwise/barefoot_grade/actor-forge (own-key caveat)/jpopendata/us-sam-opportunities join the upper-tier/crossover group alongside the names from earlier passes; oswaldocarabano only on exclusions; magicfingers, martc03/gov-contracts-mcp, artificially/business-data-mcp, ayuki (own-key caveat) and now openwell-data are free. We remain not the cheapest listing in this niche, at any volume, and do not claim to be — the case is all four dataTypes in one Actor with no SAM.gov API key, no Actor-start fee, and the watch/attachment features above. (The "and now" names above were live-priced and verified 2026-10-30; every other name here carries the date of its own earlier pass.)

FAQ

Do I need a SAM.gov API key? No. The official api.sam.gov developer API does require a free registered key, but this Actor uses the unauthenticated backend behind sam.gov's own public search page instead. Nothing to register, nothing to rotate.

Is there a posted-date range filter? Yes, since build 0.1.74 (2026-10-28): postedFrom/postedTo on publishDate, and deadlineFrom/deadlineTo on responseDate (the response deadline), all YYYY-MM-DD and inclusive on both ends, each side usable on its own as an open-ended range. The backend still has none — SAM.gov's search API exposes no date-range parameter on any of these indices, so this is the Actor's own post-fetch filter, and the one thing worth understanding about it is where it sits: the row is fetched, then dropped before it is pushed or charged, so you are never billed for a row outside your window. What that does not buy you is a cheaper upstream walk — SAM.gov still serves every row matching your server-side filters (keyword, naicsCodes, states, …), so a narrow window over a broad keyword can hit the run's time budget before maxResults is filled. Keep the other filters narrow, and reconcile with RUN_SUMMARY: declaredMatches is SAM.gov's pre-window count, dateWindowDropped is what the window removed, and dateWindowMissing is rows whose own date field was absent or unreadable — those are dropped too, deliberately, because we won't bill you for a row we can't prove is inside the window you asked for. A run that delivers far fewer rows than declaredMatches for this reason is reported as COMPLETE, not short. An unreadable date (2026-02-31), a reversed window (postedFrom after postedTo), or a window on a dataType that has no such date (deadlineFrom on wage determinations, any posted window on exclusions) stops the run before the first request with an explanation instead of quietly handing you — and billing you for — the unwindowed set. (activeOnly is still the cheapest way to separate open from closed opportunities.)

Can I look up one exact solicitation number? Yes, since build 0.1.23 (2026-10-28): set solicitationNumber to the number, with or without dashes/spaces ("SPRRA2-22-R-0016" and "SPRRA222R0016" are the same query). Correction (build 0.1.76, 2026-10-28): SAM.gov's backend does have one real exact-match parameter for this, notice_id — a solnum-style query parameter is still silently ignored, confirmed live by probing it directly, but notice_id genuinely narrows server-side (it just matches the solicitation number, not the opportunity id its name implies, and it wants the value exactly as typed — raw punctuation, case-sensitive). The Actor tries it first with one lightweight probe request: when your value matches it exactly, the whole run walks on notice_id and usually finishes in a single page instead of reading the broader index; when it doesn't (different case, approximate input, or truly no match), the run falls back automatically to the pre-charge post-fetch filter described below, unchanged from how this feature worked before notice_id was found. Either way, a fetched row is only ever pushed and charged once its own solicitation number (compared the same punctuation-stripped, case-insensitive way SAM.gov compares it internally) exactly matches — notice_id is an efficiency win, never trusted unchecked. On the fallback path, the value is sent to SAM.gov as the search keyword to narrow the walk (it overrides keyword if you also set one — you'll get a warning), but that only scopes the walk, it does not reduce how much is read upstream, so a number that happens to be a weak/short substring can still walk the whole index before the exact check runs. Use RUN_SUMMARY.noticeIdFastPath to see which path a run took, and .solicitationNumberMismatch/.solicitationNumberMissing to see what the exact-match filter removed. Not supported for wage determinations, assistance-listings or exclusions — those records carry no solicitation number, and the run stops before any request rather than billing you for the unfiltered set.

Is there an award-amount range filter? Yes, since build 0.1.77 (2026-10-29): minAwardAmount/maxAwardAmount, inclusive, either side usable alone. SAM.gov's search backend only supports an exact award-amount match (award_amount=<n>, confirmed live) and rejects every range syntax (100000-200000, [100000 TO 200000], comma pairs, >100000) with HTTP 400, so like the date windows and solicitationNumber above, this is the Actor's own post-fetch filter: a fetched row is dropped before it is pushed or charged if its own award.amount is outside your range or missing entirely. award.amount is a real field on every opportunity row, but it is null until SAM.gov records an award against it — set noticeTypes: ["a"] to scope the walk to award notices, or most fetched rows will be dropped as awardAmountMissing rather than awardAmountDropped (the run logs a one-line reminder if you don't). Reconcile with RUN_SUMMARY.awardAmountDropped (out of range) and .awardAmountMissing (no award amount at all). Opportunities only; wage determinations, assistance-listings and exclusions carry no award object, and the run stops before any request rather than billing you for the unfiltered set.

Can I see who currently holds the work a notice is re-soliciting? Yes, since build 0.1.79 (2026-10-29): set includeIncumbentAwards: true and each opportunity gains an incumbentAwards array — the top 3 US federal contract awards by dollar value from USAspending.gov matching that notice's NAICS code, with recipient name, UEI, amount, start/end dates, awarding agency and sub-agency, and a usaspending.gov link for each. When the issuing department maps to one of USAspending's top-tier agency names the match is narrowed to that agency as well; every row records which it got in incumbentAwardsMatchedBy (naics+agency, naics, no-naics or lookup-failed). No extra charge — this is a second upstream, not a second billed event.

Three honest limits. (1) incumbentYears is matched against each award's last-modification/obligation date on USAspending, not its award or start date. Measured live: a 3-year window legitimately returns a contract that started in 2007 and was last modified in 2025, because an option exercise on a long-running contract is a recent action. That is the right answer for "who is performing this today", but it is not what "look-back" sounds like, so every returned award carries both startDate and lastModifiedDate and the exact window is written to RUN_SUMMARY.incumbentAwards.lastModifiedBetween. (2) Definitive contract awards only (USAspending award types A/B/C/D) — not IDV vehicles, grants, loans or sub-awards, because USAspending rejects a request mixing award-type groups and "who performs the work" is the contract, not the vehicle. (3) NAICS is not on SAM.gov's search row (its raw row carries only id/title/solicitation number/type/award/organization/descriptions), so this needs the per-opportunity detail call and turns enrichDetail on for you with a warning rather than silently returning nulls. A notice with no NAICS code at all gets incumbentAwards: null with incumbentAwardsMatchedBy: "no-naics" — distinct from [], which means the lookup ran and USAspending genuinely holds no matching award.

Is description the full notice text? Yes — the full solicitation description as SAM.gov itself stores it (original HTML markup preserved), not a truncated snippet; it can run to several thousand characters on a detailed notice. Attachments (drawings, full statements of work as separate documents) are not part of description — set includeAttachments: true to list them.

How deep can a search go? The backend caps paging at 10,000 rows per query, so a very broad keyword will stop there. Narrow with naicsCodes, noticeTypes or states rather than trying to page past it.

Is pointOfContact personal data? These are government contracting officers' official work contact details, published by the agency itself as a required part of the statutory public notice — the same disclosure class as the contacts on our NIH RePORTER and EU TED Actors. They are returned as SAM.gov publishes them; they are not aggregated across sources, cross-referenced with any other dataset, or resold as a people-lookup product.

How does the price compare? $0.0015 per returned row with no Actor-start fee. The comparable paid SAM.gov Actors on the Store range from about $0.0005 (two 1–2-user listings' flat rate, verified live 2026-10-04) to $0.003 per row — see Pricing above for the full live ranking, including the handful of free listings — and some add an Actor-start fee of $0.00005–$0.50 on top, charge extra for attachments or change alerts, or require your own SAM.gov API key, none of which this Actor does.

Can I download the bid attachments, not just get their links? Set includeAttachments: true — every row then carries an attachments array with each file's name, size, MIME type and a direct, no-login downloadUrl. This Actor does not fetch the file bytes into the dataset itself (a notice can attach a 10+ MB drawing set, and this is a 2 GB box); the URL is SAM.gov's own stable download path, so your own pipeline fetches the actual bytes only for the files it wants, when it wants them, without ever needing a SAM.gov login. Two comparable rivals (jungle_synthesizer/samgov-scraper, scrapesage/sam-gov-scraper) also offer an attachment-download feature; this closes that gap.

How does watchLabel know what's already new, and where is that baseline stored? In a key-value store on your own Apify account, keyed by the label plus a fingerprint of keyword/naicsCodes/setAsideTypes/noticeTypes/states/organizationId/activeOnly. The first run for a label just records every currently-matching opportunity id and returns zero rows (you pay nothing); every run after that returns only ids not already in that record. Changing any of those filters starts a fresh baseline under the same label instead of comparing against the old filter's results.

Does watchChanges cost extra? No extra fee — a changed opportunity is billed at the same $0.0015/row as a new one, so you only pay when there's actually something to see. Plain watchLabel never re-delivers an opportunity it has already sent you, even if the agency later extends the deadline or the notice moves from presolicitation to solicitation to award. Set watchChanges: true and each run also compares every already-delivered opportunity's isActive/noticeTypeCode/responseDate/modifiedDate/modificationsCount/awardeeName (plus an internal fingerprint of description) against what it looked like last time; if anything moved, the row is re-delivered tagged with _watchChangeType (which field(s) changed) and _watchPrevious (their prior values — description's previous value is a fixed note, since only a fingerprint of that text is stored, never the full text). Verified live: seeding a baseline, editing a delivered opportunity's recorded isActive flag and responseDate directly in the stored snapshot, then rerunning returned exactly those 2 rows with the correct change tags and nothing else — and a plain unchanged rerun after that returned 0 rows again.

Don't filter on the field you're watching. watchChanges compares each already-delivered row's watched fields against what they looked like last time — but two of this Actor's own filters are server-side narrowings on fields it also watches, so combining them with watchChanges makes exactly the change you're trying to catch structurally unreportable. activeOnly (on by default) sends SAM.gov is_active=true; isActive is the #1 watched field (the active → inactive/awarded transition, flagged as the single most valuable alert in this niche). The moment a row flips inactive, the filter stops it from matching the query at all — it is never fetched again, so watchChanges is never even asked about it, and the run just reports "nothing new." Live-verified cycle 1567 against a real sam.gov row (naics 221122): present with no filter, absent the instant is_active=true is added. Set activeOnly: false on any watch run where you need that transition — you'll get both active and inactive rows back and can filter on isActive yourself after delivery, or run two labels (one activeOnly: true for new rows, one activeOnly: false with watchChanges for the inactive transition). noticeTypes is the narrower second instance (opportunities only): it sends notice_type, and noticeTypeCode is watched for the presolicitation → solicitation → award lifecycle, so filtering to one type blinds the transition out of that type — leave it empty on a watch run that needs to see lifecycle moves. Both cases log an explicit warning (and, if the run also ends up with nothing new, a NOTE on that message) rather than silently reporting a clean, quiet watch.

Don't pin postedTo on a watch, either — same trap, different mechanism. activeOnly/noticeTypes above make watchChanges blind to a specific transition; a fixed postedTo is worse, because it kills watchLabel itself (new-opportunity detection, with or without watchChanges). publishDate is the date SAM.gov posted the notice, confirmed live to be assigned once and never bumped forward (active opportunities from as far back as 2011 still carry their original publishDate), while a brand-new notice's publishDate always equals today. So once today's date passes a fixed postedTo, no notice can ever again fall on or before it — the watch goes permanently quiet, and "nothing new" looks identical to "this watch is dead." postedFrom alone has no such problem (a one-sided lower bound only limits how far back the first baseline reaches). The run logs a warning when this combination is detected, and RUN_SUMMARY.watchDeadDateBound reports it so a pipeline can check from code. Drop postedTo from a watched query and reseed instead.

How do I know a run returned everything, without reading the log? Every run writes a RUN_SUMMARY record to its own key-value store — fetch it with `GET https://api.apify.com/v2/actor-runs/