# SAM.gov Scraper - Federal Contract Opportunities & Bids (`scrapewise/sam-gov-scraper`) Actor

Scrape SAM.gov Contract Opportunities without an API key: solicitations, sources sought and awards by keyword, NAICS, PSC, set-aside, agency, state and dates, with deadlines, contacts, attachments and awardee. US$ 2 per 1,000.

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

## Pricing

from $2.13 / 1,000 opportunity delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper: federal contract opportunities, bids and awards

Scrape [SAM.gov Contract Opportunities](https://sam.gov/search/?index=opp) (the former FedBizOpps) **without an API
key or an account**. Search by keyword or just by filters and get every notice the US federal government
publishes: **solicitations, combined synopsis/solicitations, pre-solicitations, sources sought, special notices and
award notices**, with **agency, office, solicitation number, posted date, response deadline, NAICS, PSC, set-aside,
place of performance, full description, the official contracting contact, attachment links and, for awards, the
winner, award number, date and amount**.

Filter by **notice type, NAICS, PSC, small-business set-aside (8(a), HUBZone, SDVOSB, WOSB...), agency or office,
state and ZIP of performance, posted date and response deadline**. SAM.gov applies every filter itself, so you only
pay for what you asked for.

Built for government contractors and capture teams, bid-matching and GovCon SaaS tools, BD and proposal managers,
small businesses looking for set-asides, and analysts tracking who wins federal contracts.

**US$ 2.00 per 1,000 opportunities, detail page included. No start fee, no monthly fee, no API key. Error rows,
duplicates and notices outside your filters are free.**

### At a glance

- **Price per 1,000 opportunities, Free plan:** US$ 2.00
- **Fee per run start:** None
- **Needs your own SAM.gov API key:** No
- **Detail page (contacts, NAICS, PSC, set-aside, attachments) at no extra cost:** Yes
- **Filters: notice type, NAICS, PSC, set-aside, agency, state, ZIP, dates:** Yes, all applied by SAM.gov
- **Award notices with winner, UEI, CAGE and amount:** Yes
- **Resumes after a platform restart without charging twice:** Yes

### What you can do with it

- **Daily bid feed.** `naicsCodes: ["541511", "541512"]`, `noticeTypes: ["solicitation", "combinedSynopsisSolicitation"]`,
  `openDeadlineOnly: true`, scheduled every morning: every open IT solicitation with deadline, set-aside and contact.
- **Small-business set-asides.** `setAsides: ["SBA", "8A", "SDVOSBC"]` plus a state such as `placeOfPerformanceStates: ["VA"]`.
- **Watch an agency.** `agencies: ["Dept of the Navy"]` (sub-offices included) or `["Veterans Affairs"]`.
- **Competitive intelligence.** `noticeTypes: ["awardNotice"]` with a NAICS code returns who won, the award number,
  date and amount, and the winner's UEI and CAGE code.
- **Market research.** Sources sought and pre-solicitations tell you what agencies will buy months ahead.
- **Reuse a SAM.gov page.** Paste an opportunity link (`https://sam.gov/opp/<id>/view`) or a SAM.gov search link.
- **Feed a CRM, a spreadsheet or a bid-matching app.** Export CSV, Excel or JSON, or call it through the Apify API.

### Input

| Field | What it does |
|---|---|
| `searchTerms` | Keywords, one per line. Each is a separate search. Leave empty to search only by filters. |
| `keywordMode` | `all` words (default), `any` word, or `exact` phrase. |
| `startUrls` | SAM.gov opportunity links, 32-character notice ids, or SAM.gov search links. |
| `noticeTypes` | `solicitation`, `combinedSynopsisSolicitation`, `presolicitation`, `sourcesSought`, `specialNotice`, `awardNotice`, `justification`, `justificationAndApproval`, `intentToBundle`, `saleOfSurplusProperty`, `modification`. |
| `naicsCodes` | NAICS codes (541511, 236220...). |
| `pscCodes` | Product Service Codes (7030, R425, J059...). |
| `setAsides` | SAM.gov set-aside codes: SBA, SBP, 8A, 8AN, HZC, HZS, SDVOSBC, SDVOSBS, WOSB, WOSBSS, EDWOSB, EDWOSBSS, LAS, IEE, ISBEE, BICiv, VSA, VSS. |
| `agencies` | Departments, agencies or offices by name or SAM.gov organization id. Sub-offices included. |
| `placeOfPerformanceStates` / `placeOfPerformanceZip` | Two-letter states / 5-digit ZIP codes. |
| `status` | `active` (default), `inactive` or `all`. |
| `postedFrom`, `postedTo` | Posted (or updated) date range, YYYY-MM-DD. |
| `responseDeadlineFrom`, `responseDeadlineTo` | Response deadline range, YYYY-MM-DD. |
| `sortBy` | `newest` (default), `oldest`, `relevance`. |
| `includeDetails` | Read each notice's detail page (on by default, same price). |
| `maxResultsPerSearch` | Opportunities per keyword or link. Default 100, up to 10,000 (SAM.gov's own cap per search). |
| `maxItems` | Hard cap on charged opportunities for the whole run. |
| `openDeadlineOnly` | Skip notices whose response deadline has passed or is missing (free). |
| `excludeKeywords` | Skip notices whose title has any of these words (free). |

Example: open small-business IT solicitations in Virginia, Maryland and DC.

```json
{
  "naicsCodes": ["541511", "541512", "541519"],
  "noticeTypes": ["solicitation", "combinedSynopsisSolicitation"],
  "setAsides": ["SBA"],
  "placeOfPerformanceStates": ["VA", "MD", "DC"],
  "openDeadlineOnly": true,
  "maxResultsPerSearch": 500
}
```

An empty input runs a small example (20 opportunities for "software"), so the Actor never fails on a blank form.

### Output

One real row from a local test run on 2026-09-29 (search "software"; the contact name is shortened):

```json
{
  "type": "opportunity",
  "noticeId": "8efe146d6e4a407795fa7039f6098edf",
  "title": "NDU NIC Lifecycle Replacement",
  "noticeType": "Award Notice",
  "noticeTypeCode": "a",
  "solicitationNumber": "HQ0100631522",
  "url": "https://sam.gov/opp/8efe146d6e4a407795fa7039f6098edf/view",
  "active": true,
  "cancelled": false,
  "postedDate": "2026-09-30T00:29:13.678+00:00",
  "modifiedDate": "2026-09-30T00:29:13+00:00",
  "responseDeadline": null,
  "responseTimeZone": null,
  "archiveDate": "2026-10-14",
  "department": "DEPT OF DEFENSE",
  "subTier": "DEPT OF THE NAVY",
  "office": "NAVSUP FLT LOG CTR NORFOLK",
  "officeCode": "N00189",
  "agencyPath": "DEPT OF DEFENSE > DEPT OF THE NAVY > NAVSUP > NAVSUP GLOBAL LOGISTICS SUPPORT > NAVSUP FLC NORFOLK > NAVSUP FLT LOG CTR NORFOLK",
  "organizationId": "500021468",
  "officeCity": "NORFOLK",
  "officeState": "VA",
  "officeZip": "23511-3392",
  "officeCountry": "USA",
  "naicsCode": "541519",
  "naicsCodes": ["541519"],
  "pscCode": "7B22",
  "setAsideCode": null,
  "setAside": null,
  "placeOfPerformance": {"city": "Washington", "state": "DC", "stateName": "District of Columbia", "zip": "20319", "country": "USA"},
  "description": null,
  "awardNumber": "NNG15SC59B",
  "awardDate": "2026-09-29",
  "awardAmount": 1352864.19,
  "awardeeName": "AFFIGENT, LLC",
  "awardeeUei": "M46UYYHVH4B1",
  "awardeeCageCode": "3NBK4",
  "awardeeCity": "Herndon",
  "awardeeState": "Virginia",
  "awardeeZip": "20171",
  "awardeeCountry": "UNITED STATES",
  "contacts": [{"type": "primary", "name": "Rubean Joy Varghese", "title": null, "email": "rubean.varghese@navy.mil", "phone": null, "fax": null}],
  "attachments": [{"name": "NDU NIC Exception to Fair Opportunity (Redacted).pdf", "type": "file", "mimeType": ".pdf", "sizeBytes": 134705, "postedDate": "2026-09-30T00:29:13.678+00:00", "access": "public", "exportControlled": false, "url": "https://sam.gov/api/prod/opps/v3/opportunities/resources/files/99f3e411ec2a43abaf07b63a3763fa3f/download"}],
  "parentNoticeId": null,
  "modificationCount": 0,
  "detailsLoaded": true,
  "searchTerm": "software",
  "position": 1,
  "source": "term:software",
  "scrapedAt": "2026-09-30T02:48:11Z",
  "errorCode": null,
  "error": null
}
```

- `responseDeadline` keeps SAM.gov's own time zone offset; `responseTimeZone` names it.
- `attachments[].url` is SAM.gov's public download link (it redirects to the file). Controlled attachments show
  `access` other than `public` and no URL.
- `contacts` is the **official contracting contact** the agency published on the notice. It is returned only when its
  email is a government address (.gov, .mil, .us) or there is no email; any other contact keeps only its type.
- With `includeDetails: false`, rows carry the search fields only (title, type, agency path, dates, solicitation
  number, awardee name and UEI) and `detailsLoaded` is false. If a detail page does not answer, the row is still
  delivered with the search fields and `detailsLoaded: false`.

The run also saves `SEARCH_SUMMARY` in its key-value store: for each keyword or link, how many notices SAM.gov has for
it and how many were delivered (free).

#### Error rows (never charged)

| errorCode | When |
|---|---|
| `NO_RESULTS` | SAM.gov has no notices for this keyword with these filters. |
| `NOT_FOUND` | The opportunity link or id does not exist or is not public. |
| `INVALID_URL` | The link is not a SAM.gov opportunity or search link. |
| `BLOCKED` | SAM.gov refused every attempt for that search. |
| `INVALID_INPUT` | A field has a value the Actor cannot use (the message says which). |
| `UNEXPECTED` | Anything else; the rest of the run continues. |

### Pricing

Pay per event, no start fee:

| Event | Price per 1,000 (Free plan) | Charged for |
|---|---|---|
| Opportunity delivered | **US$ 2.00** | each unique notice, with its detail page when `includeDetails` is on |

Examples: 1,000 opportunities cost US$ 2.00. A daily feed of 100 new notices costs about US$ 6 per month. Error rows,
duplicates and filtered-out notices are free, and `maxItems` is a hard stop.

### How it works and limits

- It reads the same public search and notice pages any visitor sees on SAM.gov. No login, no API key.
- SAM.gov returns at most **10,000 notices per search**. For bigger pulls, split by date range, NAICS or agency.
- The order is SAM.gov's own (newest update first by default).
- Posted dates in SAM.gov are filtered by the notice's latest version, so an old notice updated inside your range
  also shows up.
- Speed in our tests: 250 notices without detail pages in 2 s; 400 notices with detail pages and attachments in
  35 s.

### FAQ

**Do I need a SAM.gov account or API key?** No. Everything comes from public pages.

**Can I get only new notices every day?** Yes: schedule the Actor with `postedFrom` set to yesterday (or use
`sortBy: newest` with a small `maxResultsPerSearch`).

**Does it download the attachment files?** It returns each attachment's name, type, size and public download link;
the files themselves are not downloaded.

**What if the run is restarted by the platform?** Notices already in the dataset are not charged again: the Actor
reads its own dataset when it starts and skips what was delivered.

### Changelog

- **0.1 (2026-09-29):** first version: keywords, filters (notice type, NAICS, PSC, set-aside, agency, state, ZIP,
  posted and response dates, status), opportunity and search links, detail pages with contacts and attachments,
  award data, resume after restart.

Independent tool, not affiliated with the U.S. General Services Administration or SAM.gov.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords, one per line (for example: software, cybersecurity, janitorial services, drone). Each keyword is a separate SAM.gov search over titles, descriptions and solicitation numbers. Leave empty and use only the filters below to get every opportunity that matches them.

## `keywordMode` (type: `string`):

How SAM.gov matches the words of each keyword: all words (default), any word, or the exact phrase.

## `startUrls` (type: `array`):

SAM.gov opportunity links (https://sam.gov/opp/<id>/view), 32-character notice ids, or SAM.gov search links (https://sam.gov/search/?index=opp...). Keywords, NAICS, PSC, notice type, set-aside and status in a search link are kept.

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

Only these notice types. Empty = all types.

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

NAICS codes, one per line or comma separated (for example 541511, 541512, 236220). Empty = any.

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

Product Service Codes, one per line (for example 7030, R425, J059). Empty = any.

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

Only opportunities with these small-business set-asides. Empty = any (including full and open competition).

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

Federal departments, agencies or offices by name as SAM.gov writes them (for example: Dept of the Navy, Veterans Affairs, NASA) or by SAM.gov organization id. Sub-offices are included. Empty = all agencies.

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

Two-letter US state codes, one per line (VA, TX, CA...). Empty = anywhere.

## `placeOfPerformanceZip` (type: `array`):

5-digit ZIP codes of the place of performance. Empty = any.

## `status` (type: `string`):

Active opportunities only (default), inactive/archived only, or both.

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

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

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

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

## `responseDeadlineFrom` (type: `string`):

Only notices whose response deadline is on or after this date (YYYY-MM-DD).

## `responseDeadlineTo` (type: `string`):

Only notices whose response deadline is on or before this date (YYYY-MM-DD).

## `sortBy` (type: `string`):

Order of the results (SAM.gov's own sort). Default: newest first.

## `includeDetails` (type: `boolean`):

Read each notice's detail page: NAICS, PSC, set-aside, place of performance, full description, official contracting contacts, attachment links and award data. On by default, same price. Turn off for faster runs with the search fields only.

## `maxResultsPerSearch` (type: `integer`):

How many opportunities to take from each keyword, search link or filter-only search. Empty = 100. SAM.gov returns at most 10,000 per search; split by date or NAICS to get more.

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

Hard cap on charged opportunities for the whole run. Empty or 0 = no cap besides the per-search limit.

## `openDeadlineOnly` (type: `boolean`):

Skip notices without a response deadline or whose deadline has passed. Skipped notices are not charged.

## `excludeKeywords` (type: `array`):

Words, one per line. Notices with any of them in the title are skipped and not charged.

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

Apify Proxy is the default and works for SAM.gov.

## Actor input object example

```json
{
  "searchTerms": [
    "software"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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 = {
    "searchTerms": [
        "software"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/sam-gov-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 = {
    "searchTerms": ["software"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/sam-gov-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 '{
  "searchTerms": [
    "software"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/sam-gov-scraper --silent --output-dataset

```

## MCP server setup

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