# SAM.gov Opportunities Scraper - Federal Solicitations

Search SAM.gov contract opportunities via the official API. Title and posted-date filters. Requires a free Public API Key from SAM.gov Account Details. Source errors stay in the run summary.

Canonical product page: https://mayd-it.com/data-tools/actors/sam-gov-opportunities-scraper/
Public Actor: https://apify.com/maydit/sam-gov-opportunities-scraper

## Example input

```json
{
  "keyword": "software",
  "maxResults": 10,
  "maxRunSeconds": 240,
  "softFail": false
}
```

## Full guide

![Find notices in the official source — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/sam-gov-opportunities-scraper-eb50be1b2af9.png?signature=1A0Nx8zl2NZv6LiotPkMI)

## Find notices in the official source

For federal procurement research: search contract opportunity notices through the official SAM.gov API and export their identifiers, titles, departments and source links. A SAM.gov-issued Public API Key is required.

[Open this Actor in Console](https://console.apify.com/actors/bo8zSAWddsTuzk5H8/input) · [First run](#try-this-actor) · [Results](#result-preview) · [Cost](#usage-and-pricing) · [Full guide](#full-guide)

## Try this Actor

**Bring your API credentials first.** This Actor requires your own source API key. Enter it in the secret field in Console; the setup requirements are in the guide below.

- **First run:** Enter your own key in the secret **SAM.gov Public API Key** input, then try the existing **software** Console sample. Review the posted-date window and 20-opportunity default cap before running.
- **Read the results:** Open the default Dataset for notice rows and **SUMMARY** for source status. The official notice link is the place to review the opportunity's complete requirements.
- **Keep in mind:** An api.data.gov key is not a SAM.gov key. Missing credentials or upstream failures are not evidence that no opportunities exist. If you enable soft-fail mode, a successful run status can still accompany a source failure.

## Result preview

The dataset view highlights these columns:

- **Notice ID** · `noticeId`
- **Opportunity title** · `title`
- **Solicitation number** · `solicitationNumber`
- **Department** · `department`
- **Posted date** · `postedDate`
- **Notice type** · `type`

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

## Usage and pricing

Base result rate on the FREE tier: **$2 per 1,000 results**. The [Pricing tab](https://apify.com/maydit/sam-gov-opportunities-scraper/pricing) shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.

---

## Full guide

> Search **SAM.gov** contract opportunities through the official **Get Opportunities Public API**. A **free** Public API Key is required from **SAM.gov Account Details** (api.data.gov signup keys are not accepted).

### What it does

Queries `https://api.sam.gov/opportunities/v2/search` and returns one row per notice: notice id, title, solicitation number, department path, posted date, type, and UI link.

### What YOU must register (free)

| Item | Where | How to wire on Apify |
|---|---|---|
| **SAM.gov Public API Key** | [SAM.gov Account Details](https://sam.gov/) -> Public API Key (re-enter password). An api.data.gov signup key is not a SAM-issued key. | `input.apiKey` (secret). Env `SAM_API_KEY` applies only to runs started by the Actor's owner. |

**There is no keyless fallback in this Actor.** The [official API requires a SAM.gov Public API Key](https://open.gsa.gov/api/get-opportunities-public-api/). Daily quotas depend on account roles. This Actor uses only the official API.

The deprecated environment-variable alias `DATA_GOV_API_KEY` remains supported for existing integrations, but it must contain an actual SAM-issued Public API Key. Prefer `SAM_API_KEY` for new setups.

### Missing credentials and source failures

By default, missing credentials or a complete source failure fails the run with actionable details in `SUMMARY`. No diagnostic dataset row is emitted. For workflows that require successful termination, explicitly set `softFail: true`: the run writes zero dataset rows and `SUMMARY.status` is `blocked`, `source_failed`, or `time_limit`. Check this status before treating the run as successful data collection.

SAM documents HTTP 404 as no data. An empty gateway 404 alone cannot establish an invalid key or a valid empty match; the Actor reports it as a source failure and asks you to check the key and date/title filters. It does not turn an ambiguous failure into an empty success.

### Input

- **apiKey** (secret) - required for live opportunities
- **keyword** - default `software`
- **postedFrom / postedTo** - valid `MM/DD/YYYY` dates in chronological order, at most one calendar year apart; defaults are 30 days before today and today. A February 29 anniversary is February 28 in a non-leap year. Invalid date inputs fail before any request, including when `softFail: true`.
- **maxResults** / **maxRunSeconds** / **softFail**

### Limitations

- Official API only - no HTML scraping.
- Daily request caps depend on your account role. Pages contain up to 100 rows to reduce request use; the Actor stops at `maxResults`.
### Result accounting

Only real source records are written to the dataset. `SUMMARY.total` counts saved rows. A dataset spending cap stops further writes and sets `SUMMARY.stoppedOnChargeLimit` and `SUMMARY.incomplete`. Source failures and time limits are reported in the summary; they do not generate substitute result rows.

## Help with your run

Open the **Issues** tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

[Explore more Mayd-It Actors](https://apify.com/maydit)

## Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.
