# SAM.gov Contract Opportunities Scraper (No API Key) (`kempt_horizon_yzk/samgov-opportunities`) Actor

Search US federal contract opportunities (RFPs, RFQs, solicitations, sources sought) from SAM.gov without an API key. Input keywords, NAICS, PSC, set-aside, agency, state, dates. Returns one JSON record per notice with deadline, contacts, links. $0.004/result.

- **URL**: https://apify.com/kempt_horizon_yzk/samgov-opportunities.md
- **Developed by:** [Kempt Horizon Data](https://apify.com/kempt_horizon_yzk) (community)
- **Categories:** AI, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SAM.gov Contract Opportunities Scraper – Federal Bids & RFPs (No API Key)

Get **every federal contract opportunity from SAM.gov** – solicitations, RFPs, RFQs, sources sought, presolicitations and award notices – as clean JSON, CSV or Excel. **No SAM.gov API key and no 10-requests-a-day limit.** Filter by keyword, NAICS, PSC, set-aside, agency, state and dates. Turn on **"Only new since last run"**, schedule it daily, and get just the fresh bids. Optionally add **attachment text** (PDF/DOCX) and **USAspending award history** to spot the incumbent.

### For AI agents (MCP / API) – quick reference

- **Use when:** you need current US federal government contract opportunities / bids / RFPs / RFQs / sources-sought notices from SAM.gov, filtered by topic, NAICS, PSC, set-aside, agency, state or dates. No SAM.gov API key needed.
- **Don't use for:** past contract award spending analysis only (use USAspending), non-US or state/local bids.
- **Minimal input:** `{"keywords": ["cybersecurity", "software", "cloud"], "naicsCodes": ["5415"], "postedLastDays": 7, "maxItems": 20}` (all fields optional).
- **Output:** one dataset item per notice: `noticeId`, `title`, `solicitationNumber`, `noticeType`, agency/office, `naicsCode`, `pscCode`, `setAside`, `postedDate`, `responseDeadline`, place of performance, description, contacts, `url`; optionally attachments text and award history.
- **Price:** $0.001 per run start + **$0.004 per opportunity** ($0.01 if enriched). 20 results ≈ $0.08. Pay-per-event only, limited permissions, so agentic payments (x402 / Skyfire / Apify AGI) work.
- **MCP:** add `https://mcp.apify.com?tools=kempt_horizon_yzk/samgov-opportunities` to your MCP client.

### What does SAM.gov Contract Opportunities Scraper do?

SAM.gov (formerly FedBizOpps / FBO) is where US federal agencies post contracting opportunities. This Actor reads the **official public daily Contract Opportunities extract** that SAM.gov Data Services publishes (~70,000 notices). It filters the notices server-side and outputs typed, analysis-ready records.

- ✅ **No API key needed.** Non-federal SAM.gov keys are limited to **10 requests/day**; this Actor doesn't use one.
- ✅ **Powerful filters:** keyword (any/all), NAICS prefix, PSC prefix, set-aside (SBA, 8(a), HUBZone, SDVOSB, WOSB…), agency/office, place-of-performance state, notice type, posted and response-deadline date ranges, active-only
- ✅ **Monitoring mode:** remembers what you have already seen and returns only new notices
- ✅ **Enrichment (optional):** public attachment list + extracted text from PDF/DOCX/TXT; USAspending.gov award history (prior awards on the same solicitation number + recent awards in the same NAICS at the same agency)
- ✅ **Relevance score** for your keywords, with newest notices first
- ✅ Retries with exponential backoff; polite to government servers

### Who is it for?

Government-contracting BD and capture teams, small businesses chasing set-asides, proposal consultants, GovCon newsletters, and market-research analysts who want a cheap alternative to GovWin, HigherGov or GovSpend.

### How much does it cost?

Pay per result, with no subscription:

| Event | Price |
|---|---|
| Actor start | $0.001 |
| Opportunity | **$0.004** |
| Enriched opportunity (attachments and/or award history) | **$0.01** |

Example: a daily monitor that finds 40 new IT opportunities costs about **$0.16/day**. 1,000 opportunities cost $4. Set a **maximum cost per run** in the run options and the Actor stops cleanly when it reaches it.

### How to use it

1. Click **Try for free**.
2. Enter keywords and/or NAICS codes (e.g. `5415` for all computer-systems-design codes).
3. Optionally pick set-asides, states, agencies or a date range.
4. Click **Start**, then download results as JSON, CSV, Excel or HTML, or use the API.
5. For alerts: tick **Only new since last run**, give the monitor a name, and add a daily **Schedule**. Connect it to Slack, email, Zapier, Make or a webhook through Apify integrations.

### Input example

```json
{
  "keywords": ["cybersecurity", "zero trust"],
  "naicsCodes": ["5415"],
  "setAsideCodes": ["SBA", "SDVOSBC"],
  "states": ["VA", "MD", "DC"],
  "noticeTypes": ["Solicitation", "Combined Synopsis/Solicitation", "Sources Sought"],
  "postedLastDays": 7,
  "maxItems": 500,
  "onlyNew": true,
  "stateKey": "dmv-cyber-monitor",
  "includeAttachments": false,
  "includeAwardHistory": false
}
```

Common set-aside codes: `SBA` Total Small Business, `SBP` Partial SB, `8A` 8(a), `8AN` 8(a) sole source, `HZC`/`HZS` HUBZone, `SDVOSBC`/`SDVOSBS` Service-Disabled Veteran, `WOSB`/`EDWOSB` Women-Owned, `VSA` Veteran-owned, `ISBEE` Indian Small Business. Use `NONE` for full and open competition.

### Output example

```json
{
  "noticeId": "33e39090ff0b47b2b54d9a8e9cfaa6f2",
  "title": "Area of Interest (AOI) for User Activity Monitoring (UAM) Centralization Prototype Other Transaction (OT)",
  "solicitationNumber": "DISA-OTA-27-R-UAM",
  "noticeType": "Solicitation",
  "active": true,
  "postedDate": "2026-10-13T15:11:30.000Z",
  "responseDeadline": "2026-10-22T22:00:00.000Z",
  "department": "DEPT OF DEFENSE",
  "subTier": "DEFENSE INFORMATION SYSTEMS AGENCY (DISA)",
  "office": "IT CONTRACTING DIVISION - PL84",
  "naicsCode": "541519",
  "pscCode": "DA01",
  "setAsideCode": null,
  "placeOfPerformance": { "city": "Fort George G Meade", "state": "MD", "country": "USA" },
  "award": null,
  "contacts": [{ "name": "DITCO OTA Mailbox", "email": "disa.scott.ditco.mbx.ps84-other-transaction-authority@mail.mil" }],
  "description": "Amendment 0001 - ... enhance cybersecurity across the Department ...",
  "url": "https://sam.gov/opp/33e39090ff0b47b2b54d9a8e9cfaa6f2/view",
  "relevanceScore": 6,
  "enriched": false
}
```

Enriched records also include `attachments[]` (`name`, `type`, `url`, `sizeBytes`, `text`, `textError`) and `awardHistory` (`matchedBySolicitation[]`, `similarAwards[]` with recipient business name, UEI, amount, dates and a USAspending link).

### Data fields

noticeId, title, solicitationNumber, noticeType, baseNoticeType, active, postedDate, responseDeadline, archiveDate, department, subTier, office, CGAC/FPDS/AAC codes, naicsCode, pscCode, setAsideCode, setAside, placeOfPerformance, officeAddress, award (number, date, amount, awardee), contacts, description, url, relevanceScore, attachments, awardHistory, scrapedAt.

### Data freshness and limits

- SAM.gov regenerates the public extract **once a day** (overnight, US Eastern). Notices posted after that appear in the next day's run. A schedule around 07:00 ET works well.
- Attachment text is capped at 50,000 characters per file and 15 MB per file. Restricted or export-controlled attachments are never downloaded.
- Posted dates are reported in UTC (ISO 8601).

### Privacy and compliance

Uses only public US government data: the official SAM.gov public extract, SAM.gov's public attachment downloads, and the USAspending.gov public API. **No entity-registration (SAM entity) data is collected.** Contacts are the official contracting-office points of contact published on each notice. Attachments that look like attendee rosters or sign-in sheets are listed but not text-extracted, because they can contain personal data. Award history includes only business-level award fields (no recipient addresses). Don't use the output for unsolicited bulk marketing to the listed government contacts.

### FAQ

**Do I need a SAM.gov account or API key?** No.
**Can I get archived/inactive notices?** Set *Active notices only* to false. The extract includes recent inactive notices.
**How does "only new" work?** Notice IDs are stored in a named key-value store (`samgov-opportunities-state`), separately for each monitor name (or filter set). Notices that didn't fit into `maxItems` aren't marked as seen, so they show up next run.
**Is this affiliated with GSA?** No. It's an independent tool that uses public data.

Found a bug or need a field? Open an issue on the Actor's Issues tab.

# Actor input Schema

## `keywords` (type: `array`):

Optional. Words/phrases matched (case-insensitive) in notice title, solicitation number or description, e.g. \["cybersecurity","zero trust"]. Empty = no keyword filter.

## `keywordMatch` (type: `string`):

Require any or all keywords.

## `naicsCodes` (type: `array`):

Optional. NAICS codes or prefixes; a prefix matches all codes under it, e.g. "5415" = all IT services (541511, 541512...). Empty = all industries.

## `pscCodes` (type: `array`):

Product Service Codes or prefixes, e.g. D3 or R425.

## `setAsideCodes` (type: `array`):

SAM.gov set-aside codes: SBA (Total Small Business), SBP, 8A, 8AN, HZC, HZS, SDVOSBC, SDVOSBS, WOSB, WOSBSS, EDWOSB, EDWOSBSS, VSA, VSS, ISBEE, IEE. Use NONE for notices without a set-aside.

## `agencies` (type: `array`):

Text matched against department, sub-tier and office, e.g. "DEPT OF DEFENSE", "army", "NASA", "VETERANS AFFAIRS".

## `states` (type: `array`):

Two-letter state codes, e.g. VA, MD, TX.

## `noticeTypes` (type: `array`):

e.g. Solicitation, Combined Synopsis/Solicitation, Presolicitation, Sources Sought, Special Notice, Award Notice, Justification. Leave empty for all.

## `postedLastDays` (type: `integer`):

Optional. Only notices posted in the last N days (e.g. 7). Ignored if 'Posted from' is set. Empty = any date.

## `postedFrom` (type: `string`):

YYYY-MM-DD (inclusive, UTC).

## `postedTo` (type: `string`):

YYYY-MM-DD (inclusive, UTC).

## `deadlineFrom` (type: `string`):

YYYY-MM-DD. Notices without a deadline are excluded when set.

## `deadlineTo` (type: `string`):

YYYY-MM-DD.

## `activeOnly` (type: `boolean`):

Skip archived/inactive notices.

## `maxItems` (type: `integer`):

Maximum notices to return, newest first. Each result costs $0.004 ($0.01 if enriched), so set low (e.g. 10-50) for quick lookups.

## `onlyNew` (type: `boolean`):

Remember notice IDs between runs (per filter set) and output only notices not seen before. Ideal for scheduled daily runs.

## `stateKey` (type: `string`):

Optional name for the 'only new' memory. Defaults to a hash of your filters. Use a fixed name to keep history when you tweak filters.

## `includeDescription` (type: `boolean`):

Include the notice description text.

## `includeContacts` (type: `boolean`):

Official government points of contact listed on the notice.

## `includeAttachments` (type: `boolean`):

List public attachments/links per notice. Charged at the enriched rate.

## `includeAttachmentText` (type: `boolean`):

When attachments are on, download public PDF/DOCX/TXT files and extract text (max 50k chars per file).

## `maxAttachmentsPerNotice` (type: `integer`):

Limits download time per notice.

## `includeAwardHistory` (type: `boolean`):

Prior awards for the same solicitation number (incumbent) and recent awards in the same NAICS at the same agency. Charged at the enriched rate.

## `awardHistoryLimit` (type: `integer`):

How many awards to return in each history list.

## `enrichmentConcurrency` (type: `integer`):

Parallel enrichment requests. Keep low to be polite to government servers.

## `extractUrl` (type: `string`):

Leave empty. Alternative URL of the SAM.gov Contract Opportunities CSV extract (for testing/mirrors).

## Actor input object example

```json
{
  "keywords": [
    "cybersecurity",
    "software",
    "cloud"
  ],
  "keywordMatch": "any",
  "naicsCodes": [
    "5415"
  ],
  "postedLastDays": 7,
  "activeOnly": true,
  "maxItems": 20,
  "onlyNew": false,
  "includeDescription": true,
  "includeContacts": true,
  "includeAttachments": false,
  "includeAttachmentText": true,
  "maxAttachmentsPerNotice": 5,
  "includeAwardHistory": false,
  "awardHistoryLimit": 5,
  "enrichmentConcurrency": 3
}
```

# Actor output Schema

## `opportunities` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "cybersecurity",
        "software",
        "cloud"
    ],
    "naicsCodes": [
        "5415"
    ],
    "postedLastDays": 7,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("kempt_horizon_yzk/samgov-opportunities").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": [
        "cybersecurity",
        "software",
        "cloud",
    ],
    "naicsCodes": ["5415"],
    "postedLastDays": 7,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("kempt_horizon_yzk/samgov-opportunities").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "cybersecurity",
    "software",
    "cloud"
  ],
  "naicsCodes": [
    "5415"
  ],
  "postedLastDays": 7,
  "maxItems": 20
}' |
apify call kempt_horizon_yzk/samgov-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kempt_horizon_yzk/samgov-opportunities"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/H8S5cg11QfodhFtb9/builds/8q4wDEAcUaJSFP1IS/openapi.json
