SAM.gov Federal Contract Opportunities & Attachments
Pricing
from $2.50 / 1,000 contract notices
SAM.gov Federal Contract Opportunities & Attachments
Scrape public U.S. federal contract opportunities from SAM.gov: solicitations, awards, sources sought, agency and contact details, the full solicitation text, and the solicitation documents themselves. No API key, no login, no session cookies.
Pricing
from $2.50 / 1,000 contract notices
Rating
0.0
(0)
Developer
Oswaldo Carabano
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
35 minutes ago
Last modified
Categories
Share
Every U.S. federal contract opportunity, as clean JSON — including the solicitation documents.
No API key. No login. No session cookies. You paste nothing and configure nothing before your first run. Hit Start with the defaults and you get contract notices.
Why that first line matters
Several SAM.gov scrapers ask you to bring your own api.sam.gov API key. That means
registering with SAM.gov, waiting for approval, and then owning the problem when the
key's quota runs out or it expires — the actor stops working because of something you
did correctly.
This one talks to the same public endpoint the SAM.gov search page itself uses. There is nothing to register and nothing to renew.
What you get
One row per notice, 62 fields, snake_case, null where a value is genuinely absent —
never a missing key, so row.award_amount is safe on every row.
| Identity | notice_id, solicitation_number, title, notice_type, url |
| Lifecycle | is_active, is_canceled, published_at, modified_at, archive_at, modification_count |
| Deadline | response_due_local, response_due_utc, response_due_precision, response_timezone |
| Classification | naics_code, naics_title, psc_code, psc_title, set_aside_code, set_aside |
| Agency | agency_name, agency_id, agency_code, plus the full agency_hierarchy |
| Contact | contact_name, contact_email, contact_phone, plus contacts_all |
| Place of performance | pop_country, pop_state, pop_city, pop_zip |
| Award | award_number, award_date, award_amount, awardee_name, awardee_uei, awardee_cage_code |
| The solicitation text | description_html and description_text |
| Documents | attachments[] with name, size_bytes, mime_type and a stable url |
Fill rates, measured — not estimated
On a sample of 13,434 notices across five days spread over ten months:
100.0 % notice_id, title, notice_type, published_at, modified_at, archive_at99.6 % contact_name 99.2 % contact_email99.5 % solicitation_number 99.4 % agency_name97.8 % psc_code 96.1 % naics_code84.3 % description_html 75.2 % response_due_*46.1 % set_aside_code 32.7 % contact_phone
Award fields sit at ~23% of all notices — but that is because most notices are not
awards. Within award notices (notice_type_code = "a", about a quarter of the index),
award_amount and awardee_name are effectively always present.
We do not list a field here unless we have measured it.
The documents, and the honest number
Turn on "Also fetch solicitation documents" and every notice gains an
attachments[] array. There are two kinds and the row tells you which:
kind | What it is | Fields |
|---|---|---|
file | The real document — the PDF, the SOW, the price matrix, the amendment | name, size_bytes, mime_type, url |
link | A URL to the agency's own portal, when that is all the agency posted | name (its label), url |
Measured on a stratified sample of 829 notices across 70 agency × notice-type cells, covering 96.7% of the active index:
36.7% ± 4.6 of active notices carry at least one downloadable file, and the rate
varies a lot by notice type:
| Notice type | Share of index | Carries a file |
|---|---|---|
r Sources Sought | 7% | 60% |
s Special Notice | 6% | 56% |
u Justification | 1% | 52% |
o Solicitation | 18% | 49% |
k Combined Synopsis/Solicitation | 34% | 39% |
p Presolicitation | 8% | 32% |
a Award Notice | 24% | 14% |
And it varies even more by agency, which is the part worth knowing before you plan a run:
| Agency | Solicitations carrying a file |
|---|---|
| Veterans Affairs | ~100% |
| General Services Administration | ~90% |
| Department of Defense (63% of the whole index) | ~28% |
DoD posts a large share of its documents on its own portals — you get a link to
neco.navy.mil instead of the file. That is why the DoD number drags the overall rate
down, and why filtering by agency changes what you get more than filtering by type does.
Average file size: 1.5 MB.
file_count and link_count are separate fields on purpose. A link to
neco.navy.mil is not the solicitation, and we are not going to count it as one.
Downloading a document
The url we give you is stable and unsigned — it keeps working long after the run
finishes, and you can store it. It is a 303 redirect to a short-lived signed S3 link,
so your client has to follow redirects and finish the download promptly:
$curl -L -o sow.pdf "<attachments[0].url>" # -L is required
Verified: the bytes you get back match the size_bytes we report, exactly.
What we do not return
Attachments that SAM.gov marks as restricted, export-controlled, deleted, or non-public are not returned at all — not even their URL, because publishing the URL to a controlled document is publishing the document. This is checked against six separate flags with an allowlist, not a blocklist.
The deadline field, and why there are three of them
This is the one place where being precise costs an extra column, and it is worth it.
responseDate from SAM.gov is not always a real instant. Measured on 1,566 notices with
a deadline:
response_due_precision | Share | What it means |
|---|---|---|
instant | 61.0% | Real offset. response_due_utc is a true UTC instant you can convert |
date_only | 38.8% | The notice says "due on the 25th" with no time. response_due_utc is null |
local_naive | 0.2% | A wall-clock time with no zone. response_due_utc is null |
SAM.gov stamps midnight UTC on the date_only ones. We do not pass that through as an
instant, because it would look like a precise deadline and it is not one. Use
response_due_local for display and response_due_utc only when
response_due_precision is instant.
Also available
Exclusion records (federal debarment list, 168,206 records) go to a separate
exclusions dataset. Set "Maximum exclusion records" above 0.
⚠️ We deliberately do not offer a "is this vendor debarred?" lookup. 63% of the list is individuals and only ~20% of those carry a UEI, so matching by name alone manufactures false positives — and a false positive here tells you a real person is debarred when they are not.
Coverage
5,591,183 notices in the index, back to 200049,702 active right now (the default: turn off "Only active notices" for the archive)~2,500 published per calendar day
Sweeping is done by publication date, one calendar day per request, newest first. Rows
are deduplicated by notice_id before they are delivered, so you are never charged
for a duplicate.
Pricing
| Event | Price |
|---|---|
| Actor start | $0.00001 |
| Notice delivered | $0.0025 |
| Attachment listed | $0.0005 |
| Exclusion record | $0.0005 |
You are not charged for error rows, and you are not charged for duplicates. Charging happens after a row is delivered, never in a batch at the end — so a run that stops early has charged you for exactly what you received.
Notes
- Runs are deliberately polite: 4 concurrent requests with a 1-second delay. SAM.gov is public infrastructure paid for by taxpayers, and we are not going to hammer it because we can.
robots.txtis fetched on every single run and enforced in the request layer. The actor never requests a disallowed path.- Notices are immutable once published: a SAM.gov amendment creates a new notice that
links back to the previous one. That is why cached rows stay correct, and why
from_cache,fetched_atanddata_age_hoursare on every row. - U.S. Government works are not subject to copyright (17 U.S.C. § 105), and FAR Part 5 requires agencies to publish these notices so that businesses can find them.
Data removal: https://samgov.actorstack.dev · privacy@actorstack.dev