# SAM.gov Opportunities Scraper (`hexadatalabs/sam-gov-opportunities-scraper`) Actor

Use this when you need US federal contract opportunities from SAM.gov: solicitations, sources sought and awards by keyword, NAICS, set-aside, agency, state and date, with deadline, award value and link. Public daily extract, no API key. Pay per result.

- **URL**: https://apify.com/hexadatalabs/sam-gov-opportunities-scraper.md
- **Developed by:** [Hexadata](https://apify.com/hexadatalabs) (community)
- **Categories:** Lead generation, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 opportunity (result)s

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 Opportunities Scraper

**SAM.gov Opportunities Scraper** returns US federal contract opportunities from SAM.gov (the official System for Award Management) as clean JSON: solicitations, combined synopsis/solicitations, presolicitations, sources sought, special notices and award notices filtered by keyword, NAICS code, set-aside, agency, place-of-performance state and posted date, with response deadline, award amount, awardee and the notice link. It reads the GSA's public daily data extract (no API key, no daily quota), runs incrementally for scheduled alerts, and you **pay per result**.

### What you get

One item per notice, same field names as every Hexadata Actor:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | SAM.gov notice id (32 hex characters), unique |
| `title` | string | |
| `solicitationNumber` | string | null | |
| `agency` / `subAgency` / `office` | string | null | Department, sub-tier and contracting office |
| `noticeType` / `baseType` | string | `Solicitation`, `Combined Synopsis/Solicitation`, `Presolicitation`, `Sources Sought`, `Award Notice`, `Special Notice`, `Justification`… |
| `country` | string | `US` |
| `publishedAt` | string | Posted date-time, ISO 8601 (US Eastern, as published) |
| `deadline` | string | null | Response deadline, ISO 8601 with offset |
| `archiveDate` / `archiveType` | string | null | When and how SAM.gov will archive the notice |
| `active` | boolean | |
| `setAsideCode` / `setAside` | string | null | `SBA`, `SDVOSBC`, `WOSB`, `8A`, `HZC`… and its description |
| `naicsCode` / `classificationCode` | string | null | NAICS and product/service code (PSC) |
| `placeOfPerformanceCity` / `State` / `Zip` / `Country` | string | null | |
| `officeCity` / `officeState` / `officeZip` | string | null | Contracting office location |
| `awardNumber` / `awardDate` / `awardedValue` / `currency` / `awardee` | mixed | Award notices: contract number, date, amount in USD, awardee name and address |
| `description` | string | null | Notice description, up to 4,000 characters |
| `url` / `additionalInfoUrl` | string | Notice page on sam.gov and additional-info link |
| `source`, `scrapedAt` | string | Attribution and extraction timestamp |

With `includeContacts: true` you also get the primary and secondary point of contact (name, title, e-mail, phone). With `includeRaw: true` the original 47-column extract row is attached as `raw`.

### Use cases

- **Government contractors and capture managers** get every new solicitation and sources-sought in their NAICS codes and states each morning, with deadlines, instead of saved searches that expire or e-mails that pile up.
- **Small businesses with a set-aside status** (8(a), HUBZone, SDVOSB, WOSB) filter opportunities reserved for them (`setAsides: ["SDVOSBC"]`) and respond before the competition notices them.
- **GovCon consultants and bid-matching services** run the Actor on a schedule with `onlyNewSinceLastRun` and push results to a CRM, Slack or Google Sheets through an Apify integration, one feed per client profile.
- **Sales teams selling to federal agencies** use award notices (`noticeTypes: "award"`) to see who won what, for how much, at which agency, and build a list of primes to partner with.
- **AI agents and RAG pipelines** call the Actor as an MCP tool ("find Air Force solicitations for drone detection posted this week") and reason over structured results.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `searchQueries` | string\[] | `[]` (prefill `["cybersecurity"]`) | Case-insensitive phrases matched in title, solicitation number and description; OR-ed. |
| `noticeTypes` | select | `all` | `solicitation`, `presolicitation`, `sources-sought`, `award`, `special-notice`, `justification`, `intent-to-bundle`. |
| `naicsCodes` | string\[] | `[]` | NAICS codes, prefix match (`541512`, `5415`, `23`). |
| `setAsides` | string\[] | `[]` | Set-aside codes: `SBA`, `SBP`, `8A`, `8AN`, `HZC`, `HZS`, `SDVOSBC`, `SDVOSBS`, `WOSB`, `WOSBSS`, `EDWOSB`, `EDWOSBSS`, `VSA`, `VSS`, `LAS`, `IEE`, `ISBEE`, `BICIV`, `NONE`. |
| `agencies` | string\[] | `[]` | Substrings of the department, sub-tier or office name (`"VETERANS AFFAIRS"`, `"NASA"`). |
| `states` | string\[] | `[]` | Two-letter place-of-performance states (office state when none). |
| `dateFrom` / `dateTo` | date | – | Posted-date bounds (`YYYY-MM-DD`). With no other filter, the last 7 days are used. |
| `onlyActive` | boolean | `true` | Skip archived / inactive notices. |
| `onlyNewSinceLastRun` | boolean | `false` | For schedules: only notices posted since the previous run that were not delivered before (state in the named store `hexadata-sam-gov-opportunities`). |
| `maxResults` | integer | `100` | Hard cap on results and cost. Newest first. |
| `includeContacts` | boolean | `false` | Add contracting-officer contact fields. |
| `includeRaw` | boolean | `false` | Attach the original extract row. |
| `proxyConfiguration` | object | off | Not needed. |

Invalid input (unknown set-aside code, NAICS with letters, malformed date) stops the run before the download starts, so it costs nothing.

### Output example

Two real items from the runs saved in `tests/` (2026-10-27). A solicitation (`searchQueries: ["cybersecurity"]`, `noticeTypes: "solicitation"`):

```json
{
  "id": "1414fc3a5070490c8c53d15644386249",
  "title": "Commercial Solutions Opening (CSO) for Space Domain Awareness (SDA) Solutions.",
  "solicitationNumber": "FA2518-25-S-C001",
  "agency": "DEPT OF DEFENSE",
  "subAgency": "DEPT OF THE AIR FORCE",
  "office": "FA2518 USSF SPOC/SAIO",
  "noticeType": "Combined Synopsis/Solicitation",
  "baseType": "Combined Synopsis/Solicitation",
  "country": "US",
  "publishedAt": "2026-10-26T09:41:29",
  "deadline": "2030-01-23T12:00:00-07:00",
  "archiveDate": "2030-02-07",
  "archiveType": "auto15",
  "active": true,
  "setAsideCode": "NONE",
  "setAside": "No Set aside used",
  "naicsCode": "541715",
  "classificationCode": "AR12",
  "placeOfPerformanceCity": "Colorado Springs",
  "placeOfPerformanceState": "CO",
  "placeOfPerformanceZip": "80912",
  "placeOfPerformanceCountry": "USA",
  "officeCity": "PETERSON AFB",
  "officeState": "CO",
  "officeZip": "80914-4184",
  "awardNumber": null,
  "awardDate": null,
  "awardedValue": null,
  "currency": null,
  "awardee": null,
  "description": "18 Mar 2026 Updated: Space Domain Awareness (SDA) Commercial Solutions Opening (CSO) Phase I. The initial evaluation for phase I has been completed. We received a significant number of responses, and our team has given e…",
  "url": "https://sam.gov/workspace/contract/opp/1414fc3a5070490c8c53d15644386249/view",
  "additionalInfoUrl": null,
  "source": "SAM.gov Contract Opportunities public data extract (U.S. General Services Administration)",
  "scrapedAt": "2026-10-27T05:47:09.992Z"
}
```

An award notice (`agencies: ["VETERANS AFFAIRS"]`, `noticeTypes: "award"`):

```json
{
  "id": "4d263fb52add4a3da471a9a633aeb353",
  "title": "F18 PET RADIOPHARMACEUTICALS",
  "solicitationNumber": "36C24726P0659",
  "agency": "VETERANS AFFAIRS, DEPARTMENT OF",
  "office": "247-NETWORK CONTRACT OFFICE 7 (36C247)",
  "noticeType": "Award Notice",
  "country": "US",
  "publishedAt": "2026-10-26T10:33:01",
  "active": true,
  "setAsideCode": "SBA",
  "setAside": "Small Business Set Aside - Total",
  "naicsCode": "325412",
  "classificationCode": "Q527",
  "placeOfPerformanceCity": "Decatur",
  "placeOfPerformanceState": "GA",
  "awardNumber": "36C24726P0659",
  "awardDate": "2026-06-18",
  "awardedValue": 1308146.16,
  "currency": "USD",
  "awardee": "Trillamed LLC Southfield MI 48076 USA",
  "description": "The vendor shall provide all labor, supervision, and transportation necessary to provide daily delivery of F-18 FDG (fluorodeoxyglucose), NaF-F18 (sodium fluoride), to the NM Service, located in the Atlanta Veterans Affa…",
  "url": "https://sam.gov/workspace/contract/opp/4d263fb52add4a3da471a9a633aeb353/view",
  "source": "SAM.gov Contract Opportunities public data extract (U.S. General Services Administration)",
  "scrapedAt": "2026-10-27T05:49:02.168Z"
}
```

### Pricing & cost examples

**$5.00 per 1,000 opportunities** (pay per event, charged only for items saved to the dataset; duplicates, invalid rows and failed runs are never billed). `maxResults` is a hard cost cap and Apify platform usage is included.

- A first look: `maxResults: 50` ≈ **$0.25**.
- A daily alert for one NAICS family in 3 states with `onlyNewSinceLastRun` (typically 10–40 new notices per business day) ≈ **$0.05–0.20 per day**, about $3 per month.
- A market study: every award notice of one department for a quarter (≈ 5,000 notices) ≈ **$25**.

### Use with AI agents (MCP)

Every Apify Actor is available as a tool through the [Apify MCP server](https://mcp.apify.com). Add this server to Claude, Cursor, VS Code or any MCP client (OAuth sign-in on first use, or an `Authorization: Bearer <APIFY_TOKEN>` header):

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=hexadatalabs/sam-gov-opportunities-scraper"
    }
  }
}
```

Then ask, for example:

> "Which small-business set-aside solicitations for IT services in Virginia or Maryland were posted this week, and when do they close?"

The agent calls the Actor with `{"naicsCodes":["5415"],"setAsides":["SBA"],"states":["VA","MD"],"noticeTypes":"solicitation","dateFrom":"2026-10-20"}` and reads `deadline`, `setAside` and `url` from the results. The Actor description and every input field start with "Use this when…" so tool selection works without extra prompting.

### API & integrations

```bash
curl -X POST "https://api.apify.com/v2/acts/hexadatalabs~sam-gov-opportunities-scraper/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["cybersecurity"],"noticeTypes":"solicitation","maxResults":50}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("hexadatalabs/sam-gov-opportunities-scraper").call(run_input={
    "agencies": ["VETERANS AFFAIRS"], "noticeTypes": "award", "dateFrom": "2026-10-01", "maxResults": 200,
})
for opp in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(opp["awardDate"], opp["awardee"], opp["awardedValue"], opp["url"])
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('hexadatalabs/sam-gov-opportunities-scraper').call({
    naicsCodes: ['5415'], states: ['VA', 'MD', 'DC'], onlyNewSinceLastRun: true, maxResults: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((o) => `${o.deadline ?? 'no deadline'} · ${o.title}`).join('\n'));
```

**Schedules and webhooks:** create a Schedule in Apify Console (e.g. every weekday at 09:00 UTC; the extract is refreshed overnight US time) with `onlyNewSinceLastRun: true`, then add a webhook or integration (e-mail, Slack, Google Sheets, Make, Zapier, HTTP) on the `ACTOR.RUN.SUCCEEDED` event. Each run delivers only the notices posted since the previous one.

### Limitations & legal

- **Source:** the GSA's public *Contract Opportunities* daily data extract from [sam.gov/data-services](https://sam.gov/data-services) (`ContractOpportunitiesFullCSV.csv`, about 200 MB, refreshed daily). The Actor streams the file and stops as soon as `maxResults` or the date cut-off is reached, so most runs read a few megabytes; a keyword-only search over the whole file takes about a minute. No API key, no daily quota, no HTML scraping.
- **Freshness:** the extract is produced once a day, so notices posted today appear in tomorrow's run. Posted times are US Eastern without offset.
- **Licence:** SAM.gov data is published by the US government for public reuse (US federal government works are not subject to copyright); keep the attribution in `source`. Hexadata is not affiliated with GSA.
- **Personal data:** contracting-officer names, e-mails and phones are excluded unless `includeContacts: true`; use them only to ask the agency about the notice.
- **Keyword matching** is a plain case-insensitive substring in title, solicitation number and description (no stemming); add variants (`"cyber security"`, `"cybersecurity"`).
- **Coverage:** the notices present in the current extract (active notices plus recently archived ones). Attachments are not downloaded; open `url` for documents.
- If SAM.gov changes the extract columns, the run fails with `SITE_LAYOUT_CHANGED` and nothing is charged.

### Changelog

- **0.1.0** (2026-10-27): first release. Keyword, notice-type, NAICS, set-aside, agency, state and date filters; incremental mode; award fields; dataset table view; MCP-ready descriptions.

### Support

Open an issue in the **Issues** tab of this Actor (or e-mail Hexadata through the Apify profile). Issues are answered within 24 hours and confirmed bugs are fixed in a `beta` build within 48 hours.

#### En español

**SAM.gov Opportunities Scraper** extrae oportunidades de contratación del gobierno federal de EE.UU. desde SAM.gov (licitaciones, sondeos de mercado, avisos previos y adjudicaciones) a partir del extracto público diario de la GSA, sin clave de API. Filtra por palabra clave, código NAICS, reserva para pequeñas empresas (set-aside), agencia, estado y fecha, y devuelve plazo, monto adjudicado, adjudicatario y enlace en JSON limpio, con modo incremental para alertas diarias. Precio: **$5.00 por cada 1,000 resultados**; `maxResults` limita el costo. Sin datos personales por defecto.

# Actor input Schema

## `searchQueries` (type: `array`):

Case-insensitive phrases matched in the title, solicitation number and description, one per line, e.g. "cybersecurity", "janitorial services", "drone". Leave empty to filter only by NAICS / set-aside / agency / state / date.

## `noticeTypes` (type: `string`):

Use "solicitation" for notices you can bid on now (Solicitation + Combined Synopsis/Solicitation), "sources-sought" and "presolicitation" for early market research, "award" for award notices with awardee and amount.

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

North American Industry Classification codes, 2 to 6 digits, prefix match: "541512" = computer systems design, "5415" = all computer services, "23" = construction. Find codes at https://www.census.gov/naics/

## `setAsides` (type: `array`):

Only notices with these small-business set-asides: SBA (total small business), SBP (partial), 8A, 8AN, HZC, HZS (HUBZone), SDVOSBC, SDVOSBS (service-disabled veteran), WOSB, WOSBSS, EDWOSB, EDWOSBSS (women-owned), VSA, VSS (veteran), LAS, IEE, ISBEE, BICIV, NONE. Empty = any.

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

Substrings matched in the department, sub-tier or office name, e.g. "DEPT OF DEFENSE", "VETERANS AFFAIRS", "NASA", "HOMELAND SECURITY".

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

Two-letter US state or territory codes of the place of performance (the contracting office state is used when the notice has none), e.g. TX, VA, CA, DC.

## `dateFrom` (type: `string`):

Only notices posted on or after this date (YYYY-MM-DD). With no other filter, the last 7 days are used. A date also makes runs faster: the download stops once older notices are reached.

## `dateTo` (type: `string`):

Only notices posted on or before this date (YYYY-MM-DD).

## `onlyActive` (type: `boolean`):

Keep only notices SAM.gov marks as active (not archived). Turn off to include inactive and archived notices present in the extract.

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

Use this on a schedule: the Actor remembers when it last ran (shared store "hexadata-sam-gov-opportunities" in your account) and returns only notices posted since then that it has not delivered before. The first run saves everything that matches.

## `maxResults` (type: `integer`):

Stop after this many opportunities. Newest notices come first.

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

Add the primary and secondary point of contact published in the notice (name, title, e-mail, phone). Off by default because these are named individuals; turn on only if you have a lawful basis to use them (they are published by SAM.gov for vendors to ask questions about the notice).

## `includeRaw` (type: `boolean`):

Attach the original 47-column row of the SAM.gov extract under "raw" (includes contact columns). For debugging or custom parsing.

## `proxyConfiguration` (type: `object`):

The SAM.gov public extract does not need a proxy; leave it off.

## Actor input object example

```json
{
  "searchQueries": [
    "cybersecurity"
  ],
  "noticeTypes": "all",
  "onlyActive": true,
  "onlyNewSinceLastRun": false,
  "maxResults": 50,
  "includeContacts": false,
  "includeRaw": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchQueries": [
        "cybersecurity"
    ],
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hexadatalabs/sam-gov-opportunities-scraper").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 = {
    "searchQueries": ["cybersecurity"],
    "maxResults": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("hexadatalabs/sam-gov-opportunities-scraper").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 '{
  "searchQueries": [
    "cybersecurity"
  ],
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call hexadatalabs/sam-gov-opportunities-scraper --silent --output-dataset

```

## MCP server setup

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

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/kCbEaHwJjdhhDeiFx/builds/h7hwdWdi464SUdtjM/openapi.json
