# Federal Contracts & Spending Scraper (USAspending + SAM.gov) (`studious_allergy_mig/fed-contracts-scraper`) Actor

Scrapes US federal contract and grant award data from USAspending.gov and, optionally, live contract opportunities from SAM.gov, normalized into one consistent schema.

- **URL**: https://apify.com/studious\_allergy\_mig/fed-contracts-scraper.md
- **Developed by:** [Conor G](https://apify.com/studious_allergy_mig) (community)
- **Categories:** Lead generation, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Federal Contracts & Spending Scraper — USAspending.gov + SAM.gov

Pull US federal contract and grant award data straight from
**USAspending.gov**, the government's own public spending database, and —
optionally, if you supply your own free API key — live open contracting
opportunities from **SAM.gov**. Both sources come back in one normalized
schema, so you can build a pipeline once and cover both historical awards
and active solicitations.

### Why this actor

USAspending.gov's award search API is genuinely public: no API key, no
login, no rate-limit registration. It covers every prime federal contract
and grant since fiscal year 2008 — tens of millions of records, growing
every day as new awards post. This actor talks to that API directly (plain
JSON over HTTPS, no browser) and normalizes the response into a schema
built for how govcon buyers actually work: recipient name, agency, NAICS,
PSC, dollar amounts, place of performance, dates.

No actor on the Store currently combines historical USAspending award data
with live SAM.gov opportunity data in one normalized output — this one
does both, in the same run, same schema.

### Data sources

| Source | Auth | What it returns |
|---|---|---|
| **USAspending.gov** `POST /api/v2/search/spending_by_award/` | None — fully public | Historical + active prime contracts and/or grant awards |
| **SAM.gov** `GET /opportunities/v2/search` | Your own free API key (optional) | Live, open contracting opportunities/solicitations |

#### USAspending.gov (primary, always on)

This is the same API that powers usaspending.gov's own search page. No key
required, verified live against the real endpoint before shipping. It
supports filtering by keyword (recipient name), NAICS code, PSC code,
awarding agency, date range, and place of performance, and returns both
contract awards (`award_type_codes: A/B/C/D`) and grant/assistance awards
(`award_type_codes: 02/03/04/05`).

**Pagination note:** USAspending caps simple page-number pagination at
50,000 total results per query (`page * limit`). This actor stays well
under that by capping `maxResults` and using it directly as the page size,
so a single run never approaches the cap.

#### SAM.gov (secondary, opt-in, requires your own key)

SAM.gov's Opportunities API requires a free API key tied to your own
sam.gov account (Account Details → API Key). This actor **never obtains,
stores, or ships a key of its own** — leave `includeSamOpportunities` off
(the default) to skip SAM.gov entirely, or turn it on and paste your own
key into `samApiKey`.

**Honesty note:** the SAM.gov integration is written directly from SAM.gov's
published API documentation
(https://open.gsa.gov/api/get-opportunities-public-api/), but it has not
been exercised against a real key — SAM.gov keys aren't something this
actor can obtain on its own. If you run it and hit an issue, please report
it in the Issues tab so it can be fixed against real response data.

### Input

| Field | Type | Description |
|---|---|---|
| `keyword` | string | Matches recipient/vendor name on USAspending, opportunity title on SAM.gov. |
| `naicsCodes` | array of strings | Filter by NAICS industry code(s), e.g. `"541511"`. |
| `pscCodes` | array of strings | Filter by Product/Service Code(s), e.g. `"D301"`. USAspending only. |
| `awardingAgency` | string | Exact top-tier agency name, e.g. `"Department of Defense"`. |
| `awardCategory` | string | `"contracts"` (default), `"grants"`, or `"both"`. |
| `placeOfPerformanceState` | string | Two-letter state code, e.g. `"VA"`. |
| `dateFrom` / `dateTo` | string (YYYY-MM-DD) | Date range. Defaults to the last 30 days. |
| `maxResults` | integer | Max normalized records returned, combined across sources. Default `100`. |
| `includeSamOpportunities` | boolean | Turn on SAM.gov opportunities. Default `false`. |
| `samApiKey` | string (secret) | Your own free SAM.gov API key. Only used when `includeSamOpportunities` is `true`. |

#### Example — broad default run (USAspending only, fast)

```json
{
  "awardCategory": "contracts",
  "maxResults": 100
}
```

#### Example — targeted search by industry and agency

```json
{
  "keyword": "Booz Allen",
  "naicsCodes": ["541511"],
  "awardingAgency": "Department of Defense",
  "awardCategory": "contracts",
  "dateFrom": "2026-01-01",
  "dateTo": "2026-07-30",
  "maxResults": 200
}
```

#### Example — contracts + grants + SAM.gov opportunities (bring your own key)

```json
{
  "naicsCodes": ["541512"],
  "awardCategory": "both",
  "maxResults": 300,
  "includeSamOpportunities": true,
  "samApiKey": "YOUR-SAM-GOV-API-KEY"
}
```

### Output — normalized schema

Every item, regardless of source, has this shape:

| Field | Type | Notes |
|---|---|---|
| `source` | string | `"usaspending"` or `"sam.gov"` |
| `id` | string | Award ID (USAspending) or notice ID (SAM.gov) |
| `recordType` | string | `"award"` or `"opportunity"` |
| `title` / `description` | string | null | Award description or opportunity title/description |
| `recipientName` | string | null | Vendor/recipient name (USAspending only) |
| `recipientUei` | string | null | Recipient's Unique Entity Identifier, when disclosed |
| `awardingAgency` / `awardingSubAgency` | string | null | Top-tier agency and sub-agency/component |
| `obligatedAmount` | number | null | Dollar amount obligated |
| `potentialAmount` | number | null | Total outlays disbursed to date, where reported |
| `awardType` | string | null | Contract type, `"grant"`, or opportunity type |
| `naicsCode` / `naicsDescription` | string | null | Industry classification |
| `pscCode` / `pscDescription` | string | null | Product/Service Code |
| `placeOfPerformanceState` / `placeOfPerformanceCountry` | string | null | Where the work is performed |
| `startDate` / `endDate` | string | null | Period of performance / response deadline |
| `postedDate` | string | null | Last-modified date (award) or posted date (opportunity) |
| `solicitationNumber` | string | null | Solicitation/RFP number. Always `null` for USAspending awards — this is only populated by the optional SAM.gov opportunities source, which needs your own API key |
| `url` | string | Link to the public record on usaspending.gov or sam.gov |
| `scrapedAt` | string | ISO timestamp of when this actor fetched the record |

Fields the source genuinely doesn't disclose come back as JSON `null` —
never `false` or `0` — so you can tell "not reported" apart from an
actual zero-dollar or negative-flag value.

#### Sample output items (real run, 2026-07-31)

```json
{
  "source": "usaspending",
  "id": "DEAC0494AL85000",
  "recordType": "award",
  "title": null,
  "description": null,
  "recipientName": "LOCKHEED MARTIN CORP",
  "recipientUei": "FYHNA5WC8XD7",
  "awardingAgency": "Department of Energy",
  "awardingSubAgency": "Department of Energy",
  "obligatedAmount": 48063737196.35,
  "potentialAmount": -4166130.71,
  "awardType": "DEFINITIVE CONTRACT",
  "naicsCode": "561210",
  "naicsDescription": "FACILITIES SUPPORT SERVICES",
  "pscCode": "M181",
  "pscDescription": "OPER OF GOVT R&D GOCO FACILITIES",
  "placeOfPerformanceState": "NM",
  "placeOfPerformanceCountry": "UNITED STATES",
  "startDate": "1993-10-15",
  "endDate": "2017-04-30",
  "postedDate": "2026-07-07 17:57:06",
  "solicitationNumber": null,
  "url": "https://www.usaspending.gov/award/CONT_AWD_DEAC0494AL85000_8900_-NONE-_-NONE-",
  "scrapedAt": "2026-07-31T02:37:13.953Z"
}
```

```json
{
  "source": "usaspending",
  "id": "DENA0003525",
  "recordType": "award",
  "title": "IGF::CL,CT::IGF CONTRACT AWARD DE-NA0003525 TO THE NATIONAL TECHNOLOGY&ENGINEERING SOLUTIONS OF SANDIA, LLC (NTESS) FOR THE MANAGEMENT AND OPERATION OF THE DEPARTMENT OF ENERGY, NATIONAL NUCLEAR SECURITY ADMINISTRATION'S SANDIA NATIONAL LABORATORIES (SNL)",
  "description": "IGF::CL,CT::IGF CONTRACT AWARD DE-NA0003525 TO THE NATIONAL TECHNOLOGY&ENGINEERING SOLUTIONS OF SANDIA, LLC (NTESS) FOR THE MANAGEMENT AND OPERATION OF THE DEPARTMENT OF ENERGY, NATIONAL NUCLEAR SECURITY ADMINISTRATION'S SANDIA NATIONAL LABORATORIES (SNL)",
  "recipientName": "NATIONAL TECHNOLOGY & ENGINEERING SOLUTIONS OF SANDIA, LLC",
  "recipientUei": "LUJEPCRRT377",
  "awardingAgency": "Department of Energy",
  "awardingSubAgency": "Department of Energy",
  "obligatedAmount": 42571358867.68,
  "potentialAmount": 25931071186.21,
  "awardType": "DEFINITIVE CONTRACT",
  "naicsCode": "561210",
  "naicsDescription": "FACILITIES SUPPORT SERVICES",
  "pscCode": "M1JZ",
  "pscDescription": "OPERATION OF MISCELLANEOUS BUILDINGS",
  "placeOfPerformanceState": "NM",
  "placeOfPerformanceCountry": "UNITED STATES",
  "startDate": "2017-01-18",
  "endDate": "2027-04-30",
  "postedDate": "2026-07-28 19:06:01",
  "solicitationNumber": null,
  "url": "https://www.usaspending.gov/award/CONT_AWD_DENA0003525_8900_-NONE-_-NONE-",
  "scrapedAt": "2026-07-31T02:37:13.953Z"
}
```

#### Run summary

At the end of a run, a per-source status is written to the default
key-value store under `SOURCE_SUMMARY` — whether each source was
attempted, how many records it returned after dedupe, and a clear message
for anything skipped or failed (e.g. "Skipped: includeSamOpportunities is
true but no samApiKey was provided"). Records are deduped by `source:id`
across both sources. The run only fails (non-zero exit) if **every**
attempted source failed — a SAM.gov hiccup, for example, won't sink a run
that still got USAspending data.

### Use cases

- **Govcon competitive intelligence** — see which vendors are winning
  contracts in a given NAICS/PSC space, at what dollar amounts, from which
  agencies.
- **Pipeline building** — filter by agency, industry, and date range to
  build a target list of active or recently-awarded contracts and
  incumbents.
- **Market sizing** — pull obligated-dollar totals across a NAICS code or
  agency to estimate addressable market size for a given service line.
- **Subcontractor discovery** — cross-reference recipient names and NAICS
  codes to find potential teaming partners already performing similar
  work.

### Pricing

Billed **pay-per-result**: one dataset item = one award or opportunity
record.

### Limitations (please read)

- **SAM.gov requires your own API key and is untested.** The integration
  is written correctly per SAM.gov's public documentation, but has not
  been run against a live key. USAspending.gov, the primary and default
  source, is fully verified live.
- **USAspending's simple pagination caps at 50,000 results per query**
  (`page * limit`). This actor's `maxResults` cap keeps any single run
  well under that, but a very broad, very high-`maxResults` query could
  theoretically approach it — narrow with `naicsCodes`, `awardingAgency`,
  or a tighter date range if you need more than that.
- **`pscCodes` and `placeOfPerformanceState` apply to USAspending only** —
  SAM.gov's public API doesn't expose the exact same filter shape for
  PSC, so that field is passed through to SAM.gov as its own `ccode`
  parameter, not guaranteed to filter identically.
- **`title`/`description` on USAspending awards is often the contract's
  own free-text description**, not a short human title — some agencies
  write these in all caps with internal shorthand (e.g. `"IGF::CL,CT::..."`).
  That's the government's own data, not a normalization choice.
- **Data reflects a single point-in-time snapshot** of each source's
  public feed at the moment the actor ran.

# Actor input Schema

## `keyword` (type: `string`):

Matches against recipient (vendor) name on USAspending, and against opportunity title on SAM.gov. Leave blank to pull broadly across all recipients within the date range.

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

Filter by North American Industry Classification System code(s), e.g. "541511" (Custom Computer Programming Services). Leave empty for all industries.

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

Filter by Product/Service Code(s), e.g. "D301" (IT and Telecom - Facility Operation and Maintenance). USAspending only; leave empty for all.

## `awardingAgency` (type: `string`):

Exact top-tier awarding agency name, e.g. "Department of Defense" or "General Services Administration". Leave blank for all agencies.

## `awardCategory` (type: `string`):

Which USAspending award types to pull: prime contracts, grants/assistance, or both.

## `placeOfPerformanceState` (type: `string`):

Two-letter US state code, e.g. "VA". Leave blank for all states.

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

Start of the date range (YYYY-MM-DD). USAspending applies this to last-modified/action date; SAM.gov applies it to posted date. Defaults to 30 days before today.

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

End of the date range (YYYY-MM-DD). Defaults to today.

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

Maximum number of normalized records to return, combined across both sources. Kept modest by default so the default run finishes quickly.

## `includeSamOpportunities` (type: `boolean`):

When enabled (and samApiKey is provided), also fetches live contract opportunities from SAM.gov. Off by default since it requires your own free API key.

## `samApiKey` (type: `string`):

Your own free SAM.gov API key (get one at sam.gov under Account Details -> API Key). Only used when includeSamOpportunities is true. Never required for USAspending.gov data.

## Actor input object example

```json
{
  "awardCategory": "contracts",
  "maxResults": 100,
  "includeSamOpportunities": false
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("studious_allergy_mig/fed-contracts-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("studious_allergy_mig/fed-contracts-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call studious_allergy_mig/fed-contracts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studious_allergy_mig/fed-contracts-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/mi2y12rH4ioNTZoS7/builds/9lFw1h1nFu0EuyR50/openapi.json
