SAM.gov Federal Contracts Scraper + Monitor — No Login, $3/1k avatar

SAM.gov Federal Contracts Scraper + Monitor — No Login, $3/1k

Pricing

from $3.00 / 1,000 results

Go to Apify Store
SAM.gov Federal Contracts Scraper + Monitor — No Login, $3/1k

SAM.gov Federal Contracts Scraper + Monitor — No Login, $3/1k

Scrape SAM.gov federal contract opportunities: RFPs, solicitations, sources sought, awards. Filter by keyword, NAICS, PSC, set-aside, notice type, agency, state, posted and due dates. Contracting officer contacts, full text. No login or cookies. MCP-ready for AI agents. $3 per 1,000 records.

Pricing

from $3.00 / 1,000 results

Rating

0.0

(0)

Developer

Fortuitous Pirate

Fortuitous Pirate

Maintained by Community

Actor stats

7

Bookmarked

130

Total users

23

Monthly active users

2 days ago

Last modified

Share

SAM.gov Federal Contracts Scraper + Monitor

Pull federal contract opportunities from SAM.gov (solicitations, RFPs, RFQs, sources sought, presolicitations, special notices and award notices) into a clean spreadsheet or JSON feed. Each row has the contracting officer's name, email and phone, NAICS and PSC codes, set-aside, place of performance, response deadline (with days left), the full description text, direct download links for every attachment (SOWs, PWS, pricing sheets, amendments) and, on award notices, the winner's name, UEI, CAGE code and amount.

No SAM.gov account, no API key, no login, no proxy. Run it with no input and you get the 100 most recently updated active notices.

Four ways to use it, all in one actor:

ModeWhat you give itWhat you get
Searchkeywords and/or filters (NAICS, PSC, set-aside, notice type, agency, state, date windows)every matching notice, newest first
Lookupsolicitation numbers, notice IDs or sam.gov/opp/.../view URLsthose notices, active or archived, with every amendment
Bulkseveral keywords, or a CSV / Google Sheet URL (listUrl) mixing keywords, solicitation numbers and URLsone merged, de-duplicated dataset
Monitorthe same filters plus onlyNew: true, on an Apify Scheduleonly notices that are new or updated since the last run, with an optional webhook

Who uses it

  • Government contractors and BD teams: a daily list of new bids in your NAICS/PSC codes and set-aside, already filtered to deadlines you can still meet.
  • Capture managers (bid/no-bid): every notice comes with its documents, contacts, days-to-deadline and due date in one row, so you can triage 50 opportunities without clicking through SAM.gov.
  • Proposal teams: download the solicitation package (SOW, PWS, pricing template, Q&A, amendments) straight into the run's storage with downloadAttachments.
  • Small businesses (8(a), HUBZone, SDVOSB, WOSB, VOSB): filter straight to the set-asides you qualify for.
  • Subcontractors, teaming partners and GovCon lead generation: award notices with the winner's name, UEI, CAGE code and location, and contracting officer contacts by agency and office, exported to your CRM.
  • Market research and AI agents: structured, LLM-ready JSON of what the government is buying, who is buying it and who won.

What you get per notice

FieldExampleNotes
opportunityId, solicitationNumber, parentNoticeId07ffa9495d33..., N0016426R3003parentNoticeId links an amendment to the original notice
title, type, typeCode, statusPresolicitation, p, Published
postedDate, modifiedDate, responseDeadline, responseTimeZone, daysUntilDeadline2026-10-30T20:00:00+00:00, 9daysUntilDeadline is computed at scrape time; negative = already closed
isActive, isCanceled, archiveDate, archiveTypetrue, false, 2026-11-30
agencyName, subAgencyName, officeName, officeCode, officeAddress, organizationPathDEPT OF DEFENSE > DEPT OF THE NAVY > NAVSEA > ... > NSWC CRANEfull federal hierarchy
naicsCode, naicsCodes, pscCode541330, R425
setAsideType, setAsideDescriptionSBA, Total Small Business Set-Aside (FAR 19.5)
placeOfPerformance{ city, state, stateCode, zip, country, streetAddress }
description, descriptionTextSAM.gov summary (HTML) and the full notice text as plain text
contacts[], primaryContactName, primaryContactEmail, primaryContactPhoneLogan Kelley, logan.b.kelley.civ@us.navy.milevery point of contact, plus the primary one as flat columns for CSV
award{ amount, date, number, awardee, awardeeUei, awardeeCageCode, awardeeCity, awardeeState, awardeeZip, awardeeCountry }award notices only, otherwise null
attachments[], attachmentCountfilename, mimeType, size, type, accessLevel, postedDate, downloadUrl (+ storedKey, storedUrl when downloaded)type: "link" entries point off-site (e.g. DIBBS, PIEE)
samGovLink, scrapedAthttps://sam.gov/opp/<id>/view
matchedByN4008426R1026lookups and multi-keyword runs: which number / keyword produced the row
changeType, firstSeenAt, matchedKeywords, monitorIdnew / updatedmonitor mode only

Filters

Every filter is passed to SAM.gov's own search, so results match what you would see on sam.gov. All filters combine (AND). Multiple values inside one filter are OR-ed: ["VA", "MD"] means Virginia or Maryland.

InputWhat it doesExample
keywords + keywordModeFree-text search. Any word (default), all words, or exact phrase. One search per line; keywordList is the array form for API users"cybersecurity", EXACT
listUrlCSV / TSV / text file or Google Sheet (shared as "anyone with the link"). First column; rows are detected as keyword, solicitation number or notice URLhttps://docs.google.com/spreadsheets/d/.../edit
naicsCodesNAICS codes. Prefixes work: 5415 matches 541511, 541512, ...["541511", "541512"]
pscCodesProduct Service Codes (classification codes)["DA10", "R425", "S201"]
setAsideTypesSet-aside codes["SBA", "8A", "SDVOSBC", "WOSB", "HZC", "VSA"]
opportunityTypesNotice types, by code or name["Solicitation", "Sources Sought", "k"]
agenciesDepartment, agency or office by name, acronym or SAM.gov org ID["Department of Veterans Affairs", "DEPT OF THE NAVY"]
statesPlace-of-performance state codes["VA", "MD", "DC"]
status / activeOnlyactive (default), inactive (archived only) or all"all" for award history
postedWithinDays / postedFrom / postedToPosted (or last updated) window. Dates or relative values"7 days", "2026-10-01"
responseDeadlineFrom / responseDeadlineToOffer due-date window. Relative values count forward from today"today" to "30 days"
solicitationNumbersLookup by solicitation number (active or archived)["N4008426R1026", "36C26026Q0576"]
noticeIdsLookup by notice ID or https://sam.gov/opp/<id>/view URL
maxOpportunitiesStop after this many rows (default 100)500
sortByRecently modified (default) or relevance-relevance
fetchDetailsFull details (contacts, NAICS/PSC, set-aside, full text, award). Off = faster listing-only pulltrue
includeDescriptionOff = leave the description fields empty for slim CSV exportsfalse
includeAttachmentUrlsAttachment list with download URLstrue
downloadAttachments + maxAttachmentSizeMb + maxAttachmentDownloadsAlso save the public files into the run's key-value storetrue, 25, 200
onlyNew + monitorId + firstRunMode + webhookUrlMonitor mode (see below)true, "it-services-va", "baseline"
proxyConfigurationOptional. SAM.gov answers Apify's cloud IPs directly, so none is used by default

Date fields accept YYYY-MM-DD, MM/DD/YYYY, today, or relative values like 7 days, 2 weeks, 3 months (counted back for posted dates, forward for deadlines; -3 days / +3 days force a direction). Input names used by other SAM.gov tools are accepted as aliases: noticeTypes, setAsideCodes, maxResults, fetchFullDetails, includeAttachments, responseDueFrom/To, modifiedFrom/To, lookbackDays.

Input examples

Small-business IT bids due in the next 30 days

{
"naicsCodes": ["541511", "541512", "541519"],
"setAsideTypes": ["SBA", "8A"],
"opportunityTypes": ["Solicitation", "Combined Synopsis/Solicitation"],
"responseDeadlineFrom": "today",
"responseDeadlineTo": "30 days",
"maxOpportunities": 200
}

Engineering support (PSC R425) still open, with the solicitation package downloaded

{
"pscCodes": ["R425", "D302"],
"responseDeadlineFrom": "today",
"responseDeadlineTo": "30 days",
"downloadAttachments": true,
"maxAttachmentSizeMb": 25
}

SDVOSB opportunities at the VA, with contacts

{
"agencies": ["Department of Veterans Affairs"],
"setAsideTypes": ["SDVOSBC", "VSA"],
"postedWithinDays": 14
}

Who won? Janitorial award notices from last month, archived included

{
"pscCodes": ["S201"],
"opportunityTypes": ["Award Notice"],
"status": "all",
"postedFrom": "2026-09-01",
"postedTo": "2026-09-30"
}

Bulk: several keyword searches in one run, merged and de-duplicated

{
"keywords": "zero trust\nSOC as a service\nvulnerability assessment",
"opportunityTypes": ["o", "k", "r"],
"maxOpportunities": 300
}

Bulk from a sheet: { "listUrl": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0" } reads the first column; keywords, solicitation numbers and sam.gov URLs can be mixed in one list.

Track the solicitations you are bidding on (every amendment, active or archived)

{
"solicitationNumbers": ["N4008426R1026", "36C26026Q1017", "W912C326CA008"]
}

Monitor: daily feed of only new or updated notices, posted to Slack / Make / n8n

{
"naicsCodes": ["236220", "238210"],
"states": ["TX", "OK"],
"opportunityTypes": ["o", "k", "p"],
"postedWithinDays": 3,
"onlyNew": true,
"monitorId": "construction-tx",
"firstRunMode": "baseline",
"webhookUrl": "https://hooks.slack.com/services/..."
}

Monitor mode

Set onlyNew: true and put the actor on an Apify Schedule. The actor remembers every notice it has returned in a key-value store named samgov-monitor-<hash of monitorId> in your account, and on each later run returns only:

  • changeType: "new": a notice it has not returned before, with firstSeenAt;
  • changeType: "updated": a notice whose modifiedDate moved since it was last returned (amendment, deadline change, Q&A posted).

firstRunMode decides what the very first run does: emitAll (default) returns everything that currently matches, baseline records it silently so the next run reports only changes. Notices beyond maxOpportunities stay unseen and come out on the next run, so nothing is lost. Use a different monitorId per watchlist to run several profiles side by side. Monitor mode also works with solicitationNumbers: you get a row only when one of your tracked bids is amended.

If webhookUrl is set, every run POSTs a JSON summary { monitorId, runId, newCount, updatedCount, itemsPushed, opportunities[first 50] } to it (Slack incoming webhooks, Zapier, Make, n8n or your own endpoint).

Migrating from the retired SAM.gov Opportunity Monitor actor: the store name is identical, so the same monitorId keeps your seen-state; noticeTypes, setAsides and lookbackDays work as-is and the keywords array becomes keywordList. Output: noticeId is opportunityId, samUrl is samGovLink, agency / subAgency / office are agencyName / subAgencyName / officeName.

Attachment downloads

includeAttachmentUrls (default on) lists every attachment with a direct downloadUrl that opens in any browser. With downloadAttachments: true the actor also saves each public file into the run's default key-value store and adds storedKey and storedUrl to the attachment, so Make/Zapier/n8n can pick the file up or you can fetch it with the Apify API. Files above maxAttachmentSizeMb (default 25), external links and controlled (login-only) files are listed with a skipReason instead. maxAttachmentDownloads (default 200) caps the number of files per run. Downloads are included in the row price; there is no extra charge per file.

A downloaded file gets, for example, "storedKey": "66becf06-Performance_Work_Statement_(PWS)_-_MARFORRES_FDET_Engineer_Support_Services_Oct2026.docx" and "storedUrl": "https://api.apify.com/v2/key-value-stores/OhDstkbmAkDoki5PR/records/66becf06-Performance_Work_Statement_%28PWS%29_-_MARFORRES_FDET_Engineer_Support_Services_Oct2026.docx?signature=..." (a signed link that works without a token).

Output

One row per notice. A real row from a run with pscCodes: ["R425","D302"], responseDeadlineFrom: "today", responseDeadlineTo: "30 days" (description trimmed):

{
"opportunityId": "07ffa9495d334260ab03488c5b5ee856",
"solicitationNumber": "N0016426R3003_DRAFT",
"title": "Draft RFP for DRPM RAS ME RAS 1.0 and MCM RAS 2.0 Professional Support Services",
"description": "THIS IS A DRAFT SEAPORT-NxG SOLICITATION TO REQUEST INPUT FROM INDUSTRY - THE GOVERNMENT MAY NOT RES ...",
"descriptionText": "THIS IS A DRAFT SEAPORT-NxG SOLICITATION TO REQUEST INPUT FROM INDUSTRY - THE GOVERNMENT MAY NOT RESPOND TO ALL QUESTIONS POSTED BUT WILL CONSIDER EACH FOR FINAL SOLICITATION. This Advance Notice/Draft is issued by Naval ...",
"type": "Presolicitation",
"typeCode": "p",
"status": "Published",
"postedDate": "2026-10-21T14:54:46+00:00",
"modifiedDate": "2026-10-21T14:54:46+00:00",
"responseDeadline": "2026-10-30T20:00:00+00:00",
"responseTimeZone": "America/New_York",
"daysUntilDeadline": 9,
"isActive": true,
"isCanceled": false,
"agencyName": "DEPT OF DEFENSE",
"subAgencyName": "DEPT OF THE NAVY",
"officeName": "NSWC CRANE",
"officeCode": "N00164",
"officeAddress": { "streetAddress": "WARFARE CENTER", "streetAddress2": "300 HIGHWAY 361", "city": "CRANE", "state": "IN", "zip": "47522-5001", "country": "USA" },
"organizationPath": "DEPT OF DEFENSE > DEPT OF THE NAVY > NAVSEA > NAVSEA WARFARE CENTER > NSWC CRANE",
"parentNoticeId": "f5771a27a0d4424f9e8e3ce9b4a884ef",
"naicsCode": "541330",
"naicsCodes": ["541330"],
"pscCode": "R425",
"setAsideType": "SBA",
"setAsideDescription": "Total Small Business Set-Aside (FAR 19.5)",
"archiveDate": "2026-11-30",
"archiveType": "autocustom",
"placeOfPerformance": { "streetAddress": "Washington Navy yard, DC 20376", "city": null, "state": null, "stateCode": null, "zip": "20376", "country": null, "countryCode": null },
"contacts": [{ "name": "Logan Kelley", "email": "logan.b.kelley.civ@us.navy.mil", "phone": "", "fax": "", "title": null, "type": "primary" }],
"primaryContactName": "Logan Kelley",
"primaryContactEmail": "logan.b.kelley.civ@us.navy.mil",
"primaryContactPhone": "",
"award": null,
"attachmentCount": 4,
"attachments": [
{
"filename": "PIEE Solicitation Module Link for N0016426R3003_DRAFT",
"mimeType": "",
"size": 0,
"resourceId": "2366e246dbe84ec1a4c483c775cfb005",
"accessLevel": "public",
"postedDate": "2026-10-16T11:51:56.747+00:00",
"type": "link",
"description": "PIEE Solicitation Module Link for N0016426R3003_DRAFT",
"exportControlled": false,
"downloadUrl": "https://piee.eb.mil/sol/xhtml/unauth/search/oppMgmtLink.xhtml?noticeId=N0016426R3003_DRAFT&noticeType=Presolicitation"
}
],
"samGovLink": "https://sam.gov/opp/07ffa9495d334260ab03488c5b5ee856/view",
"scrapedAt": "2026-10-21T16:10:27+00:00"
}

Award notices fill award, for example { "amount": "114511.00", "date": "2026-10-21", "number": "15BGCS27D10900001", "awardee": "Young Veterans Electrodiagnostic Ser., PLLC", "awardeeUei": "Q2HBKZ3BPNG7", "awardeeCageCode": "9XHF5", "awardeeCity": "Versailles", "awardeeState": "KY", "awardeeZip": "40383", "awardeeCountry": "UNITED STATES" }.

The dataset has three ready-made table views: Opportunities (triage columns incl. days left), Contacts (agency, office, contracting officer, email, phone) and Monitor changes.

Each run also saves a summary in the key-value store record OUTPUT: rows returned, total matches on SAM.gov per keyword, the agencies your names were matched to, files downloaded, monitor counts, and any notices that failed. If something breaks mid-run, every row already collected stays in the dataset and the summary says PARTIAL.

Pricing

Pay per result: $3 per 1,000 notices plus a $0.005 start fee per run (per GB of memory; the actor runs at 1 GB). Contacts, full text, attachment URLs, attachment downloads and the monitor are all included in the row price; there are no add-on events. Monitor runs only pay for the new or updated rows they return, so a daily watchlist that finds 5 new bids a day costs about $0.60 a month (150 rows + 30 start fees).

Examples: a daily feed of 50 notices = $0.155 per run; a 2,000-row market pull = $6.

Limits and tips

  • SAM.gov caps a single query at 10,000 notices. Split larger pulls into date windows with postedFrom / postedTo or into several keywords.
  • "Posted" dates: SAM.gov's search index dates a notice by its latest publication, so an amended notice counts as recently posted. That is usually what a bid feed wants; use parentNoticeId to group amendments with their original.
  • Faster runs: turn off fetchDetails and includeAttachmentUrls when you only need titles, numbers, dates and agencies (one request per page instead of three per notice).
  • Agency names: check the log or the OUTPUT summary to see which SAM.gov organization each name matched. If a name is ambiguous, use the numeric organization ID it shows.
  • Controlled attachments: files with accessLevel other than public need a SAM.gov login; the actor lists them but cannot download them.
  • Notice IDs vs solicitation numbers: a solicitation number can have several notices (original, amendments, award). solicitationNumbers returns all of them; noticeIds returns exactly one.
  • Timeouts: the default run timeout is 5 minutes. Raise it in the run options for big pulls with details and attachment downloads.

Integrations and AI agents

Results export as JSON, CSV, Excel, XML or HTML from the dataset tab, or through the Apify API, webhooks and SDKs.

from apify_client import ApifyClient
client = ApifyClient("MY_APIFY_TOKEN")
run = client.actor("fortuitous_pirate/sam-gov-scraper").call(run_input={
"naicsCodes": ["541511", "541512"],
"setAsideTypes": ["SBA", "8A"],
"responseDeadlineFrom": "today",
"maxOpportunities": 200,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["solicitationNumber"], row["daysUntilDeadline"], row["primaryContactEmail"])

The JavaScript client (apify-client) works the same way: client.actor('fortuitous_pirate/sam-gov-scraper').call(input) then client.dataset(run.defaultDatasetId).listItems().

  • Schedules: run it hourly or daily; combine with onlyNew so each run only returns changes.
  • Webhooks: Apify run webhooks fire when a run finishes; webhookUrl additionally posts the new rows themselves.
  • Make, Zapier, n8n: use the Apify app to start the actor and read the dataset, or point webhookUrl at a scenario trigger.
  • Google Sheets, Slack, Airbyte, GitHub: available through Apify integrations.
  • MCP / AI agents: the output is clean JSON that assistants can use through the Apify MCP server. Ask: "find open SDVOSB construction solicitations in Texas due in the next three weeks and list the contracting officers".

FAQ

Do I need a SAM.gov account or API key? No. The actor reads the same public data the sam.gov website shows to anonymous visitors.

Can I get archived and awarded notices? Yes. Set status to all or inactive, or look them up directly with solicitationNumbers / noticeIds.

Are the attachment files downloaded? The URLs are always included. Set downloadAttachments: true to also store the public files in the run's key-value store (storedUrl on each attachment).

How do I get only new opportunities each day? onlyNew: true plus a schedule. The first run returns (or, with firstRunMode: "baseline", silently records) everything that currently matches; later runs return only new and updated notices.

Why does a notice show up again in monitor mode? Its modifiedDate changed (amendment, Q&A or deadline change); the row says changeType: "updated". A run whose filters match nothing finishes successfully with an empty dataset.

Is this data legal to use? SAM.gov contract opportunity data is published by the U.S. government for public use. Notices name government points of contact; if you are in the EU or UK, you are responsible for having a lawful basis for processing personal data.

This actor is an independent tool. It is not affiliated with or endorsed by the U.S. General Services Administration (GSA) or SAM.gov. Feature requests and problems: open an issue on the Issues tab.