# SAM.gov Contract Opportunities (US Federal, No API Key) (`datlab/sam-gov-contract-opportunities`) Actor

US federal contract opportunities from SAM.gov's official public daily extract. Filter by keyword, NAICS, PSC, set-aside, notice type, agency, state and posted date. No API key, no login, no contact-person data. Fast and reliable: one streamed file, no scraping.

- **URL**: https://apify.com/datlab/sam-gov-contract-opportunities.md
- **Developed by:** [DatLab](https://apify.com/datlab) (community)
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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 (US Federal Contracts, No API Key)

Get **SAM.gov contract opportunities** — US federal solicitations, combined synopses, sources sought, presolicitations, special notices and award notices — **with no SAM.gov API key and no login**. Filter by keyword, NAICS, PSC, set-aside (SDVOSB, 8(a), HUBZone, WOSB and others), notice type, agency, place of performance and posted date. Results come from SAM.gov's official public daily extract, not from HTML scraping.

- ✅ **Reliable**: reads SAM.gov's **official public daily extract** instead of scraping the website, so no logins, captchas, rate limits or broken selectors
- ✅ **Fast and cheap**: typical "last 7 days" searches finish in ~1-3 seconds of crawl time, with no browser or proxy
- ✅ **All the filters bid teams use**: NAICS / PSC prefixes, set-asides (SBA, 8(a), SDVOSB, WOSB, HUBZone…), notice types, agencies, states, date windows, open-for-response only
- ✅ **Monitoring mode**: `onlyNewSinceLastRun` returns only notices you haven't received before. Schedule it daily for alerts
- ✅ **Privacy-safe**: contracting officers' names, emails and phone numbers are **never** included

### Use cases

- Daily bid alerts for your NAICS codes and set-aside status
- Capture / BD pipelines, CRM and Slack feeds
- Market research: who buys what, where, and who wins (award notices with awardee and amount)
- GovCon newsletters and opportunity dashboards

### Input

| Field | Description |
|---|---|
| `keywords` | Whole word/phrase match, case-insensitive (any keyword). `cyber*` = prefix match. Searches title, solicitation number and (by default) the description |
| `searchInDescription` | Also match keywords in the description text (default `true`) |
| `naicsCodes` / `pscCodes` | Prefix match: `5415` matches 541511, 541512…; `D3` matches D301, D310… |
| `setAsideTypes` | SAM.gov set-aside codes (`SBA`, `8A`, `SDVOSBC`, `WOSB`, `HZC`…), `ANY` (any set-aside) or `NONE` (full & open) |
| `noticeTypes` | `solicitation`, `combined`, `presolicitation`, `sources_sought`, `special_notice`, `award`, `justification`, `modification`, `surplus_sale`, `bundle` |
| `agencies` | Substring of department, sub-tier or office (`VETERANS AFFAIRS`, `FOREST SERVICE`). Abbreviations work: DOD, ARMY, NAVY, AIR FORCE, VA, GSA, DHS, NASA, DLA… |
| `placeOfPerformanceStates` | State codes or names (`TX`, `California`) |
| `postedWithinDays` | Posted in the last N days (default 7, `0` = no limit) |
| `postedFrom` / `postedTo` | Explicit date range (overrides `postedWithinDays`) |
| `activeOnly` | Only active, non-archived notices (default `true`) |
| `openForResponseOnly` | Only notices whose response deadline hasn't passed |
| `latestVersionOnly` | One record per solicitation number (the newest notice) |
| `includePre2022Awards` | Include award notices posted before 4 Apr 2022 (default `false`, see [Data limits](#data-limits)) |
| `onlyNewSinceLastRun` / `stateKey` | Monitoring: skip notices delivered in earlier runs (separate memory per `stateKey`) |
| `includeDescription` | Add the notice description (contact details removed) |
| `maxItems` | Result cap (`0` = unlimited) |

Example: small-business IT opportunities still open for bids, posted in the last 14 days:

```json
{
  "keywords": ["software", "cyber*", "cloud"],
  "naicsCodes": ["5415"],
  "setAsideTypes": ["ANY"],
  "noticeTypes": ["solicitation", "combined", "sources_sought"],
  "postedWithinDays": 14,
  "openForResponseOnly": true,
  "maxItems": 500
}
```

### Output

One dataset item per notice:

```json
{
  "noticeId": "34551fb14f374336ac3439876ac2d7b6",
  "solicitationNumber": "6973GH-27-R-FOMSSOFTWAREDEVELOPMENT",
  "title": "FOMS SOFTWARE DEVELOPMENT",
  "noticeType": "Sources Sought",
  "department": "TRANSPORTATION, DEPARTMENT OF",
  "subTier": "FEDERAL AVIATION ADMINISTRATION",
  "office": "6973GH FRANCHISE ACQUISITION SVCS",
  "naicsCode": "541511",
  "pscCode": null,
  "setAsideCode": null,
  "setAside": null,
  "postedDate": "2026-10-27T15:24:01",
  "responseDeadline": "2026-11-06T17:00:00-05:00",
  "archiveDate": "2026-11-21",
  "active": true,
  "placeOfPerformance": "Oklahoma City, OK, USA",
  "popState": "OK",
  "awardNumber": null,
  "awardDate": null,
  "awardAmount": null,
  "awardee": null,
  "url": "https://sam.gov/opp/34551fb14f374336ac3439876ac2d7b6/view",
  "additionalInfoUrl": null,
  "source": "sam.gov-public-extract",
  "dataAsOf": "2026-10-28T03:30:31.000Z",
  "scrapedAt": "2026-10-28T23:45:44.829Z"
}
```

| Field | Notes |
|---|---|
| `noticeType` | As labelled by SAM.gov (`Solicitation`, `Combined Synopsis/Solicitation`, `Sources Sought`, `Award Notice`…) |
| `responseDeadline` | As published. Usually ISO 8601 with the agency's offset, sometimes date only |
| `postedDate` | SAM.gov timestamp (no zone given by the source) |
| `award*`, `awardee` | Award notices only. `awardee` is the company name; its street address is removed |
| `url` | Public SAM.gov notice page (attachments live there) |
| `dataAsOf` | When SAM.gov generated the extract. It refreshes daily, early morning US time |
| `description` | Only with `includeDescription`. Emails, phone numbers and contact sentences are removed |

The dataset has ready-made views: **Overview**, **Awards** and **With description**. A `RUN_SUMMARY` record in the key-value store shows rows scanned, matches, data freshness, duration and memory.

### Pricing

This Actor uses **pay per result**: **$1.50 per 1,000 notices** ($0.0015 per notice in the dataset).

- 100 notices ≈ $0.15, 1,000 notices = $1.50
- All filters (NAICS, PSC, set-aside, agency, keyword, dates …) are applied **before** results are saved, so you pay only for matching notices. The full extract is scanned for free.
- With `onlyNewSinceLastRun`, a daily alert only charges for notices you haven't received yet.
- Set **Maximum cost per run** in the run options to cap spending.
- Apify's free plan includes monthly credit you can use to try it.

The live price list is on the **Pricing** tab of this page.

### FAQ

**Do I need a SAM.gov account or API key?**
No. The Actor reads SAM.gov's official public Contract Opportunities extract, which needs neither.

**How current is the data?**
SAM.gov publishes the extract once a day, so new notices usually appear the next morning (US Eastern).

**How do I get daily bid alerts?**
Set your filters, turn on `onlyNewSinceLastRun`, and add a daily schedule. Connect the dataset to email, Slack, Google Sheets or a webhook through Apify integrations.

**Can I get award data?**
Yes. Award notices include the awardee business name, award number, date and amount. Older awards (before 4 April 2022) are excluded by default; see Data limits.

**Why is a title cut off?**
Titles are returned exactly as they appear in SAM.gov's extract, and some are already truncated there.

**Can I get historical / archived opportunities?**
No. The public extract contains active notices only.

### Privacy

Only information about the **opportunity** is returned, never about people:

- The extract's point-of-contact columns (names, titles, emails, phones, fax) are never read. Neither are place-of-performance street addresses or SAM.gov workspace links.
- Awardee street addresses are stripped, so only the business name is kept.
- In titles and descriptions, emails and phone numbers are removed. So are sentences carrying contact cues ("contact the Contracting Officer…", "Name/Title: …", "Mr. …") and trailing signatures. Free-text cleaning is heuristic.

### Limits & tips

- Data is SAM.gov's public daily snapshot, so a notice posted today usually appears the next morning. For a daily alert, schedule the Actor after ~06:00 US Eastern with `onlyNewSinceLastRun`.
- The public extract covers **active** notices. Archived/historical notices aren't in it.
- Notices that are restricted or controlled (CUI) on SAM.gov aren't in the public extract.
- Attachments aren't downloaded. Open `url` to get them.

### Data limits

SAM.gov notes that entity information in records from **before 4 April 2022** (when the government switched from DUNS numbers to its own Unique Entity ID) may include **Dun & Bradstreet data**, which has restrictions on commercial use and redistribution. To keep your results clean, **award notices posted before 4 April 2022 are excluded by default**. If you need them, set `includePre2022Awards` to `true`. You're then responsible for checking that your use of any D\&B-sourced awardee data is permitted. Other notice types aren't affected, and the current public extract contains very few notices that old.

### Legal & data use

- Data comes from SAM.gov's official public extract, which is US government information published for public use. The Actor doesn't scrape logged-in pages, CUI or restricted notices.
- It's built to return **opportunity data, not personal data**: contact names, emails and phone numbers are excluded (see Privacy).
- See Data limits for Dun & Bradstreet restrictions on pre-2022 award records.
- Not affiliated with or endorsed by the U.S. General Services Administration (GSA) or SAM.gov. Always confirm details on the official notice before you bid.

### Running on Apify

You can run this Actor on the Apify platform from the Console, the API, a schedule, integrations (webhooks, Slack, Google Sheets, Make, Zapier) or MCP.

### Other DatLab actors

- [Web Page to Markdown](https://apify.com/datlab/web-page-to-markdown) — turn a list of URLs into Markdown for LLMs and RAG
- [Website to Markdown Crawler](https://apify.com/datlab/site-to-markdown-crawler) — crawl a site into Markdown, with sitemaps and llms.txt
- [Sitemap Change Monitor](https://apify.com/datlab/sitemap-change-monitor) — extract sitemap URLs and watch new, removed and updated pages
- [ATS Job Listings](https://apify.com/datlab/ats-job-listings) — Personio, Teamtailor, Workable and Recruitee, one schema

# Actor input Schema

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

Keep notices whose title, solicitation number or description contains ANY of these words or phrases (whole words, case-insensitive). End a word with <code>*</code> for prefix matching, e.g. <code>cyber*</code> matches cybersecurity.

## `searchInDescription` (type: `boolean`):

Off = match keywords against title and solicitation number only (fewer, more precise results).

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

Prefix match: <code>5415</code> matches 541511, 541512, 541519 …

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

Prefix match: <code>D3</code> matches D302, D310 … ; <code>R4</code> matches R408 …

## `setAsideTypes` (type: `array`):

Keep notices with ANY of these set-asides. <code>NONE</code> = no set-aside, <code>ANY</code> = any set-aside.

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

Keep only these notice types. Empty = all.

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

Keep notices whose department, sub-tier or office contains ANY of these (case-insensitive), e.g. <code>VETERANS AFFAIRS</code>, <code>DEPT OF THE NAVY</code>, <code>FOREST SERVICE</code>. Common abbreviations work too: DOD, ARMY, NAVY, AIR FORCE, VA, GSA, DHS, DOE, DOJ, DOT, HHS, USDA, NASA, DOI, DOS, EPA, DLA, COMMERCE, TREASURY.

## `placeOfPerformanceStates` (type: `array`):

Two-letter US state codes (<code>VA</code>, <code>TX</code>) or full names. Notices without a place of performance are excluded when this is set.

## `postedWithinDays` (type: `integer`):

Ignored when <i>Posted from</i> is set. 0 = no date limit (reads the whole ~70,000-notice file).

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

Inclusive.

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

Inclusive.

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

Skip notices that are inactive or past their archive date.

## `openForResponseOnly` (type: `boolean`):

Keep only notices whose response deadline is in the future (notices without a deadline are dropped).

## `latestVersionOnly` (type: `boolean`):

SAM.gov lists each amendment as a separate notice. On = keep only the newest notice per solicitation number.

## `includePre2022Awards` (type: `boolean`):

Off by default. Award notices posted before 4 April 2022 may contain Dun & Bradstreet entity data that carries commercial-use restrictions, so they are skipped unless you turn this on and confirm your use is permitted.

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

Stop after saving this many notices. 0 = no limit.

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

Add the notice description text. Emails, phone numbers, contact sentences and sign-off blocks are removed.

## `onlyNewSinceLastRun` (type: `boolean`):

For scheduled runs: skip notices already delivered by an earlier run with the same state key.

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

Name for the memory of delivered notices. Use a different key per saved search.

## Actor input object example

```json
{
  "keywords": [
    "software",
    "cyber*"
  ],
  "searchInDescription": true,
  "naicsCodes": [
    "5415"
  ],
  "pscCodes": [],
  "setAsideTypes": [],
  "noticeTypes": [
    "solicitation",
    "combined",
    "sources_sought"
  ],
  "agencies": [],
  "placeOfPerformanceStates": [],
  "postedWithinDays": 7,
  "postedFrom": "",
  "postedTo": "",
  "activeOnly": true,
  "openForResponseOnly": false,
  "latestVersionOnly": false,
  "includePre2022Awards": false,
  "maxItems": 100,
  "includeDescription": false,
  "onlyNewSinceLastRun": false,
  "stateKey": "default"
}
```

# Actor output Schema

## `results` (type: `string`):

All dataset items produced by the run.

## `runSummary` (type: `string`):

RUN_SUMMARY record with per-source status, counts and timing.

# 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": [
        "software",
        "cyber*"
    ],
    "naicsCodes": [
        "5415"
    ],
    "noticeTypes": [
        "solicitation",
        "combined",
        "sources_sought"
    ],
    "postedWithinDays": 7,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("datlab/sam-gov-contract-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": [
        "software",
        "cyber*",
    ],
    "naicsCodes": ["5415"],
    "noticeTypes": [
        "solicitation",
        "combined",
        "sources_sought",
    ],
    "postedWithinDays": 7,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("datlab/sam-gov-contract-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": [
    "software",
    "cyber*"
  ],
  "naicsCodes": [
    "5415"
  ],
  "noticeTypes": [
    "solicitation",
    "combined",
    "sources_sought"
  ],
  "postedWithinDays": 7,
  "maxItems": 100
}' |
apify call datlab/sam-gov-contract-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datlab/sam-gov-contract-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/a4ibujo4Md7futLC8/builds/zzUR07ke9aGGyriuk/openapi.json
